Mercurial > hg > openjdk > jigsaw > langtools
changeset 1842:f9e6d666883e default tip
Merge
line wrap: on
line diff
--- a/.hgtags Thu Apr 25 09:24:40 2013 -0700 +++ b/.hgtags Tue May 07 17:14:17 2013 -0700 @@ -30,6 +30,7 @@ dbdeb4a7581b2a8699644b91cae6793cb01953f7 jdk7-b53 197a7f881937d406a01214aa9ded49c073f7d380 jdk7-b54 7394a8694cedea574c7dbd38de87f4cbe0e27b8a jdk7-b55 +9359f5d705289c8680748d11bc80978edc957ba1 j1-2009-demo 825f23a4f262eb06cfc94406140f3bfecb17ffe8 jdk7-b56 4030cc469205bbd517ca629fb170afb81760bbc5 jdk7-b57 5bcac54d408b436d2364925ee7947b5609e07962 jdk7-b58 @@ -68,6 +69,11 @@ 97b6fa97b8ddb3a49394011c2a0ec5d6535e594c jdk7-b91 98cba5876cb50fa3c58a313ddd668f5014ff14f6 jdk7-b92 683cd1f6bc4b562b0ddf29d5f80f05c2123b76b0 jdk7-b93 +51b53bc20417668e7e9a013238d3079f3df1800f jigsaw-b01 +e2879c758bac08ca28218f781b8baccb8e07256f jigsaw-b03 +1d3e1ab9bfccc6c297ee5bb4f2231dbb4c88be5a jigsaw-b04 +71bc65043b3579ad26a3464e1a6dd1cd37c87cf4 jigsaw-b05 +2c30424a82834d0b7ad45adb7de4404e1d43e9f7 jigsaw-b06 bb3d7c75a56df0c00246072b996fad1858a771a1 jdk7-b94 752bb790fc2d6df91e91d84420c9c87136eb81eb jdk7-b95 89cd267c216751bdacf8629bb07a40c0950fc4f2 jdk7-b96
--- a/.jcheck/conf Thu Apr 25 09:24:40 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -project=jdk8
--- a/make/build.properties Thu Apr 25 09:24:40 2013 -0700 +++ b/make/build.properties Tue May 07 17:14:17 2013 -0700 @@ -44,10 +44,13 @@ target.java = ${target.java.home}/bin/java # Version info -- override as needed -jdk.version = 1.7.0 +jdk.version = 1.8.0 build.number = b00 milestone = internal +# version for modules +module.version = 8-ea + # FIXME -- these need to match the standard values # If we include date in full.version (ie for developer build) # we will need to make sure the build is idempotent (i.e. @@ -68,7 +71,12 @@ # set the following to -version to verify the versions of javac being used javac.version.opt = # in time, there should be no exceptions to -Xlint:all -javac.lint.opts = -Xlint:all -Werror +# +# NOTE: rawtypes warnings temporarily disabled because of warnings generated by +# use of diamond operator in generated stubs. +# +#javac.lint.opts = -Xlint:all -Werror +javac.lint.opts = -Xlint:all,-rawtypes,-options -Werror # options for the <javadoc> task for javac #javadoc.jls3.url=http://java.sun.com/docs/books/jls/ @@ -124,6 +132,33 @@ javac.tests = \ tools/javac +# Additional modules for langtools public API + +javax.tools.module.name = jdk.compiler +javax.tools.module.includes = \ + javax/tools/** \ + javax/lang/model/** \ + javax/annotation/processing/** + +# + +langtools.module.name = jdk.devtools +langtools.module.includes = \ + com/sun/source/** \ + com/sun/tools/javac/** \ + com/sun/tools/javah/** \ + com/sun/tools/javap/** \ + com/sun/tools/classfile/** \ + com/sun/javadoc/** \ + com/sun/tools/doclets/** \ + com/sun/tools/javadoc/** + +# + +mirror.module.name = jdk.mirror +mirror.module.includes = \ + com/sun/mirror/** + # javadoc.includes = \ @@ -141,6 +176,8 @@ doclets.tests = \ com/sun/javadoc/ +# doclets are included in javadoc module + # javah.includes = \ @@ -174,25 +211,15 @@ # The API can be provided by using a suitable boot.java.home # or by setting import.jdk require.latest.jdk.files = \ - com/sun/tools/javac/nio/*.java + com/sun/tools/javac/jigsaw/*.java # The following files in the import jdk source directory are required # in order to compile the files defined in ${require.latest.jdk.files} # -# For NIO, the list of stub files is defined by the contents of the primary -# API packages, together with such types that may be required in order to -# compile the stubs. Some of these dependencies would go away if the stub -# generator were to be improved -- e.g. by removing unnecessary imports. -# import.jdk.stub.files = \ - java/io/File.java \ - java/nio/file/**.java \ - java/nio/file/attribute/**.java \ - java/nio/file/spi/**.java \ - java/nio/channels/AsynchronousChannel.java \ - java/nio/channels/AsynchronousFileChannel.java \ - java/nio/channels/CompletionHandler.java \ - java/nio/channels/SeekableByteChannel.java + java/lang/module/**.java \ + java/lang/reflect/Module.java \ + org/openjdk/jigsaw/**.java # The following value is used by the main jtreg target. # An empty value means all tests @@ -202,3 +229,7 @@ # Check style configuration # overridable name and version checkstyle.name.version = checkstyle-5.4 + +# Set the verbosity used for displaying bootstrap.opts. The value should +# be suitable for the level attribute of the echo task. +bootstrap.opts.verbose=verbose
--- a/make/build.xml Thu Apr 25 09:24:40 2013 -0700 +++ b/make/build.xml Tue May 07 17:14:17 2013 -0700 @@ -120,12 +120,14 @@ <!-- Convenient shorthands for standard locations within the workspace. --> <property name="build.dir" location="build"/> <property name="build.bootstrap.dir" location="${build.dir}/bootstrap"/> + <property name="build.bootstrap.lib.dir" location="${build.dir}/bootstrap/lib"/> <property name="build.coverage.dir" location="${build.dir}/coverage"/> <property name="build.classes.dir" location="${build.dir}/classes"/> <property name="build.gensrc.dir" location="${build.dir}/gensrc"/> <property name="build.genstubs.dir" location="${build.dir}/genstubs"/> <property name="build.javadoc.dir" location="${build.dir}/javadoc"/> <property name="build.jtreg.dir" location="${build.dir}/jtreg"/> + <property name="build.modules.dir" location="${build.dir}/modules"/> <property name="build.toolclasses.dir" location="${build.dir}/toolclasses"/> <property name="dist.dir" location="dist"/> <property name="dist.bin.dir" location="${dist.dir}/bin"/> @@ -154,15 +156,36 @@ <!-- Standard property values, if not overriden by earlier settings. --> <property file="${make.dir}/build.properties"/> - <!-- launcher.java is used in the launcher scripts provided to run - the tools' jar files. If it has not already been set, then - default it to use ${target.java.home}, if available, otherwise - quietly default to simply use "java". --> - <condition property="launcher.java" - value="${target.java.home}/bin/java" else="java"> - <isset property="target.java.home"/> + + <!-- Characteristics of boot.java.home. --> + + <!-- If ${boot.java.home} is a modular image, then we need to build modules + during the bootstrap phase for use in the second phase. --> + <condition property="boot.java.provides.modules"> + <available file="${boot.java.home}/lib/modules/%jigsaw-library" type="file"/> </condition> + <!-- If ${boot.java.home} contains the latest JDK API, we don't need to generate stubs + in order to compile the javac files that use the latest API. --> + <condition property="boot.java.provides.latest.jdk"> + <or> + <isset property="boot.java.provides.modules"/> + <available + ignoresystemclasses="true" + classpath="${boot.java.home}/jre/lib/rt.jar" classname="java.lang.module.ModuleInfo"/> + </or> + </condition> + + + <!-- Characteristics of target.java.home (if set). --> + + <!-- If ${target.java.home} is a modular image, then we need to generate modules + in the second phase for use by the langtools launcher scripts. --> + <condition property="target.java.provides.modules"> + <available file="${target.java.home}/lib/modules/%jigsaw-library" type="file"/> + </condition> + + <!-- Logic for handling access import jdk classes, if available. import.jdk should be unset, or set to jdk home (to use rt.jar) or to jdk repo (to use src/share/classes). @@ -171,39 +194,14 @@ in the build-bootstrap-classes macro. --> <available property="import.jdk.src.dir" value="${import.jdk}/src/share/classes" - filepath="${import.jdk}/src/share/classes" file="java/nio/file/Path.java"/> + filepath="${import.jdk}/src/share/classes" file="java/lang/module/ModuleInfo.java"/> <available property="import.jdk.jar" value="${import.jdk}/jre/lib/rt.jar" ignoresystemclasses="true" - classpath="${import.jdk}/jre/lib/rt.jar" classname="java.nio.file.Path"/> + classpath="${import.jdk}/jre/lib/rt.jar" classname="java.lang.module.ModuleInfo"/> - <!-- Set the default bootclasspath option used for javac. - Note that different variants of the option are used, meaning we can't just - define the value for the option. - Note the explicit use of the standard property ${path.separator} in the following. - This is because Ant is not clever enough to handle direct use of : or ; --> - <condition property="javac.bootclasspath.opt" - value="-Xbootclasspath:${build.classes.dir}${path.separator}${import.jdk.jar}" - else="-Xbootclasspath/p:${build.classes.dir}"> - <isset property="import.jdk.jar"/> - </condition> - <condition property="boot.java.provides.latest.jdk"> - <available - ignoresystemclasses="true" - classpath="${boot.java.home}/jre/lib/rt.jar" classname="java.nio.file.Path"/> - </condition> - - <condition property="bootstrap.exclude.files" value="" else="${require.latest.jdk.files}"> - <isset property="boot.java.provides.latest.jdk"/> - </condition> - - <condition property="exclude.files" value="" else="${require.latest.jdk.files}"> - <or> - <isset property="boot.java.provides.latest.jdk"/> - <isset property="import.jdk"/> - </or> - </condition> - + <!-- Require stubs if ${boot.java.home} does not provide latest JDK API and + ${import.jdk} is set to jdk/src/share/classes. --> <condition property="require.import.jdk.stubs"> <and> <not> @@ -213,6 +211,50 @@ </and> </condition> + + <!-- No need to exclude any files during bootstrap phase if ${boot.java.home} + provides the latest API. --> + <condition property="bootstrap.exclude.files" value="" else="${require.latest.jdk.files}"> + <isset property="boot.java.provides.latest.jdk"/> + </condition> + + <!-- No need to exclude any files during second phase if ${boot.java.home} + provides the latest API or if import.jdk is set. --> + <condition property="exclude.files" value="" else="${require.latest.jdk.files}"> + <or> + <isset property="boot.java.provides.latest.jdk"/> + <isset property="import.jdk"/> + </or> + </condition> + + + <!-- Determine how to use bootstrap-javac in the second phase. + If ${boot.java.home} is a modular image, use -L <library>, + otherwise use -Xbootclasspath/p:<classes>. In both cases, + prefix all words with -J to tunnel them through the javac + launcher to the underlying JVM. --> + <!-- javac -L -Xbootclasspath/p in classpath mode fails to compile. + Not use -L for now. + value="-J-L -J${build.bootstrap.dir}/lib/modules -J-Xmode:module" + --> + <condition property="default.bootstrap.opts" + value="-J-Xbootclasspath/p:${build.bootstrap.dir}/classes" + else="-J-Xbootclasspath/p:${build.bootstrap.dir}/classes"> + <isset property="boot.java.provides.modules"/> + </condition> + + + <!-- Set the default bootclasspath option used for javac. + Note that different variants of the option are used (-Xbcp: and -Xbcp/p:), + meaning we can't just define the value for the option (i.e the path after the ':'). + Note the explicit use of the standard property ${path.separator} in the following. + This is because Ant is not clever enough to handle direct use of : or ; --> + <condition property="javac.bootclasspath.opt" + value="-Xbootclasspath:${build.classes.dir}${path.separator}${import.jdk.jar}" + else="-Xbootclasspath/p:${build.classes.dir}"> + <isset property="import.jdk.jar"/> + </condition> + <!-- Set the default value of the sourcepath used for javac. --> <condition property="javac.sourcepath" value="${build.genstubs.dir}" else=""> <isset property="require.import.jdk.stubs"/> @@ -222,6 +264,16 @@ <property name="javac.classpath" value=""/> + <!-- launcher.java is used in the launcher scripts provided to run + the tools' jar files. If it has not already been set, then + default it to use ${target.java.home}, if available, otherwise + quietly default to simply use "java". --> + <condition property="launcher.java" + value="${target.java.home}/bin/java" else="java"> + <isset property="target.java.home"/> + </condition> + + <!-- **** General top level targets. --> @@ -513,9 +565,12 @@ **** javac targets. --> + <target name="build-bootstrap-classes-javac" depends="-check-boot.java.home,-def-build-bootstrap-classes"> + <build-bootstrap-classes includes="${javac.includes}"/> + </target> + <target name="build-bootstrap-javac" - depends="-def-build-bootstrap-classes,-def-build-bootstrap-jar,-def-build-bootstrap-tool"> - <build-bootstrap-classes includes="${javac.includes}"/> + depends="build-bootstrap-classes-javac,build-bootstrap-module-langtools,-def-build-bootstrap-jar,-def-build-bootstrap-tool"> <build-bootstrap-jar name="javac" includes="${javac.includes}"/> <build-bootstrap-tool name="javac"/> </target> @@ -524,7 +579,7 @@ <build-classes includes="${javac.includes}"/> </target> - <target name="build-javac" depends="build-classes-javac"> + <target name="build-javac" depends="build-classes-javac,build-module-langtools"> <build-jar name="javac" includes="${javac.includes}"/> <build-tool name="javac"/> </target> @@ -543,13 +598,42 @@ <target name="javac" depends="build-javac,jtreg-javac,findbugs-javac"/> + <!-- langtools module targets --> + + <target name="build-bootstrap-module-javax-tools" + depends="build-bootstrap-classes-javac,-def-build-bootstrap-module" + if="boot.java.provides.modules"> + <build-bootstrap-module module.name="${javax.tools.module.name}" includes="${javax.tools.module.includes}"/> + </target> + + <target name="build-module-javax-tools" depends="build-classes-javac,-def-build-module" + if="target.java.provides.modules"> + <build-module module.name="${javax.tools.module.name}" includes="${javax.tools.module.includes}"/> + </target> + + <target name="build-bootstrap-module-langtools" + depends="build-bootstrap-classes-javac,build-bootstrap-classes-javah,build-bootstrap-classes-javap,build-bootstrap-classes-javadoc,build-bootstrap-classes-doclets,build-bootstrap-module-javax-tools,-def-build-bootstrap-module" + if="boot.java.provides.modules"> + <build-bootstrap-module module.name="${langtools.module.name}" includes="${langtools.module.includes}"/> + </target> + + <target name="build-module-langtools" + depends="build-classes-javac,build-classes-javah,build-classes-javap,build-classes-javadoc,build-classes-doclets,build-module-javax-tools,-def-build-module" + if="target.java.provides.modules"> + <build-module module.name="${langtools.module.name}" includes="${langtools.module.includes}"/> + </target> <!-- **** javadoc targets. --> - <target name="build-bootstrap-javadoc" depends="build-bootstrap-javac"> + <target name="build-bootstrap-classes-javadoc" + depends="build-bootstrap-classes-javac"> <build-bootstrap-classes includes="${javadoc.includes}"/> + </target> + + <target name="build-bootstrap-javadoc" + depends="build-bootstrap-classes-javadoc,build-bootstrap-javac,build-bootstrap-module-langtools"> <build-bootstrap-jar name="javadoc" includes="${javadoc.includes}" jarclasspath="javac.jar doclets.jar"/> <build-bootstrap-tool name="javadoc"/> @@ -559,7 +643,7 @@ <build-classes includes="${javadoc.includes}"/> </target> - <target name="build-javadoc" depends="build-javac,build-classes-javadoc"> + <target name="build-javadoc" depends="build-javac,build-classes-javadoc,build-module-langtools"> <build-jar name="javadoc" includes="${javadoc.includes}" jarclasspath="javac.jar doclets.jar"/> <build-tool name="javadoc"/> @@ -584,8 +668,13 @@ **** doclets targets. --> - <target name="build-bootstrap-doclets" depends="build-bootstrap-javadoc,-def-build-bootstrap-jar"> + <!-- no module targets ... classes are included in javadoc module --> + + <target name="build-bootstrap-classes-doclets" depends="build-bootstrap-classes-javadoc"> <build-bootstrap-classes includes="${doclets.includes}"/> + </target> + + <target name="build-bootstrap-doclets" depends="build-bootstrap-javadoc"> <build-bootstrap-jar name="doclets" includes="${doclets.includes}" jarmainclass="com.sun.tools.javadoc.Main" jarclasspath="javadoc.jar"/> @@ -617,22 +706,27 @@ **** javah targets. --> - <target name="build-bootstrap-javah" depends="build-bootstrap-javadoc"> + <target name="build-bootstrap-classes-javah" + depends="build-bootstrap-classes-javac"> <build-bootstrap-classes includes="${javah.includes}"/> - <build-bootstrap-jar name="javah" includes="${javah.includes}" - jarclasspath="javadoc.jar doclets.jar javac.jar"/> - <build-bootstrap-tool name="javah"/> </target> - <target name="build-javah" depends="build-javac,build-classes-javah"> - <build-jar name="javah" includes="${javah.includes}" jarclasspath="javac.jar"/> - <build-tool name="javah"/> + <target name="build-bootstrap-javah" + depends="build-bootstrap-classes-javah,build-bootstrap-javac,build-bootstrap-module-langtools"> + <build-bootstrap-jar name="javah" includes="${javah.includes}" + jarclasspath="javac.jar"/> + <build-bootstrap-tool name="javah"/> </target> <target name="build-classes-javah" depends="build-classes-javadoc"> <build-classes includes="${javah.includes}"/> </target> + <target name="build-javah" depends="build-javac,build-classes-javah,build-module-langtools"> + <build-jar name="javah" includes="${javah.includes}" jarclasspath="javac.jar"/> + <build-tool name="javah"/> + </target> + <!-- (no javadoc for javah) --> <target name="jtreg-javah" depends="build-javah,-def-jtreg"> @@ -650,11 +744,15 @@ **** javap targets. --> - <target name="build-bootstrap-javap" - depends="-def-build-bootstrap-classes,-def-build-bootstrap-jar,-def-build-bootstrap-tool"> + <target name="build-bootstrap-classes-javap" + depends="build-bootstrap-classes-javac"> <build-bootstrap-classes includes="${javap.includes}"/> + </target> + + <target name="build-bootstrap-javap" + depends="build-bootstrap-classes-javap,build-bootstrap-javac,build-bootstrap-module-langtools"> <build-bootstrap-jar name="javap" includes="${javap.includes}" - jarmainclass="sun.tools.javap.Main"/> + jarclasspath="javac.jar"/> <build-bootstrap-tool name="javap"/> </target> @@ -662,14 +760,14 @@ <build-classes includes="${javap.includes}"/> </target> - <target name="build-javap" depends="build-javac,build-classes-javap"> + <target name="build-javap" depends="build-javac,build-classes-javap,build-module-langtools"> <build-jar name="javap" includes="${javap.includes}" jarmainclass="com.sun.tools.javap.Main" jarclasspath="javac.jar"/> <build-tool name="javap"/> </target> - <!-- (no javadoc for javap) --> + <!-- (no javadoc for javap ... what about classfile library? ) --> <target name="jtreg-javap" depends="build-javap,-def-jtreg"> <jtreg-tool name="javap" tests="${javap.tests}"/> @@ -770,6 +868,69 @@ **** Targets for Ant macro and task definitions. --> + <target name="-def-jigsaw"> + <mkdir dir="${build.toolclasses.dir}"/> + <javac fork="true" + source="${boot.javac.source}" + target="${boot.javac.target}" + executable="${boot.java.home}/bin/javac" + srcdir="${make.tools.dir}/Jigsaw" + destdir="${build.toolclasses.dir}/" + classpath="${ant.home}/lib/ant.jar"/> + <taskdef name="fpkg" + classname="FpkgTask" + classpath="${build.toolclasses.dir}/"/> + <taskdef name="jmod" + classname="JmodTask" + classpath="${build.toolclasses.dir}/"/> + </target> + + <target name="-def-build-module" depends="-def-jigsaw"> + <macrodef name="build-module"> + <attribute name="module.name"/> + <attribute name="module.version" default="${module.version}"/> + <attribute name="classes.dir" default="${build.classes.dir}"/> + <attribute name="includes"/> + <attribute name="excludes" default=""/> + <attribute name="dest.dir" default="${dist.lib.dir}"/> + <attribute name="jdk" default="${target.java.home}"/> + <attribute name="library" default="${dist.lib.dir}/modules"/> + <sequential> + <fpkg name="@{module.name}" version="@{module.version}" + dir="@{classes.dir}" includes="@{includes}" excludes="@{excludes}" + jdk="@{jdk}" + destdir="@{dest.dir}" + fork="true" executable="@{jdk}/bin/jpkg"/> + <jmod task="create" library="@{library}" parent="@{jdk}/lib/modules" + fork="true" executable="@{jdk}/bin/jmod"/> + <jmod task="install" library="@{library}" + fork="true" executable="@{jdk}/bin/jmod"> + <arg file="@{dest.dir}/@{module.name}@@@{module.version}.jmod"/> + </jmod> + </sequential> + </macrodef> + </target> + +<!-- + <target name="-def-jmod"> + <macrodef name="jmod"> + <attribute name="task"/> + <attribute name="library"/> + <attribute name="java.home" default="${target.java.home}"/> + <element name="args" implicit="true" optional="true"/> + <sequential> + <echo message="jmod @{task} -L @{library} ..."/> + <exec executable="@{java.home}/bin/jmod" failonerror="true"> + <arg value="@{task}"/> + <arg value="-L"/> + <arg file="@{library}"/> + <args/> + </exec> + </sequential> + </macrodef> + </target> +--> + <target name="-def-build-tool"> <macrodef name="build-tool"> <attribute name="name"/> @@ -817,7 +978,7 @@ <attribute name="excludes" default="${exclude.files} **/package-info.java"/> <attribute name="classes.dir" default="${build.classes.dir}"/> <attribute name="gensrc.dir" default="${build.gensrc.dir}"/> - <attribute name="javac.bootclasspath" default="${build.bootstrap.dir}/classes"/> + <attribute name="bootstrap.opts" default="${default.bootstrap.opts}"/> <attribute name="bootclasspath.opt" default="${javac.bootclasspath.opt}"/> <attribute name="classpath" default="${javac.classpath}"/> <attribute name="sourcepath" default="${javac.sourcepath}"/> @@ -827,6 +988,7 @@ <attribute name="release" default="${release}"/> <attribute name="full.version" default="${full.version}"/> <sequential> + <echo level="${bootstrap.opts.verbose}" message="build-classes: bootstrap.opts=@{bootstrap.opts}"/> <echo level="verbose" message="build-classes: excludes=@{excludes}"/> <echo level="verbose" message="build-classes: bootclasspath.opt=@{bootclasspath.opt}"/> <echo level="verbose" message="build-classes: classpath=@{classpath}"/> @@ -863,7 +1025,7 @@ debuglevel="${javac.debuglevel}"> <compilerarg value="-implicit:none"/> <compilerarg value="-Xprefer:source"/> - <compilerarg value="-J-Xbootclasspath/p:@{javac.bootclasspath}"/> + <compilerarg line="@{bootstrap.opts}"/> <compilerarg line="@{bootclasspath.opt}"/> <compilerarg line="${javac.no.jdk.warnings}"/> <compilerarg line="${javac.version.opt}"/> @@ -878,6 +1040,11 @@ <exclude name="**/*.orig"/> <exclude name="**/overview.html"/> <exclude name="**/package.html"/> + <exclude name="**/overview.html"/> + <exclude name="**/*.orig"/> + <exclude name="**/*.rej"/> + <exclude name="**/*.BAK"/> + <exclude name="**/*~"/> </fileset> </copy> </sequential> @@ -907,7 +1074,7 @@ target="${boot.javac.target}" gensrc.dir="${build.bootstrap.dir}/gensrc" classes.dir="${build.bootstrap.dir}/classes" - javac.bootclasspath="" + bootstrap.opts="" bootclasspath.opt="-Xbootclasspath/p:${build.bootstrap.dir}/classes" sourcepath="" release="${bootstrap.release}" @@ -916,6 +1083,16 @@ </presetdef> </target> + <target name="-def-build-bootstrap-module" depends="-def-build-module"> + <presetdef name="build-bootstrap-module"> + <build-module + classes.dir="${build.bootstrap.dir}/classes" + dest.dir="${build.bootstrap.dir}/lib" + library="${build.bootstrap.dir}/lib/modules" + jdk="${boot.java.home}"/> + </presetdef> + </target> + <target name="-def-pcompile"> <mkdir dir="${build.toolclasses.dir}"/> <javac fork="true"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/Jigsaw/FpkgTask.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.MatchingTask; +import org.apache.tools.ant.util.FileUtils; + +/** + * This class provides a specialized form of jpkg, to create a module package file + * from the appropriate langtools classes, and (re)using the module-info.class + * file from a previously installed copy of the module. + * If the package file exists and is up to date, it will not be modified. + * + * Note: the code here relies on the internal layout of a module library. + * Ideally, there would be tool support to extract module info.class from + * a library. + */ +public class FpkgTask extends MatchingTask { + /** + * Set the module name. + */ + public void setName(String name) { + this.name = name; + } + + /** + * Set the module version. + */ + public void setVersion(String version) { + this.version = version; + } + + /** + * Set the directory in which to write the package file. + * See jpkg --dest-dir. + */ + public void setDestDir(File destDir) { + this.destDir = destDir; + } + + /** + * Set the type of package to be written: (deb or jmod) + * See the first anonymous arg for jpkg. + */ + public void setType(String type) { + this.type = type; + } + + /** + * Set the root directory of the implicit fileset of files to be included + * in the package. + * All the related attributes of an implicit fileset may be used. + * The fileset may include classes (*.class) and resources (other files.) + */ + public void setDir(File dir) { + this.dir = dir; + } + + /** + * Set the JDK from which to import the copy of module-info to be used. + * It is assumed the module library will be at jdk/lib/modules + * and that the library follows the SimpleLibrary layout. + */ + public void setJDK(File jdk) { + this.jdk = jdk; + } + + /** + * Set whether or not jpkg should be executed in a separate process. + */ + public void setFork(boolean fork) { + this.fork = fork; + } + + /** + * Set the path for the executable for jpkg, for use when fork is true. + */ + public void setExecutable(String executable) { + this.executable = executable; + } + + @Override + public void execute() { + if (name == null || name.length() == 0) + throw new BuildException("no name given"); + + if (version == null || version.length() == 0) + throw new BuildException("no version given"); + + if (destDir == null) + throw new BuildException("no output directory given"); + + if (type == null) + type = "jmod"; + else if (!(type.equals("jmod") || type.equals("deb"))) + throw new BuildException("invalid type given"); + + // if fork is true, validate executable? + + File file = new File(destDir, name + "@" + version + "." + type); + if (isUptodate(file)) { + log("Skipping " + name + "@" + version + " because it is up to date", + Project.MSG_VERBOSE); + return; + } + + // The following code presumes knowledge of the layout of the JDK module library + File jdkModulesDir = new File(new File(jdk, "lib"), "modules"); + File jdkModulesMarker = new File(jdkModulesDir, "%jigsaw-library"); + if (!jdkModulesMarker.exists()) + throw new BuildException("cannot find JDK module library"); + + File importModuleDir = new File(new File(jdkModulesDir, name), version); + if (!importModuleDir.exists()) + throw new BuildException("cannot find module " + name + "@" + version + " in JDK module library"); + + File importModuleInfo = new File(importModuleDir, "info"); + if (!importModuleInfo.exists()) + throw new BuildException("cannot find module info for module " + name + "@" + version + " in JDK module library"); + + File javaTmpDir = new File(System.getProperty("java.io.tmpdir")); + File tmpDir = new File(javaTmpDir, (getClass().getSimpleName() + "." + System.currentTimeMillis())); + + try { + File tmpModuleDir = new File(tmpDir, name); + File tmpClassesDir = new File(tmpModuleDir, "classes"); + + tmpClassesDir.mkdirs(); + destDir.mkdirs(); + FileUtils fu = FileUtils.getFileUtils(); + fu.copyFile(importModuleInfo, new File(tmpClassesDir, "module-info.class")); + copyFiles(tmpClassesDir); + + List<String> opts = new ArrayList<String>(); + add(opts, "--module-dir", tmpClassesDir.getPath()); + add(opts, "--dest-dir", destDir.getPath()); + add(opts, type); + add(opts, name); + + log("Creating module file for " + name, Project.MSG_INFO); + jpkg(opts); + } catch (InterruptedException e) { + throw new BuildException("error occurred", e); + } catch (IOException e) { + throw new BuildException("error occurred", e); + } finally { + delete(tmpDir); + } + } + + void jpkg(List<String> opts) throws IOException, InterruptedException { + if (fork) { + List<String> cmd = new ArrayList<String>(); + cmd.add(executable); + cmd.addAll(opts); +// log("exec: " + cmd, Project.MSG_VERBOSE); +// ProcessBuilder pb = new ProcessBuilder(cmd); +// pb.redirectErrorStream(true); +// Process p = pb.start(); +// BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); +// try { +// String line; +// while ((line = in.readLine()) != null) +// System.out.println(line); +// } finally { +// in.close(); +// } +// int rc = p.waitFor(); +// if (rc != 0) +// throw new BuildException("unexpected exit from jpkg: " + rc); + Execute.runCommand(this, cmd.toArray(new String[cmd.size()])); + } else { + throw new BuildException("fork=false not supported yet"); + } + } + + boolean isUptodate(File file) { + long fileTime = file.lastModified(); + + DirectoryScanner s = getDirectoryScanner(dir); + for (String path: s.getIncludedFiles()) { + File f = new File(dir, path); + if (f.lastModified() > fileTime) + return false; + } + + return true; + } + + void copyFiles(File classesDir) throws IOException { + FileUtils fu = FileUtils.getFileUtils(); + DirectoryScanner s = getDirectoryScanner(dir); + for (String path: s.getIncludedFiles()) { + File toDir = classesDir; + fu.copyFile(new File(dir, path), new File(toDir, path)); + } + } + + boolean delete(File file) { + if (file.isDirectory()) { + boolean ok = true; + for (File f: file.listFiles()) + ok &= delete(f); + ok &= file.delete(); + return ok; + } else + return file.delete(); + } + + void add(List<String> list, String... values) { + for (String v: values) + list.add(v); + } + + private String name; + private String version; + private File destDir; + private String type; + private File dir; + private File jdk; + private boolean fork; + private String executable; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/Jigsaw/JmodTask.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.types.Commandline; + +/** + * This class provides simple limited support for using jmod. + * Only the "create" and "install" options are supported. + */ +public class JmodTask extends Task { + /** + * Set the task to be performed: "create" or "install". + * If the task is "create", the library will be created if it does not + * already exist. + * If the task is "install" and the module is up to date in the library + * it will not be modified. If the module exists but is not up to date, + * it will be deleted before jmod is invoked. + */ + public void setTask(String task) { + this.task = task; + } + + /** + * Set the library to be created/used. + * See jmod -L/--library. + */ + public void setLibrary(File library) { + this.library = library; + } + + /** + * Set the parent of the library to be created. + * See jmod -P/--parent-path. + */ + public void setParent(File parent) { + this.parent = parent; + } + + /** + * Set whether or not jmod should be executed in a separate process. + */ + public void setFork(boolean fork) { + this.fork = fork; + } + + /** + * Set the path for the executable for jmod, for use when fork is true. + */ + public void setExecutable(String executable) { + this.executable = executable; + } + + /** + * Set additional arguments for the task. If the task is "install", + * use this to specify module package files to be installed. + */ + public void addArg(Commandline.Argument arg) { + args.add(arg); + } + + @Override + public void execute() { + if (task == null) + throw new BuildException("task not set"); + + if (task.equals("create")) + doCreate(); + else if (task.equals("install")) + doInstall(); + else + throw new BuildException("task not recognized"); + } + + void doCreate() { + if (library.exists()) { + if (new File(library, "%jigsaw-library").exists()) { + log("Skipping " + library + " because it already exists", + Project.MSG_VERBOSE); + return; + } else + throw new BuildException("library exists but is not a valid Jigsaw library"); + } else { + File libDir = library.getParentFile(); + libDir.mkdirs(); + List<String> opts = new ArrayList<String>(); + add(opts, "create"); + add(opts, "--library", library.getPath()); + if (parent == null) + add(opts, "--no-parent"); + else + add(opts, "--parent-path", parent.getPath()); + + System.out.println("Creating module library " + library); + + try { + jmod(opts); + } catch (InterruptedException e) { + throw new BuildException("error occurred", e); + } catch (IOException e) { + throw new BuildException("error occurred", e); + } + } + } + + void doInstall() { + List<File> files = new ArrayList<File>(); + + for (Commandline.Argument arg: args) { + for (String s: arg.getParts()) { + File f = new File(s); + String fname = f.getName(); + int lastDot = fname.lastIndexOf("."); + String fbase = (lastDot == -1 ? fname : fname.substring(0, lastDot)); + int at = fbase.indexOf("@"); + String mname = (at == -1 ? fbase : fbase.substring(0, at)); + String mversion = (at == -1 ? "" : fbase.substring(at + 1)); + File mdir = new File(new File(library, mname), mversion); + if (mdir.exists() && mdir.lastModified() > f.lastModified()) { + log("Skipping " + f + " because installed module is up to date", + Project.MSG_VERBOSE); + continue; + } + log("Deleting " + mdir, Project.MSG_VERBOSE); + delete(mdir); + files.add(f); + } + } + + if (files.isEmpty()) + return; + + try { + List<String> opts = new ArrayList<String>(); + add(opts, "install"); + add(opts, "--library", library.getPath()); + for (File f: files) + add(opts, f.getPath()); + + log("Installing " + files.size() + + " module" + (files.size() == 1 ? "" : "s") + + " in " + library, + Project.MSG_INFO); + jmod(opts); + } catch (InterruptedException e) { + throw new BuildException("error occurred", e); + } catch (IOException e) { + throw new BuildException("error occurred", e); + } + } + + void jmod(List<String> opts) throws IOException, InterruptedException { + if (fork) { + List<String> cmd = new ArrayList<String>(); + cmd.add(executable); + cmd.addAll(opts); +// log("exec: " + cmd, Project.MSG_VERBOSE); +// ProcessBuilder pb = new ProcessBuilder(cmd); +// pb.redirectErrorStream(true); +// Process p = pb.start(); +// BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); +// try { +// String line; +// while ((line = in.readLine()) != null) +// System.out.println(line); +// } finally { +// in.close(); +// } +// int rc = p.waitFor(); +// if (rc != 0) +// throw new BuildException("unexpected exit from jmod: " + rc); + Execute.runCommand(this, cmd.toArray(new String[cmd.size()])); + } else { + throw new BuildException("fork=false not supported yet"); + } + } + + boolean delete(File file) { + if (file.isDirectory()) { + boolean ok = true; + for (File f: file.listFiles()) + ok &= delete(f); + ok &= file.delete(); + return ok; + } else + return file.delete(); + } + + void add(List<String> list, String... values) { + for (String v: values) + list.add(v); + } + + private String task; + private File library; + private File parent; + private boolean fork; + private String executable; + private List<Commandline.Argument> args = new ArrayList<Commandline.Argument>(); +}
--- a/make/tools/genstubs/GenStubs.java Thu Apr 25 09:24:40 2013 -0700 +++ b/make/tools/genstubs/GenStubs.java Tue May 07 17:14:17 2013 -0700 @@ -284,9 +284,9 @@ tree.accept(this); ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); for (JCTree def: tree.defs) { - if (def.getTag() == JCTree.Tag.IMPORT) { + if (def.hasTag(JCTree.Tag.IMPORT)) { JCImport imp = (JCImport) def; - if (imp.qualid.getTag() == JCTree.Tag.SELECT) { + if (imp.qualid.hasTag(JCTree.Tag.SELECT)) { JCFieldAccess qualid = (JCFieldAccess) imp.qualid; if (!qualid.name.toString().equals("*") && !names.contains(qualid.name)) { @@ -296,7 +296,7 @@ } defs.add(def); } - return m.TopLevel(tree.packageAnnotations, tree.pid, defs.toList()); + return m.TopLevel(defs.toList()); } @Override
--- a/makefiles/BuildLangtools.gmk Thu Apr 25 09:24:40 2013 -0700 +++ b/makefiles/BuildLangtools.gmk Tue May 07 17:14:17 2013 -0700 @@ -105,7 +105,8 @@ SETUP:=BOOT_JAVAC,\ DISABLE_SJAVAC:=true,\ SRC:=$(LANGTOOLS_TOPDIR)/src/share/classes $(LANGTOOLS_OUTPUTDIR)/gensrc,\ - EXCLUDES:=com/sun/tools/javac/nio,\ + EXCLUDES:=com/sun/tools/javac/nio \ + com/sun/tools/javac/jigsaw,\ COPY:=$(RESOURCE_SUFFIXES),\ BIN:=$(LANGTOOLS_OUTPUTDIR)/btclasses/bootstrap)) @@ -123,10 +124,11 @@ genstubs.GenStubs # We fetch source from the JDK... JDKS=$(JDK_TOPDIR)/src/share/classes - # Build the list of classes to generate stubs from. java/util/Objects.java isn't - # currently needed, but is used as a demo for now. + # Build the list of classes to generate stubs from. STUBSOURCES:=$(shell $(FIND) $(JDKS) -name "*.java" | $(GREP) \ - -e "$(JDKS)/java/util/Objects.java") + -e "$(JDKS)/java/lang/module/" \ + -e "$(JDKS)/java/lang/reflect/Module.java" \ + -e "$(JDKS)/org/openjdk/jigsaw/") # Rewrite the file names into class names because the GenStubs tool require this. STUBCLASSES:=$(subst /,.,$(patsubst $(JDKS)/%.java,%,$(STUBSOURCES))) @@ -170,7 +172,7 @@ SETUP:=GENERATE_NEWBYTECODE,\ SRC:=$(LANGTOOLS_TOPDIR)/src/share/classes $(LANGTOOLS_OUTPUTDIR)/gensrc \ $(LANGTOOLS_OUTPUTDIR)/genstubs,\ - EXCLUDES:=java/util java/io java/nio,\ + EXCLUDES:=java/util java/io java/nio java/lang org/openjdk,\ COPY:=$(RESOURCE_SUFFIXES),\ BIN:=$(LANGTOOLS_OUTPUTDIR)/classes))
--- a/src/share/bin/launcher.sh-template Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/bin/launcher.sh-template Tue May 07 17:14:17 2013 -0700 @@ -33,22 +33,6 @@ esac mylib="$mydir/../lib" -# By default, put the jar file and its dependencies on the bootclasspath. -# This is always required on a Mac, because the system langtools classes -# are always on the main class path; in addition, it may be required on -# standard versions of JDK (i.e. using rt.jar and tools.jar) because some -# langtools interfaces are in rt.jar. -# Assume that the jar file being invoked lists all the necessary langtools -# jar files in its Class-Path manifest entry, so there is no need to search -# dependent jar files for additional dependencies. - -if [ "$LANGTOOLS_USE_BOOTCLASSPATH" != "no" ]; then - cp=`unzip -c "$mylib/#PROGRAM#.jar" META-INF/MANIFEST.MF | - grep "Class-Path:" | - sed -e 's|Class-Path: *||' -e 's|\([a-z]*\.jar\) *|'"$mylib"'/\1#PS#|g'` - bcp="$mylib/#PROGRAM#.jar#PS#$cp" -fi - # tools currently assumes that assertions are enabled in the launcher ea=-ea:com.sun.tools... @@ -71,5 +55,32 @@ done unset DUALCASE +# Use newline as arg separator to preserve spaces in args +javahome=`dirname "\`dirname \"#TARGET_JAVA#\" \`"` +if [ -r "$javahome"/lib/modules/%jigsaw-library ]; then + if [ -r $mylib/modules/%jigsaw-library ]; then + langtools="-L$nl$mylib/modules" + tool="-m${nl}#PROGRAM#" + fi +else + # By default, put the jar file and its dependencies on the bootclasspath. + # This is always required on a Mac, because the system langtools classes + # are always on the main class path; in addition, it may be required on + # standard versions of JDK (i.e. using rt.jar and tools.jar) because some + # langtools interfaces are in rt.jar. + # Assume that the jar file being invoked lists all the necessary langtools + # jar files in its Class-Path manifest entry, so there is no need to search + # dependent jar files for additional dependencies. + + if [ "$LANGTOOLS_USE_BOOTCLASSPATH" != "no" ]; then + cp=`unzip -c "$mylib/#PROGRAM#.jar" META-INF/MANIFEST.MF | + grep "Class-Path:" | + sed -e 's|Class-Path: *||' -e 's|\([a-z]*\.jar\) *|'"$mylib"'/\1#PS#|g'` + bcp="$mylib/#PROGRAM#.jar"#PS#$cp + fi + langtools="${bcp:+-Xbootclasspath/p:"$bcp"}" + tool="-jar$nl${mylib}/#PROGRAM#.jar" +fi + IFS=$nl -"#TARGET_JAVA#" "${bcp:+-Xbootclasspath/p:"$bcp"}" ${ea} ${javaOpts} -jar "${mylib}/#PROGRAM#.jar" ${toolOpts} +"#TARGET_JAVA#" ${langtools} ${ea} ${javaOpts} ${tool} ${toolOpts}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/EntrypointDirectiveTree.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.source.tree; + +public interface EntrypointDirectiveTree extends ModuleDirectiveTree { + ExpressionTree getClassName(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/ExportDirectiveTree.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.source.tree; + +/** + * + */ +public interface ExportDirectiveTree extends ModuleDirectiveTree { + ExpressionTree getExportName(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/ModuleDirectiveTree.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.source.tree; + +/** + * A super-type for all the directives in a ModuleTree. + */ +public interface ModuleDirectiveTree extends Tree { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/ModuleIdTree.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.source.tree; + +import javax.lang.model.element.Name; + +/** + * + */ +public interface ModuleIdTree extends Tree { + Tree getName(); + Name getVersion(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/ModuleQueryTree.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.source.tree; + +import javax.lang.model.element.Name; + +/** + * + */ +public interface ModuleQueryTree extends Tree { + Tree getName(); + Name getVersionQuery(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/ModuleTree.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.source.tree; + +import java.util.List; + + +/** + * + */ +public interface ModuleTree extends Tree { + ModuleIdTree getId(); + List<? extends ModuleDirectiveTree> getDirectives(); + CharSequence getExtendedMetadata(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/PackageTree.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,13 @@ + +package com.sun.source.tree; + +import java.util.List; + + +/** + * + */ +public interface PackageTree extends Tree { + List<? extends AnnotationTree> getAnnotations(); + Tree getPackageId(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/PermitsDirectiveTree.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.source.tree; + +/** + * + */ +public interface PermitsDirectiveTree extends Tree { + Tree getModuleName(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/ProvidesModuleDirectiveTree.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.source.tree; + +public interface ProvidesModuleDirectiveTree extends ModuleDirectiveTree { + ModuleIdTree getModuleId(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/ProvidesServiceDirectiveTree.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.source.tree; + +/* + * + */ +public interface ProvidesServiceDirectiveTree extends ModuleDirectiveTree { + ExpressionTree getServiceName(); + ExpressionTree getImplementationName(); +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/RequiresFlag.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.source.tree; + +/** + * This may go away in favor of a public definition in javax.lang.model + */ +public enum RequiresFlag { + OPTIONAL, + LOCAL, + REEXPORT, + SYNTHETIC, + SYNTHESIZED +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/RequiresModuleDirectiveTree.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.source.tree; + +import java.util.List; + +public interface RequiresModuleDirectiveTree extends ModuleDirectiveTree { + List<RequiresFlag> getFlags(); + ModuleQueryTree getModuleQuery(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/RequiresServiceDirectiveTree.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.source.tree; + +import java.util.List; + +public interface RequiresServiceDirectiveTree extends ModuleDirectiveTree { + List<RequiresFlag> getFlags(); + ExpressionTree getServiceName(); +}
--- a/src/share/classes/com/sun/source/tree/Tree.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/source/tree/Tree.java Tue May 07 17:14:17 2013 -0700 @@ -581,6 +581,30 @@ */ ERRONEOUS(ErroneousTree.class), + MODULE(ModuleTree.class), + + ENTRYPOINT_DIRECTIVE(EntrypointDirectiveTree.class), + + EXPORT_DIRECTIVE(ExportDirectiveTree.class), + + MODULE_ID(ModuleIdTree.class), + + MODULE_QUERY(ModuleQueryTree.class), + + PERMITS_DIRECTIVE(PermitsDirectiveTree.class), + + PROVIDES_MODULE_DIRECTIVE(ProvidesModuleDirectiveTree.class), + + PROVIDES_SERVICE_DIRECTIVE(ProvidesServiceDirectiveTree.class), + + REQUIRES_MODULE_DIRECTIVE(RequiresModuleDirectiveTree.class), + + REQUIRES_SERVICE_DIRECTIVE(RequiresServiceDirectiveTree.class), + + VIEW_DECLARATION(ViewDeclarationTree.class), + + PACKAGE(PackageTree.class), + /** * Used for instances of {@link ClassTree} representing interfaces. */
--- a/src/share/classes/com/sun/source/tree/TreeVisitor.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/source/tree/TreeVisitor.java Tue May 07 17:14:17 2013 -0700 @@ -73,7 +73,9 @@ R visitConditionalExpression(ConditionalExpressionTree node, P p); R visitContinue(ContinueTree node, P p); R visitDoWhileLoop(DoWhileLoopTree node, P p); + R visitEntrypoint(EntrypointDirectiveTree node, P p); R visitErroneous(ErroneousTree node, P p); + R visitExport(ExportDirectiveTree node, P p); R visitExpressionStatement(ExpressionStatementTree node, P p); R visitEnhancedForLoop(EnhancedForLoopTree node, P p); R visitForLoop(ForLoopTree node, P p); @@ -85,10 +87,20 @@ R visitLiteral(LiteralTree node, P p); R visitMethod(MethodTree node, P p); R visitModifiers(ModifiersTree node, P p); + R visitModule(ModuleTree node, P p); + R visitModuleId(ModuleIdTree node, P p); + R visitModuleQuery(ModuleQueryTree node, P p); R visitNewArray(NewArrayTree node, P p); R visitNewClass(NewClassTree node, P p); R visitLambdaExpression(LambdaExpressionTree node, P p); + R visitPackage(PackageTree node, P p); R visitParenthesized(ParenthesizedTree node, P p); + R visitPermits(PermitsDirectiveTree node, P p); + R visitProvidesModule(ProvidesModuleDirectiveTree node, P p); + R visitProvidesService(ProvidesServiceDirectiveTree node, P p); + R visitRequiresModule(RequiresModuleDirectiveTree node, P p); + R visitRequiresService(RequiresServiceDirectiveTree node, P p); + R visitView(ViewDeclarationTree node, P p); R visitReturn(ReturnTree node, P p); R visitMemberSelect(MemberSelectTree node, P p); R visitMemberReference(MemberReferenceTree node, P p);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/ViewDeclarationTree.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.source.tree; + +import java.util.List; + +/** + * + */ +public interface ViewDeclarationTree extends Tree { + ExpressionTree getName(); + List<? extends ModuleDirectiveTree> getDirectives(); +}
--- a/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java Tue May 07 17:14:17 2013 -0700 @@ -34,7 +34,7 @@ * @since 1.6 */ @jdk.Supported -public class SimpleTreeVisitor <R,P> implements TreeVisitor<R,P> { +public class SimpleTreeVisitor<R,P> implements TreeVisitor<R,P> { protected final R DEFAULT_VALUE; protected SimpleTreeVisitor() { @@ -269,6 +269,65 @@ return defaultAction(node, p); } + @Override + public R visitModule(ModuleTree node, P p) { + return defaultAction(node, p); + } + + @Override + public R visitModuleId(ModuleIdTree node, P p) { + return defaultAction(node, p); + } + + @Override + public R visitModuleQuery(ModuleQueryTree node, P p) { + return defaultAction(node, p); + } + + @Override + public R visitView(ViewDeclarationTree node, P p) { + return defaultAction(node, p); + } + + @Override + public R visitEntrypoint(EntrypointDirectiveTree node, P p) { + return defaultAction(node, p); + } + + @Override + public R visitExport(ExportDirectiveTree node, P p) { + return defaultAction(node, p); + } + + @Override + public R visitPermits(PermitsDirectiveTree node, P p) { + return defaultAction(node, p); + } + + @Override + public R visitProvidesModule(ProvidesModuleDirectiveTree node, P p) { + return defaultAction(node, p); + } + + @Override + public R visitProvidesService(ProvidesServiceDirectiveTree node, P p) { + return defaultAction(node, p); + } + + @Override + public R visitRequiresModule(RequiresModuleDirectiveTree node, P p) { + return defaultAction(node, p); + } + + @Override + public R visitRequiresService(RequiresServiceDirectiveTree node, P p) { + return defaultAction(node, p); + } + + public R visitPackage(PackageTree node, P p) { + return defaultAction(node, p); + } + public R visitOther(Tree node, P p) { return defaultAction(node, p); }
--- a/src/share/classes/com/sun/source/util/TreeScanner.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/source/util/TreeScanner.java Tue May 07 17:14:17 2013 -0700 @@ -403,6 +403,62 @@ return r; } + public R visitModule(ModuleTree node, P p) { + R r = scan(node.getId(), p); + r = scanAndReduce(node.getDirectives(), p, r); + return r; + } + + public R visitView(ViewDeclarationTree node, P p) { + R r = scan(node.getName(), p); + r = scanAndReduce(node.getDirectives(), p, r); + return r; + } + + public R visitEntrypoint(EntrypointDirectiveTree node, P p) { + return scan(node.getClassName(), p); + } + + public R visitExport(ExportDirectiveTree node, P p) { + return scan(node.getExportName(), p); + } + + public R visitModuleId(ModuleIdTree node, P p) { + return scan(node.getName(), p); + } + + public R visitModuleQuery(ModuleQueryTree node, P p) { + return scan(node.getName(), p); + } + + public R visitPermits(PermitsDirectiveTree node, P p) { + return scan(node.getModuleName(), p); + } + + public R visitProvidesModule(ProvidesModuleDirectiveTree node, P p) { + return scan(node.getModuleId(), p); + } + + public R visitProvidesService(ProvidesServiceDirectiveTree node, P p) { + R r = scan(node.getServiceName(), p); + r = scanAndReduce(node.getImplementationName(), p, r); + return r; + } + + public R visitRequiresModule(RequiresModuleDirectiveTree node, P p) { + return scan(node.getModuleQuery(), p); + } + + public R visitRequiresService(RequiresServiceDirectiveTree node, P p) { + return scan(node.getServiceName(), p); + } + + public R visitPackage(PackageTree node, P p) { + R r = scan(node.getAnnotations(), p); + r = scanAndReduce(node.getPackageId(), p, r); + return r; + } + public R visitOther(Tree node, P p) { return null; }
--- a/src/share/classes/com/sun/tools/classfile/AccessFlags.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/classfile/AccessFlags.java Tue May 07 17:14:17 2013 -0700 @@ -57,6 +57,7 @@ public static final int ACC_ANNOTATION = 0x2000; // class, inner public static final int ACC_ENUM = 0x4000; // class, inner, field public static final int ACC_MANDATED = 0x8000; // class, inner, field, method + public static final int ACC_MODULE = 0x10000; // class, inner, field, method public static enum Kind { Class, InnerClass, Field, Method}; @@ -81,12 +82,12 @@ } private static final int[] classModifiers = { - ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT + ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT, ACC_MODULE }; private static final int[] classFlags = { ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, ACC_ABSTRACT, - ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM + ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE }; public Set<String> getClassModifiers() { @@ -100,12 +101,12 @@ private static final int[] innerClassModifiers = { ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, - ACC_ABSTRACT + ACC_ABSTRACT, ACC_MODULE }; private static final int[] innerClassFlags = { ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SUPER, - ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM + ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE }; public Set<String> getInnerClassModifiers() { @@ -119,12 +120,12 @@ private static final int[] fieldModifiers = { ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, - ACC_VOLATILE, ACC_TRANSIENT + ACC_VOLATILE, ACC_TRANSIENT, ACC_MODULE }; private static final int[] fieldFlags = { ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, - ACC_VOLATILE, ACC_TRANSIENT, ACC_SYNTHETIC, ACC_ENUM + ACC_VOLATILE, ACC_TRANSIENT, ACC_SYNTHETIC, ACC_ENUM, ACC_MODULE }; public Set<String> getFieldModifiers() { @@ -137,13 +138,13 @@ private static final int[] methodModifiers = { ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, - ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT + ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT, ACC_MODULE }; private static final int[] methodFlags = { ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SYNCHRONIZED, ACC_BRIDGE, ACC_VARARGS, ACC_NATIVE, ACC_ABSTRACT, - ACC_STRICT, ACC_SYNTHETIC + ACC_STRICT, ACC_SYNTHETIC, ACC_MODULE }; public Set<String> getMethodModifiers() { @@ -210,6 +211,8 @@ return "strictfp"; case ACC_MANDATED: return "mandated"; + case ACC_MODULE: + return "module"; default: return null; } @@ -249,6 +252,8 @@ return "ACC_ENUM"; case ACC_MANDATED: return "ACC_MANDATED"; + case ACC_MODULE: + return "ACC_MODULE"; default: return null; }
--- a/src/share/classes/com/sun/tools/classfile/Attribute.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/classfile/Attribute.java Tue May 07 17:14:17 2013 -0700 @@ -66,6 +66,12 @@ public static final String StackMapTable = "StackMapTable"; public static final String Synthetic = "Synthetic"; + // JSR 294 + public static final String Module = "Module"; + public static final String ModuleData = "ModuleData"; + public static final String ModuleProvides = "ModuleProvides"; + public static final String ModuleRequires = "ModuleRequires"; + public static class Factory { public Factory() { // defer init of standardAttributeClasses until after options set up @@ -115,6 +121,11 @@ standardAttributes.put(LocalVariableTable, LocalVariableTable_attribute.class); standardAttributes.put(LocalVariableTypeTable, LocalVariableTypeTable_attribute.class); + standardAttributes.put(Module, Module_attribute.class); + standardAttributes.put(ModuleData, ModuleData_attribute.class); + standardAttributes.put(ModuleProvides, ModuleProvides_attribute.class); + standardAttributes.put(ModuleRequires, ModuleRequires_attribute.class); + if (!compat) { // old javap does not recognize recent attributes standardAttributes.put(MethodParameters, MethodParameters_attribute.class); standardAttributes.put(CompilationID, CompilationID_attribute.class); @@ -191,5 +202,10 @@ R visitStackMap(StackMap_attribute attr, P p); R visitStackMapTable(StackMapTable_attribute attr, P p); R visitSynthetic(Synthetic_attribute attr, P p); + + R visitModule(Module_attribute attr, P p); + R visitModuleData(ModuleData_attribute attr, P p); + R visitModuleProvides(ModuleProvides_attribute attr, P p); + R visitModuleRequires(ModuleRequires_attribute attr, P p); } }
--- a/src/share/classes/com/sun/tools/classfile/ClassTranslator.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/classfile/ClassTranslator.java Tue May 07 17:14:17 2013 -0700 @@ -38,6 +38,8 @@ import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodHandle_info; import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodType_info; import com.sun.tools.classfile.ConstantPool.CONSTANT_Methodref_info; +import com.sun.tools.classfile.ConstantPool.CONSTANT_ModuleId_info; +import com.sun.tools.classfile.ConstantPool.CONSTANT_ModuleQuery_info; import com.sun.tools.classfile.ConstantPool.CONSTANT_NameAndType_info; import com.sun.tools.classfile.ConstantPool.CONSTANT_String_info; import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info; @@ -331,6 +333,32 @@ return info; } + public CPInfo visitModuleId(CONSTANT_ModuleId_info info, Map<Object, Object> translations) { + CONSTANT_ModuleId_info info2 = (CONSTANT_ModuleId_info) translations.get(info); + if (info2 == null) { + ConstantPool cp2 = translate(info.cp, translations); + if (cp2 == info.cp) + info2 = info; + else + info2 = new CONSTANT_ModuleId_info(cp2, info.name_index, info.version_index); + translations.put(info, info2); + } + return info; + } + + public CPInfo visitModuleQuery(CONSTANT_ModuleQuery_info info, Map<Object, Object> translations) { + CONSTANT_ModuleQuery_info info2 = (CONSTANT_ModuleQuery_info) translations.get(info); + if (info2 == null) { + ConstantPool cp2 = translate(info.cp, translations); + if (cp2 == info.cp) + info2 = info; + else + info2 = new CONSTANT_ModuleQuery_info(cp2, info.name_index, info.version_index); + translations.put(info, info2); + } + return info; + } + public CPInfo visitNameAndType(CONSTANT_NameAndType_info info, Map<Object, Object> translations) { CONSTANT_NameAndType_info info2 = (CONSTANT_NameAndType_info) translations.get(info); if (info2 == null) { @@ -344,6 +372,7 @@ return info; } + public CPInfo visitMethodref(CONSTANT_Methodref_info info, Map<Object, Object> translations) { CONSTANT_Methodref_info info2 = (CONSTANT_Methodref_info) translations.get(info); if (info2 == null) { @@ -356,7 +385,6 @@ } return info; } - public CPInfo visitMethodHandle(CONSTANT_MethodHandle_info info, Map<Object, Object> translations) { CONSTANT_MethodHandle_info info2 = (CONSTANT_MethodHandle_info) translations.get(info); if (info2 == null) {
--- a/src/share/classes/com/sun/tools/classfile/ClassWriter.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/classfile/ClassWriter.java Tue May 07 17:14:17 2013 -0700 @@ -278,6 +278,18 @@ return 2; } + public Integer visitModuleId(CONSTANT_ModuleId_info info, ClassOutputStream out) { + out.writeShort(info.name_index); + out.writeShort(info.version_index); + return 1; + } + + public Integer visitModuleQuery(CONSTANT_ModuleQuery_info info, ClassOutputStream out) { + out.writeShort(info.name_index); + out.writeShort(info.version_index); + return 1; + } + public Integer visitNameAndType(CONSTANT_NameAndType_info info, ClassOutputStream out) { out.writeShort(info.name_index); out.writeShort(info.type_index); @@ -479,6 +491,57 @@ out.writeShort(entry.index); } + public Void visitModule(Module_attribute attr, ClassOutputStream out) { + out.writeShort(attr.module_id_index); + return null; + } + + public Void visitModuleData(ModuleData_attribute attr, ClassOutputStream out) { + out.writeShort(attr.data_index); + return null; + } + + public Void visitModuleProvides(ModuleProvides_attribute attr, ClassOutputStream out) { + out.writeShort(attr.view_table.length); + for (ModuleProvides_attribute.View v: attr.view_table) + writeView(v, out); + return null; + } + + protected void writeView(ModuleProvides_attribute.View v, ClassOutputStream out) { + out.writeShort(v.view_name_index); + out.writeShort(v.entrypoint_index); + out.writeShort(v.alias_table.length); + for (int alias_index: v.alias_table) + out.writeShort(alias_index); + out.writeShort(v.service_table.length); + for (ModuleProvides_attribute.Service s: v.service_table) { + out.writeShort(s.service_index); + out.writeShort(s.impl_index); + } + out.writeShort(v.export_table.length); + for (int export_index: v.export_table) { + out.writeShort(export_index); + } + out.writeShort(v.permit_table.length); + for (int permit_index: v.permit_table) + out.writeShort(permit_index); + } + + public Void visitModuleRequires(ModuleRequires_attribute attr, ClassOutputStream out) { + out.writeShort(attr.module_table.length); + for (ModuleRequires_attribute.Entry e: attr.module_table) { + out.writeShort(e.index); + out.writeInt(e.flags); + } + out.writeShort(attr.service_table.length); + for (ModuleRequires_attribute.Entry e: attr.service_table) { + out.writeShort(e.index); + out.writeInt(e.flags); + } + return null; + } + public Void visitMethodParameters(MethodParameters_attribute attr, ClassOutputStream out) { out.writeByte(attr.method_parameter_table.length); for (MethodParameters_attribute.Entry e : attr.method_parameter_table) {
--- a/src/share/classes/com/sun/tools/classfile/ConstantPool.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/classfile/ConstantPool.java Tue May 07 17:14:17 2013 -0700 @@ -117,6 +117,8 @@ public static final int CONSTANT_MethodHandle = 15; public static final int CONSTANT_MethodType = 16; public static final int CONSTANT_InvokeDynamic = 18; + public static final int CONSTANT_ModuleId = 19; + public static final int CONSTANT_ModuleQuery = 20; public static enum RefKind { REF_getField(1, "getfield"), @@ -215,6 +217,14 @@ pool[i] = new CONSTANT_Methodref_info(this, cr); break; + case CONSTANT_ModuleId: + pool[i] = new CONSTANT_ModuleId_info(this, cr); + break; + + case CONSTANT_ModuleQuery: + pool[i] = new CONSTANT_ModuleQuery_info(this, cr); + break; + case CONSTANT_NameAndType: pool[i] = new CONSTANT_NameAndType_info(this, cr); break; @@ -278,6 +288,14 @@ return ((CONSTANT_Class_info) get(index, CONSTANT_Class)); } + public CONSTANT_ModuleId_info getModuleIdInfo(int index) throws InvalidIndex, UnexpectedEntry { + return ((CONSTANT_ModuleId_info) get(index, CONSTANT_ModuleId)); + } + + public CONSTANT_ModuleQuery_info getModuleQueryInfo(int index) throws InvalidIndex, UnexpectedEntry { + return ((CONSTANT_ModuleQuery_info) get(index, CONSTANT_ModuleQuery)); + } + public CONSTANT_NameAndType_info getNameAndTypeInfo(int index) throws InvalidIndex, UnexpectedEntry { return ((CONSTANT_NameAndType_info) get(index, CONSTANT_NameAndType)); } @@ -341,6 +359,8 @@ R visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, P p); R visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, P p); R visitLong(CONSTANT_Long_info info, P p); + R visitModuleId(CONSTANT_ModuleId_info info, P p); + R visitModuleQuery(CONSTANT_ModuleQuery_info info, P p); R visitNameAndType(CONSTANT_NameAndType_info info, P p); R visitMethodref(CONSTANT_Methodref_info info, P p); R visitMethodHandle(CONSTANT_MethodHandle_info info, P p); @@ -783,6 +803,91 @@ } } + public static class CONSTANT_ModuleId_info extends CPInfo { + CONSTANT_ModuleId_info(ConstantPool cp, ClassReader cr) throws IOException { + super(cp); + name_index = cr.readUnsignedShort(); + version_index = cr.readUnsignedShort(); + } + + public CONSTANT_ModuleId_info(ConstantPool cp, int name_index, int version_index) { + super(cp); + this.name_index = name_index; + this.version_index = version_index; + } + + public int getTag() { + return CONSTANT_ModuleId; + } + + public String getName() throws ConstantPoolException { + return cp.getUTF8Value(name_index); + } + + public int byteLength() { + return 5; + } + + public String getVersion() throws ConstantPoolException { + return (version_index == 0 ? null : cp.getUTF8Value(version_index)); + } + + @Override + public String toString() { + return "CONSTANT_ModuleId_info[name_index: " + name_index + ", version_index: " + version_index + "]"; + } + + public <R, D> R accept(Visitor<R, D> visitor, D data) { + return visitor.visitModuleId(this, data); + } + + public final int name_index; + public final int version_index; + } + + + public static class CONSTANT_ModuleQuery_info extends CPInfo { + CONSTANT_ModuleQuery_info(ConstantPool cp, ClassReader cr) throws IOException { + super(cp); + name_index = cr.readUnsignedShort(); + version_index = cr.readUnsignedShort(); + } + + public CONSTANT_ModuleQuery_info(ConstantPool cp, int name_index, int version_index) { + super(cp); + this.name_index = name_index; + this.version_index = version_index; + } + + public int getTag() { + return CONSTANT_ModuleQuery; + } + + public String getName() throws ConstantPoolException { + return cp.getUTF8Value(name_index); + } + + public int byteLength() { + return 5; + } + + public String getVersion() throws ConstantPoolException { + return (version_index == 0 ? null : cp.getUTF8Value(version_index)); + } + + @Override + public String toString() { + return "CONSTANT_ModuleQuery_info[name_index: " + name_index + ", version_index: " + version_index + "]"; + } + + public <R, D> R accept(Visitor<R, D> visitor, D data) { + return visitor.visitModuleQuery(this, data); + } + + public final int name_index; + public final int version_index; + } + public static class CONSTANT_NameAndType_info extends CPInfo { CONSTANT_NameAndType_info(ConstantPool cp, ClassReader cr) throws IOException { super(cp); @@ -812,15 +917,15 @@ return cp.getUTF8Value(type_index); } - public <R, D> R accept(Visitor<R, D> visitor, D data) { - return visitor.visitNameAndType(this, data); - } - @Override public String toString() { return "CONSTANT_NameAndType_info[name_index: " + name_index + ", type_index: " + type_index + "]"; } + public <R, D> R accept(Visitor<R, D> visitor, D data) { + return visitor.visitNameAndType(this, data); + } + public final int name_index; public final int type_index; }
--- a/src/share/classes/com/sun/tools/classfile/Dependencies.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/classfile/Dependencies.java Tue May 07 17:14:17 2013 -0700 @@ -709,6 +709,14 @@ return visitRef(info, p); } + public Void visitModuleId(CONSTANT_ModuleId_info info, Void p) { + return null; + } + + public Void visitModuleQuery(CONSTANT_ModuleQuery_info info, Void p) { + return null; + } + public Void visitNameAndType(CONSTANT_NameAndType_info info, Void p) { try { new Signature(info.type_index).getType(constant_pool).accept(this, null);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/classfile/ModuleData_attribute.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.classfile; + +import java.io.IOException; + +import com.sun.tools.classfile.ConstantPool.*; + +/** + * See Jigsaw. + * + * <p><b>This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice.</b> + */ +public class ModuleData_attribute extends Attribute { + ModuleData_attribute(ClassReader cr, int name_index, int length) throws IOException { + super(name_index, length); + data_index = cr.readUnsignedShort(); + } + + public ModuleData_attribute(int name_index, int data_index) { + super(name_index, 2); + this.data_index = data_index; + } + + public String getData(ConstantPool constant_pool) throws ConstantPoolException { + if (data_index == 0) + return null; + return constant_pool.getUTF8Info(data_index).value; + } + + public <R, D> R accept(Visitor<R, D> visitor, D data) { + return visitor.visitModuleData(this, data); + } + + public final int data_index; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/classfile/ModuleProvides_attribute.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.classfile; + +import java.io.IOException; + +/** + * See Jigsaw. + * + * <p><b>This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice.</b> + */ +public class ModuleProvides_attribute extends Attribute { + ModuleProvides_attribute(ClassReader cr, int name_index, int length) throws IOException { + super(name_index, length); + view_length = cr.readUnsignedShort(); + view_table = new View[view_length]; + for (int i = 0; i < view_length; i++) + view_table[i] = new View(cr); + } + + public ModuleProvides_attribute(ConstantPool constant_pool, View[] provides_table) + throws ConstantPoolException { + this(constant_pool.getUTF8Index(Attribute.ModuleProvides), provides_table); + } + + public ModuleProvides_attribute(int name_index, View[] view_table) { + super(name_index, 2 + length(view_table)); + this.view_length = view_table.length; + this.view_table = view_table; + } + + public <R, D> R accept(Visitor<R, D> visitor, D data) { + return visitor.visitModuleProvides(this, data); + } + + public final int view_length; + public final View[] view_table; + + private static int length(View[] view_table) { + int n = 0; + for (View v: view_table) + n += v.length(); + return n; + } + + public static class View { + public final int view_name_index; + public final int entrypoint_index; + public final int alias_length; + public final int[] alias_table; + public final int service_length; + public final Service[] service_table; + public final int export_length; + public final int[] export_table; + public final int permit_length; + public final int[] permit_table; + + View(ClassReader cr) throws IOException { + view_name_index = cr.readUnsignedShort(); + entrypoint_index = cr.readUnsignedShort(); + alias_length = cr.readUnsignedShort(); + alias_table = new int[alias_length]; + for (int i = 0; i < alias_table.length; i++) + alias_table[i] = cr.readUnsignedShort(); + service_length = cr.readUnsignedShort(); + service_table = new Service[service_length]; + for (int i = 0; i < service_table.length; i++) + service_table[i] = new Service(cr); + export_length = cr.readUnsignedShort(); + export_table = new int[export_length]; + for (int i = 0; i < export_table.length; i++) + export_table[i] = cr.readUnsignedShort(); + permit_length = cr.readUnsignedShort(); + permit_table = new int[permit_length]; + for (int i = 0; i < permit_table.length; i++) + permit_table[i] = cr.readUnsignedShort(); + } + + public View(int view_name_index, int entrypoint_index, + int[] alias_table, Service[] service_table, + int[] export_table, int[] permit_table) + { + this.view_name_index = view_name_index; + this.entrypoint_index = entrypoint_index; + this.alias_length = alias_table.length; + this.alias_table = alias_table; + this.export_length = export_table.length; + this.export_table = export_table; + this.permit_length = permit_table.length; + this.permit_table = permit_table; + this.service_length = service_table.length; + this.service_table = service_table; + } + + int length() { + return 2 // view_name_index + + 2 // entrypoint_index + + 2 + 2 * alias_table.length + + 2 + Service.length * service_table.length + + 2 + 2 * export_table.length + + 2 + 2 * permit_table.length; + + } + } + + public static class Service { + static final int length = 4; + + public final int service_index; + public final int impl_index; + + Service(ClassReader cr) throws IOException { + service_index = cr.readUnsignedShort(); + impl_index = cr.readUnsignedShort(); + } + + public Service(int service_index, int impl_index) { + this.service_index = service_index; + this.impl_index = impl_index; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/classfile/ModuleRequires_attribute.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.classfile; + +import java.io.IOException; + +/** + * See Jigsaw. + * + * <p><b>This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice.</b> + */ +public class ModuleRequires_attribute extends Attribute { + public static final int ACC_OPTIONAL = 0x1; + public static final int ACC_LOCAL = 0x2; + public static final int ACC_REEXPORT = 0x4; + public static final int ACC_SYNTHETIC = 0x1000; + public static final int ACC_SYNTHESIZED = 0x10000; + + ModuleRequires_attribute(ClassReader cr, int name_index, int length) throws IOException { + super(name_index, length); + module_length = cr.readUnsignedShort(); + module_table = new Entry[module_length]; + for (int i = 0; i < module_length; i++) + module_table[i] = new Entry(cr); + service_length = cr.readUnsignedShort(); + service_table = new Entry[service_length]; + for (int i = 0; i < service_length; i++) + service_table[i] = new Entry(cr); + } + + public ModuleRequires_attribute(ConstantPool constant_pool, Entry[] module_table, Entry[] service_table) + throws ConstantPoolException { + this(constant_pool.getUTF8Index(Attribute.ModuleRequires), module_table, service_table); + } + + public ModuleRequires_attribute(int name_index, Entry[] module_table, Entry[] service_table) { + super(name_index, 2 + length(module_table) + 2 + length(service_table)); + this.module_length = module_table.length; + this.module_table = module_table; + this.service_length = service_table.length; + this.service_table = service_table; + } + + public <R, D> R accept(Visitor<R, D> visitor, D data) { + return visitor.visitModuleRequires(this, data); + } + + public final int module_length; + public final Entry[] module_table; + public final int service_length; + public final Entry[] service_table; + + private static int length(Entry[] table) { + return table.length * Entry.length; + } + + public static class Entry { + Entry(ClassReader cr) throws IOException { + index = cr.readUnsignedShort(); + flags = cr.readInt(); + } + + public Entry(int index, int flags) { + this.index = index; + this.flags = flags; + } + + public static final int length = 4; + + public final int index; + public final int flags; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/classfile/Module_attribute.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.classfile; + +import java.io.IOException; + +/** + * See Jigsaw. + * + * <p><b>This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice.</b> + */ +public class Module_attribute extends Attribute { + Module_attribute(ClassReader cr, int name_index, int length) throws IOException { + super(name_index, length); + module_id_index = cr.readUnsignedShort(); + } + + public Module_attribute(int name_index, int module_id_index) { + super(name_index, 2); + this.module_id_index = module_id_index; + } + + public String getModuleName(ConstantPool constant_pool) throws ConstantPoolException { + return constant_pool.getModuleIdInfo(module_id_index).getName(); + } + + public String getModuleVersion(ConstantPool constant_pool) throws ConstantPoolException { + return constant_pool.getModuleIdInfo(module_id_index).getVersion(); + } + + public <R, D> R accept(Visitor<R, D> visitor, D data) { + return visitor.visitModule(this, data); + } + + public final int module_id_index; + +}
--- a/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java Tue May 07 17:14:17 2013 -0700 @@ -55,6 +55,7 @@ import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileObject; import javax.tools.JavaFileObject.Kind; +import javax.tools.ModuleFileManager; import com.sun.source.util.TaskEvent; import com.sun.source.util.TaskListener; @@ -111,13 +112,16 @@ } public JavaFileManager wrap(JavaFileManager fm) { - if (isTrusted(fm)) + if (fm == null || isTrusted(fm)) return fm; - return new WrappedJavaFileManager(fm); + if (fm instanceof ModuleFileManager) + return new WrappedModuleFileManager(fm); + else + return new WrappedJavaFileManager(fm); } public FileObject wrap(FileObject fo) { - if (isTrusted(fo)) + if (fo == null || isTrusted(fo)) return fo; return new WrappedFileObject(fo); } @@ -130,7 +134,7 @@ } public JavaFileObject wrap(JavaFileObject fo) { - if (isTrusted(fo)) + if (fo == null || isTrusted(fo)) return fo; return new WrappedJavaFileObject(fo); } @@ -150,13 +154,13 @@ } public <T /*super JavaFileOject*/> DiagnosticListener<T> wrap(DiagnosticListener<T> dl) { - if (isTrusted(dl)) + if (dl == null || isTrusted(dl)) return dl; return new WrappedDiagnosticListener<T>(dl); } TaskListener wrap(TaskListener tl) { - if (isTrusted(tl)) + if (tl == null || isTrusted(tl)) return tl; return new WrappedTaskListener(tl); } @@ -387,7 +391,63 @@ } } - protected class WrappedFileObject implements FileObject { + protected class WrappedModuleFileManager extends WrappedJavaFileManager implements ModuleFileManager { + protected ModuleFileManager clientModuleFileManager; + WrappedModuleFileManager(JavaFileManager clientJavaFileManager) { + super(clientJavaFileManager); + this.clientModuleFileManager = (ModuleFileManager) clientJavaFileManager; + } + + public ModuleMode getModuleMode() { + try { + return ((clientModuleFileManager).getModuleMode()); + } catch (ClientCodeException e) { + throw e; + } catch (RuntimeException e) { + throw new ClientCodeException(e); + } catch (Error e) { + throw new ClientCodeException(e); + } + } + + public Location getModuleLocation(Location location, JavaFileObject fo, String packageName) throws IllegalArgumentException { + try { + return ((clientModuleFileManager).getModuleLocation(location, unwrap(fo), packageName)); + } catch (ClientCodeException e) { + throw e; + } catch (RuntimeException e) { + throw new ClientCodeException(e); + } catch (Error e) { + throw new ClientCodeException(e); + } + } + + public Iterable<? extends Location> getModuleLocations(Location location) { + try { + return ((clientModuleFileManager).getModuleLocations(location)); + } catch (ClientCodeException e) { + throw e; + } catch (RuntimeException e) { + throw new ClientCodeException(e); + } catch (Error e) { + throw new ClientCodeException(e); + } + } + + public Location join(Iterable<? extends Location> locations) { + try { + return ((clientModuleFileManager).join(locations)); + } catch (ClientCodeException e) { + throw e; + } catch (RuntimeException e) { + throw new ClientCodeException(e); + } catch (Error e) { + throw new ClientCodeException(e); + } + } + } + + protected class WrappedFileObject implements FileObject, FileObject.Locatable { protected FileObject clientFileObject; WrappedFileObject(FileObject clientFileObject) { clientFileObject.getClass(); // null check @@ -512,6 +572,22 @@ } @Override + public Location getLocation() { + try { + if (clientFileObject instanceof Locatable) + return ((Locatable) clientFileObject).getLocation(); + else + return null; + } catch (ClientCodeException e) { + throw e; + } catch (RuntimeException e) { + throw new ClientCodeException(e); + } catch (Error e) { + throw new ClientCodeException(e); + } + } + + @Override public String toString() { return wrappedToString(getClass(), clientFileObject); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/javac/code/Directive.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.code; + +import java.util.EnumSet; +import java.util.Set; +import com.sun.tools.javac.code.Symbol.ClassSymbol; +import com.sun.tools.javac.code.Symbol.PackageSymbol; +import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Name; + + +/** + * Root class for the directives that may appear in module compilation units. + * + * <p><b>This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice.</b> + */ +public abstract class Directive { + public enum Kind { + REQUIRES_MODULE, + REQUIRES_SERVICE, + PROVIDES_MODULE, + PROVIDES_SERVICE, + EXPORTS, + PERMITS, + ENTRYPOINT, + VIEW + } + + /** Flags for RequiresModuleDirective and RequiresServiceDirective. */ + public enum RequiresFlag { + OPTIONAL(0x0001), + LOCAL(0x0002), + REEXPORT(0x0004), + SYNTHETIC(0x1000), + SYNTHESIZED(0x10000); + + // overkill? move to ClassWriter? + public static int value(Set<RequiresFlag> s) { + int v = 0; + for (RequiresFlag f: s) + v |= f.value; + return v; + } + + RequiresFlag(int value) { + this.value = value; + } + + public final int value; + } + + public abstract Kind getKind(); + + abstract <R, P> R accept(Visitor<R, P> visitor, P data); + + static <T extends Directive> List<T> filter(List<Directive> directives, Kind kind, Class<T> clazz) { + ListBuffer<T> list = ListBuffer.lb(); + for (Directive d: directives) { + if (d.getKind() == kind) + list.add(clazz.cast(d)); + } + return list.toList(); + } + + /** + * 'requires' ['optional'] {'local' | 'public'} ModuleNameAndVersionQuery ';' + */ + public static class RequiresModuleDirective extends Directive { + public final ModuleQuery moduleQuery; + public final Set<RequiresFlag> flags; + + public RequiresModuleDirective(ModuleQuery moduleQuery) { + this(moduleQuery, EnumSet.noneOf(RequiresFlag.class)); + } + + public RequiresModuleDirective(ModuleQuery moduleQuery, Set<RequiresFlag> flags) { + this.moduleQuery = moduleQuery; + this.flags = flags; + } + + @Override + public Kind getKind() { + return Kind.REQUIRES_MODULE; + } + + @Override + public String toString() { + return "RequiresModule[" + flags + "," + moduleQuery + "]"; + } + + @Override + public <R, P> R accept(Visitor<R, P> visitor, P data) { + return visitor.visitRequiresModule(this, data); + } + } + + /** + * 'requires' ['optional'] 'service' ServiceName ';' + */ + public static class RequiresServiceDirective extends Directive { + public final ClassSymbol sym; + public final Set<RequiresFlag> flags; + + public RequiresServiceDirective(ClassSymbol sym, Set<RequiresFlag> flags) { + this.sym = sym; + this.flags = flags; + } + + @Override + public Kind getKind() { + return Kind.REQUIRES_SERVICE; + } + + @Override + public String toString() { + return "RequiresService[" + flags + "," + sym + "]"; + } + + @Override + public <R, P> R accept(Visitor<R, P> visitor, P data) { + return visitor.visitRequiresService(this, data); + } + } + + /** + * 'provides' ModuleNameAndVersion ';' + */ + public static class ProvidesModuleDirective extends Directive { + public final ModuleId moduleId; + + public ProvidesModuleDirective(ModuleId moduleId) { + this.moduleId = moduleId; + } + + @Override + public Kind getKind() { + return Kind.PROVIDES_MODULE; + } + + @Override + public String toString() { + return "ProvidesModule[" + moduleId + "]"; + } + + @Override + public <R, P> R accept(Visitor<R, P> visitor, P data) { + return visitor.visitProvidesModule(this, data); + } + } + + /** + * 'provides' 'service' ServiceName 'with' QualifiedIdentifer ';' + */ + public static class ProvidesServiceDirective extends Directive { + public final ClassSymbol service; + public final ClassSymbol impl; + + public ProvidesServiceDirective(ClassSymbol service, ClassSymbol impl) { + this.service = service; + this.impl = impl; + } + + @Override + public Kind getKind() { + return Kind.PROVIDES_SERVICE; + } + + @Override + public String toString() { + return "ProvidesService[" + service + "," + impl + "]"; + } + + @Override + public <R, P> R accept(Visitor<R, P> visitor, P data) { + return visitor.visitProvidesService(this, data); + } + } + + /** + * 'exports' Package ';' + */ + public static class ExportsDirective extends Directive { + public final PackageSymbol sym; + + public ExportsDirective(PackageSymbol sym) { + this.sym = sym; + } + + @Override + public Kind getKind() { + return Kind.EXPORTS; + } + + @Override + public String toString() { + return "Exports[" + sym + "]"; + } + + @Override + public <R, P> R accept(Visitor<R, P> visitor, P data) { + return visitor.visitExports(this, data); + } + } + + /** + * 'permits' ModuleName ';' + */ + public static class PermitsDirective extends Directive { + public final ModuleId moduleId; + + public PermitsDirective(ModuleId moduleId) { + this.moduleId = moduleId; + } + + public PermitsDirective(Name moduleName) { + moduleId = new ModuleId(moduleName); + } + + @Override + public Kind getKind() { + return Kind.PERMITS; + } + + @Override + public String toString() { + return "Permits[" + moduleId + "]"; + } + + @Override + public <R, P> R accept(Visitor<R, P> visitor, P data) { + return visitor.visitPermits(this, data); + } + } + + /** + * 'class' TypeName ';' + */ + public static class EntrypointDirective extends Directive { + public final ClassSymbol sym; + + public EntrypointDirective(ClassSymbol sym) { + this.sym = sym; + } + + @Override + public Kind getKind() { + return Kind.ENTRYPOINT; + } + + @Override + public String toString() { + return "Entrypoint[" + sym + "]"; + } + + @Override + public <R, P> R accept(Visitor<R, P> visitor, P data) { + return visitor.visitEntrypoint(this, data); + } + } + + /** + * 'view' ModuleName '{' {ProvidesDirective | ExportsDirective | PermitsDirective | EntrypointDirective} '}' + */ + public static class ViewDeclaration extends Directive { + public final Name name; + public final List<Directive> directives; + + public ViewDeclaration(Name name, List<Directive> directives) { + this.name = name; + this.directives = directives; + } + + public ViewDeclaration(List<Directive> directives) { + this.name = null; + this.directives = directives; + } + + public boolean isDefault() { + return name == null; + } + + public boolean hasEntrypoint() { + for (Directive d: directives) { + if (d.getKind() == Directive.Kind.ENTRYPOINT) + return true; + } + return false; + } + + public ClassSymbol getEntrypoint() { + List<EntrypointDirective> list = + filter(directives, Kind.ENTRYPOINT, EntrypointDirective.class); + return list.isEmpty() ? null : list.head.sym; + } + + public List<ProvidesModuleDirective> getAliases() { + return filter(directives, Kind.PROVIDES_MODULE, ProvidesModuleDirective.class); + } + + public List<ProvidesServiceDirective> getServices() { + return filter(directives, Kind.PROVIDES_SERVICE, ProvidesServiceDirective.class); + } + + public List<ExportsDirective> getExports() { + return filter(directives, Kind.EXPORTS, ExportsDirective.class); + } + + public List<PermitsDirective> getPermits() { + return filter(directives, Kind.PERMITS, PermitsDirective.class); + } + + @Override + public Kind getKind() { + return Kind.VIEW; + } + + @Override + public String toString() { + return "View[" + directives + "]"; + } + + @Override + public <R, P> R accept(Visitor<R, P> visitor, P data) { + return visitor.visitView(this, data); + } + } + + public static interface Visitor<R, P> { + R visitRequiresModule(RequiresModuleDirective d, P p); + R visitRequiresService(RequiresServiceDirective d, P p); + R visitProvidesModule(ProvidesModuleDirective d, P p); + R visitProvidesService(ProvidesServiceDirective d, P p); + R visitExports(ExportsDirective d, P p); + R visitPermits(PermitsDirective d, P p); + R visitEntrypoint(EntrypointDirective d, P p); + R visitView(ViewDeclaration d, P p); + } + + public static class SimpleVisitor<R, P> implements Visitor<R, P> { + protected final R DEFAULT_VALUE; + + protected SimpleVisitor() { + DEFAULT_VALUE = null; + } + + protected SimpleVisitor(R defaultValue) { + DEFAULT_VALUE = defaultValue; + } + + protected R defaultAction(Directive d, P p) { + return DEFAULT_VALUE; + } + + public final R visit(Directive d, P p) { + return (d == null) ? null : d.accept(this, p); + } + + public final R visit(Iterable<? extends Directive> ds, P p) { + R r = null; + if (ds != null) + for (Directive d : ds) + r = visit(d, p); + return r; + } + + public R visitRequiresModule(RequiresModuleDirective d, P p) { + return defaultAction(d, p); + } + + public R visitRequiresService(RequiresServiceDirective d, P p) { + return defaultAction(d, p); + } + + public R visitProvidesModule(ProvidesModuleDirective d, P p) { + return defaultAction(d, p); + } + + public R visitProvidesService(ProvidesServiceDirective d, P p) { + return defaultAction(d, p); + } + + public R visitExports(ExportsDirective d, P p) { + return defaultAction(d, p); + } + + public R visitPermits(PermitsDirective d, P p) { + return defaultAction(d, p); + } + + public R visitEntrypoint(EntrypointDirective d, P p) { + return defaultAction(d, p); + } + + public R visitView(ViewDeclaration d, P p) { + return defaultAction(d, p); + } + } + + public static class Scanner<R, P> implements Visitor<R, P> { + + + /** Scan a single node. + */ + public R scan(Directive d, P p) { + return (d == null) ? null : d.accept(this, p); + } + + private R scanAndReduce(Directive d, P p, R r) { + return reduce(scan(d, p), r); + } + + /** Scan a list of nodes. + */ + public R scan(Iterable<? extends Directive> ds, P p) { + R r = null; + if (ds != null) { + boolean first = true; + for (Directive d : ds) { + r = (first ? scan(d, p) : scanAndReduce(d, p, r)); + first = false; + } + } + return r; + } + + /** + * Reduces two results into a combined result. + * The default implementation is to return the first parameter. + * The general contract of the method is that it may take any action whatsoever. + */ + public R reduce(R r1, R r2) { + return r1; + } + + public R visitRequiresModule(RequiresModuleDirective d, P p) { + return null; + } + + public R visitRequiresService(RequiresServiceDirective d, P p) { + return null; + } + + public R visitProvidesModule(ProvidesModuleDirective d, P p) { + return null; + } + + public R visitProvidesService(ProvidesServiceDirective d, P p) { + return null; + } + + public R visitExports(ExportsDirective d, P p) { + return null; + } + + public R visitPermits(PermitsDirective d, P p) { + return null; + } + + public R visitEntrypoint(EntrypointDirective d, P p) { + return null; + } + + public R visitView(ViewDeclaration d, P p) { + return scan(d.directives, p); + } + + } +}
--- a/src/share/classes/com/sun/tools/javac/code/Flags.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Flags.java Tue May 07 17:14:17 2013 -0700 @@ -378,6 +378,7 @@ this.name = name; } + @Override public String toString() { return name; }
--- a/src/share/classes/com/sun/tools/javac/code/Kinds.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Kinds.java Tue May 07 17:14:17 2013 -0700 @@ -73,9 +73,13 @@ */ public final static int MTH = 1 << 4; + /** The kind of modules. + */ + public final static int MDL = 1 << 5; + /** The error kind, which includes all other kinds. */ - public final static int ERR = (1 << 5) - 1; + public final static int ERR = (1 << 6) - 1; /** The set of all kinds. */ @@ -108,7 +112,8 @@ CLASS("kindname.class"), STATIC_INIT("kindname.static.init"), INSTANCE_INIT("kindname.instance.init"), - PACKAGE("kindname.package"); + PACKAGE("kindname.package"), + MODULE("kindname.module"); private final String name;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/javac/code/ModuleId.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.code; + +import com.sun.tools.javac.api.Formattable; +import com.sun.tools.javac.api.Messages; +import com.sun.tools.javac.util.Name; +import java.util.Locale; + +/** + * Representation of a module id, {@literal module-name[@version]} + * + * <p><b>This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice.</b> + */ +public class ModuleId implements javax.lang.model.element.ModuleElement.ModuleId, Formattable { + public final Name name; + public final Name version; + + public ModuleId(Name name) { + this.name = name; + this.version = null; + } + + public ModuleId(Name name, Name version) { + this.name = name; + this.version = version; + } + + public CharSequence getName() { + return name; + } + + public CharSequence getVersion() { + return version; + } + + public ModuleQuery toQuery() { + return new ModuleQuery(name, version); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof ModuleId)) + return false; + + ModuleId m = (ModuleId) other; + if (name != m.name) + return false; + + return (version == null ? m.version == null : version.equals(m.version)); + } + + @Override + public int hashCode() { + if (version == null) { + return name.hashCode(); + } else { + return name.hashCode() * version.hashCode(); + } + } + + // for debugging + @Override + public String toString() { + return "ModuleId[" + name + (version == null ? "" : "@" + version) + "]"; + } + + // for use in diagnostics + @Override + public String toString(Locale locale, Messages messages) { + return version == null ? name.toString() : name + "@" + version; + } + + public String getKind() { + return "ModuleId"; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/javac/code/ModuleQuery.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.code; + +import java.util.Locale; + +import com.sun.tools.javac.api.Formattable; +import com.sun.tools.javac.api.Messages; +import com.sun.tools.javac.util.Name; + +/** + * Representation of a module query, @literal{module-name@version-query} + * + * <p><b>This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice.</b> + */ +public class ModuleQuery implements javax.lang.model.element.ModuleElement.ModuleQuery, Formattable { + public final Name name; + public final Name versionQuery; + + public ModuleQuery(Name name, Name version) { + this.name = name; + this.versionQuery = version; + } + + public CharSequence getName() { + return name; + } + + public CharSequence getVersionQuery() { + return versionQuery; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof ModuleQuery)) + return false; + + ModuleQuery m = (ModuleQuery) other; + if (name != m.name) + return false; + + return (versionQuery == null) ? (m.versionQuery == null) + : versionQuery.equals(m.versionQuery); + } + + @Override + public int hashCode() { + if (versionQuery == null) { + return name.hashCode(); + } else { + return name.hashCode() * versionQuery.hashCode(); + } + } + + // for debugging + @Override + public String toString() { + return "ModuleQuery[" + name + (versionQuery == null ? "" : "@" + versionQuery) + "]"; + } + + // for use in diagnostics + @Override + public String toString(Locale locale, Messages messages) { + return versionQuery == null ? name.toString() : name + "@" + versionQuery; + } + + public String getKind() { + return "ModuleQuery"; + } + +}
--- a/src/share/classes/com/sun/tools/javac/code/Printer.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Printer.java Tue May 07 17:14:17 2013 -0700 @@ -244,6 +244,11 @@ } } + @Override + public String visitModuleType(ModuleType t, Locale locale) { + return visitType(t, locale); + } + public String visitType(Type t, Locale locale) { String s = (t.tsym == null || t.tsym.name == null) ? localize(locale, "compiler.misc.type.none")
--- a/src/share/classes/com/sun/tools/javac/code/Scope.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Scope.java Tue May 07 17:14:17 2013 -0700 @@ -107,7 +107,7 @@ this.nelems = nelems; } - /** Construct a new scope, within scope next, with given owner, + /** Construct a new scope, with given owner, * using a fresh table of length INITIAL_SIZE. */ public Scope(Symbol owner) {
--- a/src/share/classes/com/sun/tools/javac/code/Source.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Source.java Tue May 07 17:14:17 2013 -0700 @@ -167,6 +167,9 @@ public boolean allowAnonOuterThis() { return compareTo(JDK1_5) >= 0; } + public boolean allowModules() { + return compareTo(JDK1_7) >= 0; + } public boolean addBridges() { return compareTo(JDK1_5) >= 0; }
--- a/src/share/classes/com/sun/tools/javac/code/Symbol.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java Tue May 07 17:14:17 2013 -0700 @@ -25,12 +25,15 @@ package com.sun.tools.javac.code; +import java.util.LinkedHashSet; import java.util.Set; import java.util.concurrent.Callable; import javax.lang.model.element.*; +import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; +import com.sun.tools.javac.code.Directive.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.comp.Attr; import com.sun.tools.javac.comp.AttrContext; @@ -323,6 +326,13 @@ return (PackageSymbol) sym; } + /** The module which indirectly owns this symbol. + */ + public ModuleSymbol modle() { + ClassSymbol c = outermostClass(); + return c == null ? null : c.modle; + } + /** Is this symbol a subclass of `base'? Only defined for ClassSymbols. */ public boolean isSubClass(Symbol base, Types types) { @@ -662,6 +672,156 @@ } } + /** A class for module symbols. + */ + public static class ModuleSymbol extends TypeSymbol implements ModuleElement // JIGSAW need TypeSymbol? + /*implements ModuleElement*/ { + + public Name fullname; + public Name version; + + /** All directives, in natural order. */ + public List<Directive> directives; + + /** An uninterpreted sequence of characters associated with the module. */ + public Name extendedMetadata; + + public ClassSymbol module_info; + + public JavaFileManager.Location location; + + public ModuleSymbol() { + super(MDL, 0, null, null, null); + this.type = new ModuleType(this); + } + + public ModuleSymbol(Name name, Symbol owner) { + super(MDL, 0, name, null, owner); + this.type = new ModuleType(this); + this.fullname = formFullName(name, owner); + } + + // Currently ModuleId is defined in ModuleElement, which means + public com.sun.tools.javac.code.ModuleId getModuleId() { + return new com.sun.tools.javac.code.ModuleId(fullname, version); + } + + public boolean hasRequires() { + for (Directive d: directives) { + switch (d.getKind()) { + case REQUIRES_MODULE: + case REQUIRES_SERVICE: + return true; + } + } + return false; + } + + public List<RequiresModuleDirective> getRequiredModules() { + return Directive.filter(directives, Directive.Kind.REQUIRES_MODULE, + RequiresModuleDirective.class); + } + + public List<RequiresServiceDirective> getRequiredServices() { + return Directive.filter(directives, Directive.Kind.REQUIRES_SERVICE, + RequiresServiceDirective.class); + } + + public boolean hasViews() { + for (Directive d: directives) { + switch (d.getKind()) { + case REQUIRES_MODULE: + case REQUIRES_SERVICE: + continue; + default: + return true; + } + } + return false; + } + + public ViewDeclaration getDefaultView() { + ListBuffer<Directive> defaultViewDirectives = ListBuffer.lb(); + for (Directive d: directives) { + switch (d.getKind()) { + case PROVIDES_MODULE: + case PROVIDES_SERVICE: + case EXPORTS: + case PERMITS: + case ENTRYPOINT: + defaultViewDirectives.add(d); + } + } + return new ViewDeclaration(defaultViewDirectives.toList()); + } + + public List<ViewDeclaration> getViews() { + ListBuffer<Directive> defaultViewDirectives = ListBuffer.lb(); + for (Directive d: directives) { + switch (d.getKind()) { + case PROVIDES_MODULE: + case PROVIDES_SERVICE: + case EXPORTS: + case PERMITS: + case ENTRYPOINT: + defaultViewDirectives.add(d); + } + } + List<ViewDeclaration> views = + Directive.filter(directives, Directive.Kind.VIEW, + ViewDeclaration.class); + if (defaultViewDirectives.nonEmpty()) + views = views.prepend(new ViewDeclaration(defaultViewDirectives.toList())); + return views; + } + + public boolean hasExtendedMetadata() { + return (extendedMetadata != null) && !extendedMetadata.isEmpty(); + } + + public Set<PackageSymbol> getExports(final ViewDeclaration viewDecl) { + final Set<PackageSymbol> exports = new LinkedHashSet<PackageSymbol>(); + Directive.Scanner<Void,Void> s = new Directive.Scanner<Void,Void>() { + @Override + public Void visitExports(Directive.ExportsDirective d, Void p) { + exports.add(d.sym); + return null; + } + @Override + public Void visitView(Directive.ViewDeclaration d, Void p) { + if (d == viewDecl) + scan(d.directives, null); + return null; + } + }; + s.scan(directives, null); + return exports; + } + + @Override + public String toString() { + // the following strings should be localized + String n = (fullname == null) ? "<unknown>" + : (fullname.isEmpty()) ? "<unnamed>" + : String.valueOf(fullname); + return (version == null) ? n : n + "@" + version; + } + + @Override + public Name getQualifiedName() { + return fullname; + } + + public boolean isUnnamed() { + return name.isEmpty() && owner != null; + } + + public <R, P> R accept(ElementVisitor<R, P> v, P p) { + // ## + return v.visit(this, p); + } + } + /** A class for package symbols */ public static class PackageSymbol extends TypeSymbol @@ -748,6 +908,10 @@ /** A class for class symbols */ public static class ClassSymbol extends TypeSymbol implements TypeElement { + /** + * The module for the class. + */ + public ModuleSymbol modle; /** a scope for all class members; variables, methods and inner classes * type parameters are not part of this scope
--- a/src/share/classes/com/sun/tools/javac/code/Symtab.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Symtab.java Tue May 07 17:14:17 2013 -0700 @@ -29,6 +29,7 @@ import javax.lang.model.element.ElementVisitor; import javax.lang.model.type.TypeVisitor; +import javax.tools.JavaFileManager.Location; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; @@ -36,8 +37,8 @@ import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.List; import static com.sun.tools.javac.code.Flags.*; +import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.jvm.ByteCodes.*; -import static com.sun.tools.javac.code.TypeTag.*; /** A class that defines all predefined constants and operators * as well as special classes such as java.lang.Object, which need @@ -80,6 +81,18 @@ private final ClassReader reader; private final Target target; + /** A symbol for the root module. + */ + public final ModuleSymbol rootModule; + + /** A symbol for the unnamed module. + */ + public final ModuleSymbol unnamedModule; + + /** A symbol for no module, for use with -source 7 or less + */ + public final ModuleSymbol noModule; + /** A symbol for the root package. */ public final PackageSymbol rootPackage; @@ -186,7 +199,7 @@ */ public final Type[] typeOfTag = new Type[TypeTag.getTypeTagCount()]; - /** The name of the class that belongs to a basix type tag. + /** The name of the class that belongs to a basic type tag. */ public final Name[] boxedName = new Name[TypeTag.getTypeTagCount()]; @@ -194,6 +207,22 @@ */ public final Set<Name> operatorNames = new HashSet<Name>(); + /** The name of the base module. + */ + public final ModuleId baseModule; + + /** A query for the base module. + */ + public final ModuleQuery baseModuleQuery; + + /** The name of the "legacy JDK" module. + */ + public final ModuleId jdkLegacyModule; + + /** A query for the "legacy JDK" module. + */ + public final ModuleQuery jdkLegacyQuery; + /** A hashtable containing the encountered top-level and member classes, * indexed by flat names. The table does not contain local classes. * It should be updated from the outside to reflect classes defined @@ -207,6 +236,12 @@ */ public final Map<Name, PackageSymbol> packages = new HashMap<Name, PackageSymbol>(); + /** A hashtable containing the encountered modules. + * the table should be updated from outside to reflect modules + * found in the host environment. + */ + public Map<Location,ModuleSymbol> allModules = new LinkedHashMap<Location,ModuleSymbol>(); + public void initType(Type type, ClassSymbol c) { type.tsym = c; typeOfTag[type.tag.ordinal()] = type; @@ -397,14 +432,24 @@ }; // create the basic builtin symbols + final JavacMessages messages = JavacMessages.instance(context); + rootModule = new ModuleSymbol(names.empty, null); + unnamedModule = new ModuleSymbol(names.empty, rootModule) { + @Override + public String toString() { + return messages.getLocalizedString("compiler.misc.unnamed.module"); + } + }; + noModule = new ModuleSymbol(names.empty, rootModule) { }; rootPackage = new PackageSymbol(names.empty, null); - final JavacMessages messages = JavacMessages.instance(context); unnamedPackage = new PackageSymbol(names.empty, rootPackage) { + @Override public String toString() { return messages.getLocalizedString("compiler.misc.unnamed.package"); } }; noSymbol = new TypeSymbol(Kinds.NIL, 0, names.empty, Type.noType, rootPackage) { + @Override public <R, P> R accept(ElementVisitor<R, P> v, P p) { return v.visitUnknown(this, p); } @@ -724,5 +769,13 @@ enterBinop("&&", booleanType, booleanType, booleanType, bool_and); enterBinop("||", booleanType, booleanType, booleanType, bool_or); + + // Create standard module ids and queries + Name v = names.fromString(target.name.replaceAll("^1.", "")); + baseModule = new ModuleId(names.java_base, v); + jdkLegacyModule = new ModuleId(names.jdk_legacy, v); + Name q = names.fromString(">=" + v); + baseModuleQuery = new ModuleQuery(names.java_base, q); + jdkLegacyQuery = new ModuleQuery(names.jdk_legacy, q); } }
--- a/src/share/classes/com/sun/tools/javac/code/Type.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Type.java Tue May 07 17:14:17 2013 -0700 @@ -1122,6 +1122,34 @@ } } + public static class ModuleType extends Type implements NoType { + + ModuleType(TypeSymbol tsym) { + super(TypeTag.MODULE, tsym); + } + + @Override + public <R,S> R accept(Type.Visitor<R,S> v, S s) { + return v.visitModuleType(this, s); + } + + @Override + public String toString() { + return tsym.getQualifiedName().toString(); + } + + @Override + public TypeKind getKind() { + return TypeKind.MODULE; + } + + @Override + public <R, P> R accept(TypeVisitor<R, P> v, P p) { + return v.visitNoType(this, p); + } + } + + public static class TypeVar extends Type implements TypeVariable { /** The upper bound of this type variable; set from outside. @@ -1756,6 +1784,7 @@ R visitArrayType(ArrayType t, S s); R visitMethodType(MethodType t, S s); R visitPackageType(PackageType t, S s); + R visitModuleType(ModuleType t, S s); R visitTypeVar(TypeVar t, S s); R visitCapturedType(CapturedType t, S s); R visitForAll(ForAll t, S s);
--- a/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Tue May 07 17:14:17 2013 -0700 @@ -29,10 +29,8 @@ import javax.lang.model.element.ElementKind; import javax.lang.model.type.TypeKind; -import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Attribute.TypeCompound; -import com.sun.tools.javac.code.Flags; -import com.sun.tools.javac.code.Kinds; +import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Type.AnnotatedType; import com.sun.tools.javac.code.Type.ArrayType; import com.sun.tools.javac.code.Type.CapturedType; @@ -40,6 +38,7 @@ import com.sun.tools.javac.code.Type.ErrorType; import com.sun.tools.javac.code.Type.ForAll; import com.sun.tools.javac.code.Type.MethodType; +import com.sun.tools.javac.code.Type.ModuleType; import com.sun.tools.javac.code.Type.PackageType; import com.sun.tools.javac.code.Type.TypeVar; import com.sun.tools.javac.code.Type.UndetVar; @@ -47,10 +46,9 @@ import com.sun.tools.javac.code.Type.WildcardType; import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry; import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind; -import com.sun.tools.javac.code.TypeTag; -import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.comp.Annotate.Annotator; import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCExpression; @@ -58,7 +56,6 @@ import com.sun.tools.javac.tree.JCTree.JCTypeApply; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.TreeScanner; -import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.Assert; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; @@ -467,6 +464,12 @@ } @Override + public Type visitModuleType(ModuleType t, List<TypeCompound> s) { + // Error? + return t; + } + + @Override public Type visitType(Type t, List<TypeCompound> s) { return new AnnotatedType(s, t); }
--- a/src/share/classes/com/sun/tools/javac/code/TypeTag.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/TypeTag.java Tue May 07 17:14:17 2013 -0700 @@ -90,6 +90,11 @@ */ PACKAGE, + /** The tag of all module "types". + */ + MODULE, + + /** The tag of all (source-level) type variables. */ TYPEVAR,
--- a/src/share/classes/com/sun/tools/javac/code/Types.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java Tue May 07 17:14:17 2013 -0700 @@ -4212,6 +4212,7 @@ public R visitArrayType(ArrayType t, S s) { return visitType(t, s); } public R visitMethodType(MethodType t, S s) { return visitType(t, s); } public R visitPackageType(PackageType t, S s) { return visitType(t, s); } + public R visitModuleType(ModuleType t, S s) { return visitType(t, s); } public R visitTypeVar(TypeVar t, S s) { return visitType(t, s); } public R visitCapturedType(CapturedType t, S s) { return visitType(t, s); } public R visitForAll(ForAll t, S s) { return visitType(t, s); }
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue May 07 17:14:17 2013 -0700 @@ -34,9 +34,15 @@ import com.sun.source.tree.IdentifierTree; import com.sun.source.tree.MemberReferenceTree.ReferenceMode; import com.sun.source.tree.MemberSelectTree; +import com.sun.source.tree.RequiresFlag; import com.sun.source.tree.TreeVisitor; import com.sun.source.util.SimpleTreeVisitor; import com.sun.tools.javac.code.*; +import com.sun.tools.javac.code.Directive.EntrypointDirective; +import com.sun.tools.javac.code.Directive.ExportsDirective; +import com.sun.tools.javac.code.Directive.ProvidesServiceDirective; +import com.sun.tools.javac.code.Directive.RequiresServiceDirective; +import com.sun.tools.javac.code.Directive.ViewDeclaration; import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; @@ -57,6 +63,7 @@ import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.Kinds.ERRONEOUS; import static com.sun.tools.javac.code.TypeTag.*; +import static com.sun.tools.javac.code.TypeTag.PACKAGE; import static com.sun.tools.javac.code.TypeTag.WILDCARD; import static com.sun.tools.javac.tree.JCTree.Tag.*; @@ -94,6 +101,7 @@ final JCDiagnostic.Factory diags; final Annotate annotate; final DeferredLintHandler deferredLintHandler; + final Modules modules; public static Attr instance(Context context) { Attr instance = context.get(attrKey); @@ -122,6 +130,7 @@ diags = JCDiagnostic.Factory.instance(context); annotate = Annotate.instance(context); deferredLintHandler = DeferredLintHandler.instance(context); + modules = Modules.instance(context); Options options = Options.instance(context); @@ -3966,6 +3975,175 @@ return buf.toList(); } + @Override + public void visitModuleDef(JCModuleDecl tree) { + env.info.modcon = modules.getModuleContext(tree); + env.info.modcon.directives.clear(); + attribStats(tree.getDirectives(), env); + env.toplevel.modle.directives = merge(env.info.modcon.directives, + env.toplevel.modle.directives); + } + + @Override + public void visitExports(JCExportDirective tree) { + TypeSymbol tsym = attribTree(tree.qualid, env, new ResultInfo(PCK, Type.noType)).tsym; + if (tsym.kind == PCK) { + ExportsDirective d = new ExportsDirective((PackageSymbol) tsym); + if (env.info.modcon.getDirectives(Directive.Kind.EXPORTS, d.sym.fullname).isEmpty()) { + env.info.modcon.addDirective(d, tree, d.sym.fullname); + } else { + log.error(tree.qualid, "dupl.exports", d.sym); + } + } + } + + @Override + public void visitProvidesModule(JCProvidesModuleDirective tree) { + Directive d = env.info.modcon.directiveForTree.get(tree); + if (d != null) + env.info.modcon.directives.add(d); + } + + @Override + public void visitProvidesService(JCProvidesServiceDirective tree) { + TypeSymbol srvc = attribTree(tree.serviceName, env, unknownTypeInfo).tsym; + TypeSymbol impl = attribTree(tree.implName, env, unknownTypeInfo).tsym; + if (srvc.kind != ERR && impl.kind != ERR) { + if ((impl.flags() & ABSTRACT) != 0) { + log.error(tree.implName, "service.impl.is.abstract", impl); + return; + } + + if ((impl.flags() & PUBLIC) == 0) { + log.error(tree.implName, "service.impl.not.public", impl); + return; + } + + boolean hasPublicNoArgsConstructor = false; + for (Scope.Entry e = impl.members().lookup(names.init); e.scope != null; e = e.next()) { + if (e.sym.kind == MTH && ((e.sym.flags() & PUBLIC) != 0) + && ((MethodSymbol) e.sym).params().isEmpty()) { + hasPublicNoArgsConstructor = true; + break; + } + } + if (!hasPublicNoArgsConstructor) { + log.error(tree.implName, "service.impl.no.default.constr", impl); + return; + } + + if (impl.owner.kind != PCK) { + log.error(tree.implName, "service.impl.is.inner", impl); + return; + } + + ProvidesServiceDirective psd = + new ProvidesServiceDirective((ClassSymbol) srvc, (ClassSymbol) impl); + for (Directive d: env.info.modcon.getDirectives(Directive.Kind.PROVIDES_SERVICE, psd.service.fullname)) { + if (d.getKind().equals(Directive.Kind.PROVIDES_SERVICE)) { + if (psd.impl.fullname == ((ProvidesServiceDirective) d).impl.fullname) { + log.error(tree.implName, "dupl.provides.service", psd.service, psd.impl); + return; + } + } + } + + env.info.modcon.addDirective(psd, tree, psd.service.fullname); + } + } + + @Override + public void visitRequiresModule(JCRequiresModuleDirective tree) { + Directive d = env.info.modcon.directiveForTree.get(tree); + if (d != null) + env.info.modcon.directives.add(d); + } + + @Override + public void visitRequiresService(JCRequiresServiceDirective tree) { + Type t = attribType(tree.serviceName, env); + if (t.hasTag(TypeTag.CLASS) && env.tree.hasTag(JCTree.Tag.MODULE)) { + // FIXME: should check for duplicates + Set<Directive.RequiresFlag> flags = EnumSet.noneOf(Directive.RequiresFlag.class); + for (RequiresFlag f: tree.flags) { + switch (f) { + case OPTIONAL: + flags.add(Directive.RequiresFlag.OPTIONAL); + break; + } + } + RequiresServiceDirective d = new RequiresServiceDirective((ClassSymbol) t.tsym, flags); + if (env.info.modcon.getDirectives(Directive.Kind.REQUIRES_SERVICE, d.sym.fullname).isEmpty()) { + env.info.modcon.addDirective(d, tree, d.sym.fullname); + } else { + log.error(tree.serviceName, "dupl.requires.service", d.sym); + } + } + } + + @Override + public void visitPermits(JCPermitsDirective tree) { + Directive d = env.info.modcon.directiveForTree.get(tree); + if (d != null) + env.info.modcon.directives.add(d); + } + + @Override + public void visitEntrypoint(JCEntrypointDirective tree) { + Type t = attribType(tree.qualId, env); + if (t.hasTag(TypeTag.CLASS)) { + Symbol sym = t.tsym; + + boolean hasPublicStaticVoidMain = false; + for (Scope.Entry e = sym.members().lookup(names.main); e.scope != null; e = e.next()) { + int PUBLIC_STATIC = PUBLIC | STATIC; + if (e.sym.kind == MTH && ((e.sym.flags() & PUBLIC_STATIC) == PUBLIC_STATIC)) { + MethodSymbol m = (MethodSymbol) e.sym; + if (!m.getReturnType().hasTag(TypeTag.VOID)) + continue; + List<VarSymbol> params = m.params(); + if (params.size() != 1) + continue; + VarSymbol p = params.head; + if (types.dimensions(p.type) == 1 + && types.elemtype(p.type).tsym == syms.stringType.tsym) { + hasPublicStaticVoidMain = true; + break; + } + } + } + if (!hasPublicStaticVoidMain) { + log.error(tree.qualId, "no.psv.main", sym); + return; + } + + // Duplicate entrypoints should already have been detected and + // reported in Modules.visitEntrypoint, so here we just act + // defensively to ignore duplicates. + EntrypointDirective d = new EntrypointDirective((ClassSymbol) t.tsym); + if (env.info.modcon.getDirectives(Directive.Kind.ENTRYPOINT, d.sym.fullname).isEmpty()) + env.info.modcon.addDirective(d, tree, d.sym.fullname); + } + } + + @Override + public void visitView(JCViewDecl tree) { + Name name = TreeInfo.fullName(tree.name); + if (env.tree.hasTag(JCTree.Tag.MODULE)) { + ViewDeclaration orig = (ViewDeclaration) env.info.modcon.directiveForTree.get(tree); + Env<AttrContext> prevEnv = env; + env = env.dup(tree, env.info.dup()); + try { + attribStats(tree.directives, env); + } finally { + ViewDeclaration d = new ViewDeclaration(name, + merge(env.info.modcon.directives, orig.directives)); + env = prevEnv; + env.info.modcon.directives.add(d); + } + } + } + public void visitErroneous(JCErroneous tree) { if (tree.errs != null) for (JCTree err : tree.errs) @@ -3979,14 +4157,33 @@ throw new AssertionError(); } + private List<Directive> merge(ListBuffer<Directive> primary, List<Directive> secondary) { + Set<Directive> set = new LinkedHashSet<Directive>(); + set.addAll(primary); + for (Directive d: secondary) { + if (d.getKind() != Directive.Kind.VIEW) + set.add(d); + } + ListBuffer<Directive> results = new ListBuffer<Directive>(); + for (Directive d: set) + results.add(d); + return results.toList(); + } + /** * Attribute an env for either a top level tree or class declaration. */ public void attrib(Env<AttrContext> env) { - if (env.tree.hasTag(TOPLEVEL)) - attribTopLevel(env); - else - attribClass(env.tree.pos(), env.enclClass.sym); + switch (env.tree.getTag()) { + case MODULE: + attribModule(env.tree.pos(), ((JCModuleDecl)env.tree).sym); + break; + case TOPLEVEL: + attribTopLevel(env); + break; + default: + attribClass(env.tree.pos(), env.enclClass.sym); + } } /** @@ -3997,12 +4194,29 @@ JCCompilationUnit toplevel = env.toplevel; try { annotate.flush(); - chk.validateAnnotations(toplevel.packageAnnotations, toplevel.packge); + chk.validateAnnotations(toplevel.getPackageAnnotations(), toplevel.packge); } catch (CompletionFailure ex) { chk.completionError(toplevel.pos(), ex); } } + public void attribModule(DiagnosticPosition pos, ModuleSymbol m) { + try { + annotate.flush(); + attribModule(m); + } catch (CompletionFailure ex) { + chk.completionError(pos, ex); + } + + } + + void attribModule(ModuleSymbol m) { + // Get environment current at the point of module definition. + Env<AttrContext> env = enter.typeEnvs.get(m); + //System.err.println("Attr.attribModule: " + env + " " + env.tree); + attribStat(env.tree, env); + } + /** Main method: attribute class definition associated with given class symbol. * reporting completion failures at the given position. * @param pos The source position at which completion errors are to be
--- a/src/share/classes/com/sun/tools/javac/comp/AttrContext.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/AttrContext.java Tue May 07 17:14:17 2013 -0700 @@ -58,7 +58,7 @@ */ Resolve.MethodResolutionPhase pendingResolutionPhase = null; - /** A record of the lint/SuppressWarnings currently in effect + /** A record of the lint/SuppressWarnings currently in effect. */ Lint lint; @@ -67,6 +67,9 @@ */ Symbol enclVar = null; + /** The module context for the current module. */ + ModuleContext modcon; + /** ResultInfo to be used for attributing 'return' statement expressions * (set by Attr.visitMethod and Attr.visitLambda) */ @@ -87,6 +90,7 @@ info.pendingResolutionPhase = pendingResolutionPhase; info.lint = lint; info.enclVar = enclVar; + info.modcon = modcon == null ? null : modcon.dup(); info.returnResult = returnResult; info.defaultSuperCallSite = defaultSuperCallSite; return info;
--- a/src/share/classes/com/sun/tools/javac/comp/Check.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Tue May 07 17:14:17 2013 -0700 @@ -30,29 +30,26 @@ import javax.tools.JavaFileManager; import com.sun.tools.javac.code.*; +import com.sun.tools.javac.code.Lint; +import com.sun.tools.javac.code.Lint.LintCategory; +import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.code.Type.*; +import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; +import com.sun.tools.javac.comp.Infer.InferenceContext; +import com.sun.tools.javac.comp.Infer.FreeTypeListener; import com.sun.tools.javac.jvm.*; import com.sun.tools.javac.tree.*; +import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; - -import com.sun.tools.javac.code.Lint; -import com.sun.tools.javac.code.Lint.LintCategory; -import com.sun.tools.javac.code.Type.*; -import com.sun.tools.javac.code.Symbol.*; -import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; -import com.sun.tools.javac.comp.Infer.InferenceContext; -import com.sun.tools.javac.comp.Infer.FreeTypeListener; -import com.sun.tools.javac.tree.JCTree.*; -import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; - import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Flags.ANNOTATION; import static com.sun.tools.javac.code.Flags.SYNCHRONIZED; import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.code.TypeTag.WILDCARD; - import static com.sun.tools.javac.tree.JCTree.Tag.*; /** Type checking helper class for the attribution phase. @@ -1127,8 +1124,7 @@ mask |= INTERFACE; } else { - log.error(pos, - "mod.not.allowed.here", asFlagSet(illegal)); + log.error(pos, "mod.not.allowed.here", asFlagSet(illegal)); } } else if ((sym.kind == TYP ||
--- a/src/share/classes/com/sun/tools/javac/comp/Enter.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Enter.java Tue May 07 17:14:17 2013 -0700 @@ -95,7 +95,7 @@ Log log; Symtab syms; - Check chk; + Check chk; TreeMaker make; ClassReader reader; Annotate annotate; @@ -105,6 +105,8 @@ Names names; JavaFileManager fileManager; PkgInfo pkginfoOpt; + Modules modules; + JCDiagnostic.Factory diags; private final Todo todo; @@ -128,6 +130,8 @@ annotate = Annotate.instance(context); lint = Lint.instance(context); names = Names.instance(context); + modules = Modules.instance(context); + diags = JCDiagnostic.Factory.instance(context); predefClassDef = make.ClassDef( make.Modifiers(PUBLIC), @@ -237,6 +241,23 @@ : env.info.scope; } + /** Create a fresh environment for modules. + * + * @param tree The module definition. + * @param env The environment current outside of the module definition. + */ + public Env<AttrContext> moduleEnv(JCModuleDecl tree, Env<AttrContext> env) { + assert tree.sym != null; + Env<AttrContext> localEnv = + env.dup(tree, env.info.dup(new Scope(tree.sym))); + localEnv.enclClass = predefClassDef; + localEnv.outer = env; + localEnv.info.isSelfCall = false; + localEnv.info.lint = null; // leave this to be filled in by Attr, + // when annotations have been processed + return localEnv; + } + /* ************************************************************************ * Visitor methods for phase 1: class enter *************************************************************************/ @@ -282,42 +303,45 @@ @Override public void visitTopLevel(JCCompilationUnit tree) { + Assert.checkNonNull(tree.modle, tree.sourcefile.toString()); + JavaFileObject prev = log.useSource(tree.sourcefile); boolean addEnv = false; - boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info", - JavaFileObject.Kind.SOURCE); - if (tree.pid != null) { - tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid)); - if (tree.packageAnnotations.nonEmpty() || pkginfoOpt == PkgInfo.ALWAYS) { - if (isPkgInfo) { - addEnv = true; - } else { - log.error(tree.packageAnnotations.head.pos(), - "pkg.annotations.sb.in.package-info.java"); - } + + boolean isPackageInfo = TreeInfo.isPackageInfo(tree); + boolean isModuleInfo = TreeInfo.isModuleInfo(tree); + JCPackageDecl pd = TreeInfo.getPackage(tree); + + if (pd != null) { + tree.packge = pd.sym = reader.enterPackage(TreeInfo.fullName(pd.packageId)); + if (pd.annots.nonEmpty() && !isPackageInfo) { + log.error(pd.annots.head.pos(), + "pkg.annotations.sb.in.package-info.java"); } } else { tree.packge = syms.unnamedPackage; } tree.packge.complete(); // Find all classes in package. - Env<AttrContext> topEnv = topLevelEnv(tree); + + Env<AttrContext> treeEnv = topLevelEnv(tree); // Save environment of package-info.java file. - if (isPkgInfo) { + if (isPackageInfo) { + addEnv = (pd != null) && pd.annots.nonEmpty(); + Env<AttrContext> env0 = typeEnvs.get(tree.packge); if (env0 == null) { - typeEnvs.put(tree.packge, topEnv); + typeEnvs.put(tree.packge, treeEnv); } else { JCCompilationUnit tree0 = env0.toplevel; if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) { - log.warning(tree.pid != null ? tree.pid.pos() - : null, + log.warning(pd != null ? pd.pos() : null, "pkg-info.already.seen", tree.packge); - if (addEnv || (tree0.packageAnnotations.isEmpty() && + if (addEnv || (tree0.getPackageAnnotations().isEmpty() && tree.docComments != null && tree.docComments.hasComment(tree))) { - typeEnvs.put(tree.packge, topEnv); + typeEnvs.put(tree.packge, treeEnv); } } } @@ -332,11 +356,17 @@ c.completer = null; c.members_field = new Scope(c); tree.packge.package_info = c; + } else if (isModuleInfo) { + JCModuleDecl md = TreeInfo.getModule(tree); + if (md != null) { + typeEnvs.put(md.sym, treeEnv); + } } - classEnter(tree.defs, topEnv); - if (addEnv) { - todo.append(topEnv); - } + + classEnter(tree.defs, treeEnv); + if (addEnv) + todo.append(treeEnv); + log.useSource(prev); result = null; } @@ -399,6 +429,7 @@ c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree); c.sourcefile = env.toplevel.sourcefile; c.members_field = new Scope(c); + c.modle = env.toplevel.modle; ClassType ct = (ClassType)c.type; if (owner.kind != PCK && (c.flags_field & STATIC) == 0) { @@ -427,6 +458,8 @@ // Recursively enter all member classes. classEnter(tree.defs, localEnv); + Assert.checkNonNull(c.modle, c.sourcefile.toString()); + result = c.type; } //where @@ -459,6 +492,13 @@ result = a; } + @Override + public void visitModuleDef(JCModuleDecl tree) { + Env<AttrContext> moduleEnv = moduleEnv(tree, env); + typeEnvs.put(tree.sym, moduleEnv); + todo.append(moduleEnv); + } + /** Default class enter visitor method: do nothing. */ @Override @@ -479,9 +519,22 @@ * @param c The class symbol to be processed. */ public void complete(List<JCCompilationUnit> trees, ClassSymbol c) { + // Process module declarations. + // If module resolution fails, ignore trees, and if trying to + // complete a specific symbol, throw CompletionFailure. + // Note that if module resolution failed, we may not even + // have enough modules available to access java.lang, and + // so risk getting FatalError("no.java.lang") from MemberEnter. + if (!modules.enter(trees)) { + if (c != null) + throw new CompletionFailure(c, diags.fragment("cant.resolve.modules")); + return; + } + annotate.enterStart(); ListBuffer<ClassSymbol> prevUncompleted = uncompleted; - if (memberEnter.completionEnabled) uncompleted = new ListBuffer<ClassSymbol>(); + if (memberEnter.completionEnabled) + uncompleted = new ListBuffer<ClassSymbol>(); try { // enter all classes, and construct uncompleted list @@ -503,8 +556,8 @@ for (JCCompilationUnit tree : trees) { if (tree.starImportScope.elems == null) { JavaFileObject prev = log.useSource(tree.sourcefile); - Env<AttrContext> topEnv = topLevelEnv(tree); - memberEnter.memberEnter(tree, topEnv); + Env<AttrContext> treeEnv = topLevelEnv(tree); + memberEnter.memberEnter(tree, treeEnv); log.useSource(prev); } }
--- a/src/share/classes/com/sun/tools/javac/comp/Flow.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java Tue May 07 17:14:17 2013 -0700 @@ -2181,6 +2181,10 @@ tree.underlyingType.accept(this); } + public void visitModuleDef(JCModuleDecl tree) { + // Do nothing for modules + } + public void visitTopLevel(JCCompilationUnit tree) { // Do nothing for TopLevel since each class is visited individually } @@ -2311,6 +2315,9 @@ /* ------------ Visitor methods for various sorts of trees -------------*/ + public void visitModuleDef(JCModuleDecl tree) { + } + public void visitClassDef(JCClassDecl tree) { JCTree prevTree = currentTree; try {
--- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Tue May 07 17:14:17 2013 -0700 @@ -2347,25 +2347,18 @@ public void visitTopLevel(JCCompilationUnit tree) { if (needPackageInfoClass(tree)) { - Name name = names.package_info; + JCPackageDecl pd = TreeInfo.getPackage(tree); long flags = Flags.ABSTRACT | Flags.INTERFACE; if (target.isPackageInfoSynthetic()) - // package-info is marked SYNTHETIC in JDK 1.6 and later releases - flags = flags | Flags.SYNTHETIC; - JCClassDecl packageAnnotationsClass - = make.ClassDef(make.Modifiers(flags, - tree.packageAnnotations), - name, List.<JCTypeParameter>nil(), - null, List.<JCExpression>nil(), List.<JCTree>nil()); + flags |= SYNTHETIC; ClassSymbol c = tree.packge.package_info; + c.annotations.setAttributes(pd.sym.annotations); + c.modle = attrEnv.toplevel.modle; c.flags_field |= flags; - c.annotations.setAttributes(tree.packge.annotations); ClassType ctype = (ClassType) c.type; ctype.supertype_field = syms.objectType; ctype.interfaces_field = List.nil(); - packageAnnotationsClass.sym = c; - - translated.append(packageAnnotationsClass); + createInfoClass(pd.annots, c); } } // where @@ -2374,7 +2367,7 @@ case ALWAYS: return true; case LEGACY: - return tree.packageAnnotations.nonEmpty(); + return tree.getPackageAnnotations().nonEmpty(); case NONEMPTY: for (Attribute.Compound a : tree.packge.annotations.getDeclarationAttributes()) { @@ -2387,6 +2380,23 @@ throw new AssertionError(); } + public void visitModuleDef(JCModuleDecl tree) { + ModuleSymbol msym = tree.sym; + ClassSymbol c = msym.module_info; + c.flags_field |= SYNTHETIC; + createInfoClass(List.<JCAnnotation>nil(), tree.sym.module_info); + } + + private void createInfoClass(List<JCAnnotation> annots, ClassSymbol c) { + long flags = Flags.ABSTRACT | Flags.INTERFACE; + JCClassDecl infoClass = + make.ClassDef(make.Modifiers(flags, annots), + c.name, List.<JCTypeParameter>nil(), + null, List.<JCExpression>nil(), List.<JCTree>nil()); + infoClass.sym = c; + translated.append(infoClass); + } + public void visitClassDef(JCClassDecl tree) { ClassSymbol currentClassPrev = currentClass; MethodSymbol currentMethodSymPrev = currentMethodSym;
--- a/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Tue May 07 17:14:17 2013 -0700 @@ -38,6 +38,7 @@ import com.sun.tools.javac.jvm.*; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.util.*; +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Symbol.*; @@ -51,7 +52,6 @@ import static com.sun.tools.javac.code.TypeTag.TYPEVAR; import static com.sun.tools.javac.tree.JCTree.Tag.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; /** This is the second phase of Enter, in which classes are completed * by entering their members into the class scope using @@ -162,6 +162,7 @@ Env<AttrContext> env) { final JavaFileObject sourcefile = env.toplevel.sourcefile; final Scope toScope = env.toplevel.starImportScope; + final ModuleSymbol modle = env.toplevel.modle; final PackageSymbol packge = env.toplevel.packge; final TypeSymbol origin = tsym; @@ -182,7 +183,7 @@ Symbol sym = e.sym; if (sym.kind == TYP && (sym.flags() & STATIC) != 0 && - staticImportAccessible(sym, packge) && + staticImportAccessible(sym, modle, packge) && sym.isMemberOf(origin, types) && !toScope.includes(sym)) toScope.enter(sym, fromScope, origin.members()); @@ -210,7 +211,7 @@ for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) { Symbol sym = e.sym; if (sym.isStatic() && sym.kind != TYP && - staticImportAccessible(sym, packge) && + staticImportAccessible(sym, modle, packge) && !toScope.includes(sym) && sym.isMemberOf(origin, types)) { toScope.enter(sym, fromScope, origin.members()); @@ -224,7 +225,7 @@ } // is the sym accessible everywhere in packge? - boolean staticImportAccessible(Symbol sym, PackageSymbol packge) { + boolean staticImportAccessible(Symbol sym, ModuleSymbol modle, PackageSymbol packge) { int flags = (int)(sym.flags() & AccessFlags); switch (flags) { default: @@ -255,6 +256,7 @@ } final Scope toScope = env.toplevel.namedImportScope; + final ModuleSymbol modle = env.toplevel.modle; final PackageSymbol packge = env.toplevel.packge; final TypeSymbol origin = tsym; @@ -276,7 +278,7 @@ Symbol sym = e.sym; if (sym.isStatic() && sym.kind == TYP && - staticImportAccessible(sym, packge) && + staticImportAccessible(sym, modle, packge) && sym.isMemberOf(origin, types) && chk.checkUniqueStaticImport(pos, sym, toScope)) toScope.enter(sym, sym.owner.members(), origin.members()); @@ -306,7 +308,7 @@ e = e.next()) { Symbol sym = e.sym; if (sym.isStatic() && - staticImportAccessible(sym, packge) && + staticImportAccessible(sym, modle, packge) && sym.isMemberOf(origin, types)) { found = true; if (sym.kind == MTH || @@ -481,23 +483,31 @@ return; } + JCModuleDecl md = TreeInfo.getModule(tree); + JCPackageDecl pd = TreeInfo.getPackage(tree); + // check that no class exists with same fully qualified name as // toplevel package - if (checkClash && tree.pid != null) { + if (checkClash && pd != null) { Symbol p = tree.packge; while (p.owner != syms.rootPackage) { p.owner.complete(); // enter all class members of p if (syms.classes.get(p.getQualifiedName()) != null) { log.error(tree.pos, - "pkg.clashes.with.class.of.same.name", - p); + "pkg.clashes.with.class.of.same.name", + p); } p = p.owner; } } + // set up module and its dependencies + /*temp*/if (tree.modle != null)/*temp*/ // JIGSAW TEMP: tree.modle SHOULD ALWAYS BE SET + tree.modle.complete(); + // process package annotations - annotateLater(tree.packageAnnotations, env, tree.packge); + if (pd != null) + annotateLater(pd.annots, env, pd.sym); // Import-on-demand java.lang. importAll(tree.pos, reader.enterPackage(names.java_lang), env);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/javac/comp/ModuleContext.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.comp; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.sun.tools.javac.code.Directive; +import com.sun.tools.javac.tree.JCTree.JCModuleDirective; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Name; + +/** + * Contains information specific to the modules/enter/attr + * passes, to be used in place of the generic field in environments. + * + * <p><b>This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice.</b> + */ +public class ModuleContext { + + ModuleContext() { + requiresBaseModule = true; + directives = new ListBuffer<Directive>(); + directiveForTree = new HashMap<JCModuleDirective, Directive>(); + directiveIndex = new HashMap<Name, Set<Directive>>(); + } + + ModuleContext dup() { + return new ModuleContext(); + } + + void addDirective(Directive d, JCModuleDirective tree, Name name) { + directives.add(d); + directiveForTree.put(tree, d); + Set<Directive> set = directiveIndex.get(name); + if (set == null) + directiveIndex.put(name, (set = new LinkedHashSet<Directive>())); + set.add(d); + } + + Collection<Directive> getDirectives(Name name) { + Set<Directive> set = directiveIndex.get(name); + return (set != null) ? set : Collections.<Directive>emptySet(); + } + + Collection<Directive> getDirectives(Directive.Kind kind, Name name) { + List<Directive> list = null; + Set<Directive> set = directiveIndex.get(name); + if (set != null) { + for (Directive d: set) { + if (d.getKind() == kind) { + if (list == null) + list = new ArrayList<Directive>(); + list.add(d); + } + } + } + return (list == null) ? Collections.<Directive>emptySet() : list; + } + + + + final ListBuffer<Directive> directives; + final Map<JCModuleDirective, Directive> directiveForTree; + final Map<Name, Set<Directive>> directiveIndex; + + boolean requiresBaseModule; + boolean isPlatformModule; + boolean hasEntrypoint; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/javac/comp/Modules.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,1201 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package com.sun.tools.javac.comp; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.tools.JavaFileManager; +import javax.tools.JavaFileManager.Location; +import javax.tools.JavaFileObject; +import javax.tools.ModuleFileManager; +import javax.tools.ModuleFileManager.InvalidFileObjectException; +import javax.tools.ModuleFileManager.ModuleMode; +import javax.tools.StandardLocation; +import static javax.tools.StandardLocation.*; + +import com.sun.source.tree.RequiresFlag; +import com.sun.tools.javac.code.Directive; +import com.sun.tools.javac.code.Directive.PermitsDirective; +import com.sun.tools.javac.code.Directive.ProvidesModuleDirective; +import com.sun.tools.javac.code.Directive.RequiresModuleDirective; +import com.sun.tools.javac.code.Directive.ViewDeclaration; +import com.sun.tools.javac.code.ModuleId; +import com.sun.tools.javac.code.ModuleQuery; +import com.sun.tools.javac.code.Scope; +import com.sun.tools.javac.code.Symbol.ClassSymbol; +import com.sun.tools.javac.code.Symbol.ModuleSymbol; +import com.sun.tools.javac.code.Symbol.PackageSymbol; +import com.sun.tools.javac.code.Symtab; +import com.sun.tools.javac.file.JavacFileManager; +import com.sun.tools.javac.jvm.ClassReader; +import com.sun.tools.javac.main.Option; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.JCTree.JCEntrypointDirective; +import com.sun.tools.javac.tree.JCTree.JCExportDirective; +import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCModuleDecl; +import com.sun.tools.javac.tree.JCTree.JCModuleId; +import com.sun.tools.javac.tree.JCTree.JCModuleQuery; +import com.sun.tools.javac.tree.JCTree.JCPermitsDirective; +import com.sun.tools.javac.tree.JCTree.JCProvidesModuleDirective; +import com.sun.tools.javac.tree.JCTree.JCProvidesServiceDirective; +import com.sun.tools.javac.tree.JCTree.JCRequiresModuleDirective; +import com.sun.tools.javac.tree.JCTree.JCRequiresServiceDirective; +import com.sun.tools.javac.tree.JCTree.JCViewDecl; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Debug; +import com.sun.tools.javac.util.JCDiagnostic; +import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Log; +import com.sun.tools.javac.util.Name; +import com.sun.tools.javac.util.Names; +import com.sun.tools.javac.util.Options; +import static com.sun.tools.javac.main.Option.*; + +/** + * <p><b>This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice.</b> + */ +public class Modules extends JCTree.Visitor { + ClassReader reader; + Log log; + JavaFileManager fileManager; + ModuleFileManager moduleFileManager; + Names names; + Symtab syms; + Debug debug; + boolean enabled; + + ModuleMode mode; + + /** + * The set of module locations for entered trees. + * In single module compilation mode, it is a composite of class path and + * source path. + * In multi-module compilation mode, it is the set of "module directories" + * for the files on the command line (i.e. the directories above each + * source files package hierarchy.) + */ + final Set<Location> rootLocns = new LinkedHashSet<Location>(); + + final Map<Location,ModuleSymbol> allModules; + + /** The symbol currently being analyzed. */ + ModuleSymbol currSym; + + Env<ModuleContext> env; + Map<ModuleSymbol, Env<ModuleContext>> moduleEnvs = new HashMap<ModuleSymbol, Env<ModuleContext>>(); + + /** True if file manager is not a ModuleFileManager and we have + * seen module declaration in input trees. */ + boolean moduleFileManagerUnavailable; + + public static Modules instance(Context context) { + Modules instance = context.get(Modules.class); + if (instance == null) + instance = new Modules(context); + return instance; + } + + protected Modules(Context context) { + context.put(Modules.class, this); + log = Log.instance(context); + reader = ClassReader.instance(context); + fileManager = context.get(JavaFileManager.class); + names = Names.instance(context); + syms = Symtab.instance(context); + allModules = syms.allModules; + Options options = Options.instance(context); + debug = new Debug("modules", options, log); + + // module system features enabled unless -XDnomodules is set + enabled = (options.get("nomodules") == null); + + if (!enabled) + return; + + initModuleResolver(context); + + if (fileManager instanceof ModuleFileManager) { + moduleFileManager = (ModuleFileManager) fileManager; + mode = moduleFileManager.getModuleMode(); + } else + mode = ModuleMode.SINGLE; + } + + <T extends JCTree> void acceptAll(List<T> trees) { + for (List<T> l = trees; l.nonEmpty(); l = l.tail) + l.head.accept(this); + } + + public ModuleContext getModuleContext(JCModuleDecl decl) { + Env<ModuleContext> e = moduleEnvs.get(decl.sym); + return e == null ? null : e.info; + } + + @Override + public void visitModuleDef(JCModuleDecl tree) { + DEBUG("Modules.visitModuleDef " + tree.id); + + if (mode == ModuleMode.SINGLE) { + if (moduleFileManager == null) { + log.error(tree, "mdl.module.file.manager.required"); + moduleFileManagerUnavailable = true; + } else { + env.toplevel.locn = moduleFileManager.join(List.of(CLASS_PATH, SOURCE_PATH)); + if (state == State.INITIAL) + rootLocns.add(env.toplevel.locn); + } + } + + ModuleSymbol sym = reader.enterModule(env.toplevel.locn); + if (sym.name != null) { + log.error(tree.pos(), "mdl.already.defined", sym.module_info.sourcefile); + sym = new ModuleSymbol(TreeInfo.fullName(tree.id.qualId), syms.rootModule); + } else { + sym.name = sym.fullname = TreeInfo.fullName(tree.id.qualId); + sym.module_info.fullname = ClassSymbol.formFullName(sym.module_info.name, sym); + sym.module_info.flatname = ClassSymbol.formFlatName(sym.module_info.name, sym); + sym.extendedMetadata = tree.metadata; + sym.module_info.sourcefile = env.toplevel.sourcefile; + sym.module_info.members_field = new Scope(sym.module_info); + sym.completer = null; + } + + DEBUG("Modules.visitModuleDef name " + sym.name); + DEBUG("Modules.visitModuleDef fullname " + sym.fullname); + DEBUG("Modules.visitModuleDef flatName() " + sym.flatName()); + DEBUG("Modules.visitModuleDef m-i name " + sym.module_info.name); + DEBUG("Modules.visitModuleDef m-i fullname " + sym.module_info.fullname); + DEBUG("Modules.visitModuleDef m-i flatname " + sym.module_info.flatname); + + sym.location = env.toplevel.locn; + tree.sym = sym; + + sym.version = tree.getId().version; + currSym = sym; + Env<ModuleContext> menv = env.dup(tree, new ModuleContext()); + moduleEnvs.put(sym, menv); + Env<ModuleContext> prev = env; + env = menv; + try { + if (isBaseModuleName(sym.name)) + env.info.requiresBaseModule = false; + + acceptAll(tree.directives); + + DEBUG("Modules.visitModuleDef requiresBaseModule:" + env.info.requiresBaseModule); + if (env.info.requiresBaseModule) { + env.info.directives.add(new RequiresModuleDirective(syms.baseModuleQuery, + EnumSet.of(Directive.RequiresFlag.SYNTHESIZED))); + } + } finally { + sym.directives = env.info.directives.toList(); + currSym = null; + env = prev; + } + } + + @Override + public void visitTopLevel(JCCompilationUnit tree) { + DEBUG("Modules.visitTopLevel " + tree.sourcefile); + env = new Env<ModuleContext>(tree, null); + env.toplevel = tree; + JavaFileObject prev = log.useSource(tree.sourcefile); + try { + if (mode == ModuleMode.MULTIPLE) { + assert moduleFileManager != null; + Location l = moduleFileManager.join(List.of(MODULE_PATH, SOURCE_PATH)); + JCExpression pn = tree.getPackageName(); + String pkgName = (pn == null) ? "" : TreeInfo.fullName(pn).toString(); + try { + tree.locn = moduleFileManager.getModuleLocation(l, tree.sourcefile, pkgName); + DEBUG("Modules.visitTopLevel MULTIPLE " + tree.locn); + if (state == State.INITIAL) + rootLocns.add(tree.locn); + } catch (InvalidFileObjectException e) { + log.error(pn, "mdl.file.in.wrong.directory", tree.sourcefile, pkgName); + } + } + + if (TreeInfo.isModuleInfo(tree)) + acceptAll(tree.defs); + } finally { + log.useSource(prev); + DEBUG("Modules.visitTopLevel EXIT rootLocns=" + rootLocns); + } + } + + @Override + public void visitEntrypoint(JCEntrypointDirective tree) { + if (env.info.hasEntrypoint) + log.error(tree, "dupl.entrypoint"); + env.info.hasEntrypoint = true; + } + + @Override + public void visitExports(JCExportDirective tree) { + } + + @Override + public void visitPermits(JCPermitsDirective tree) { + JCTree qualId = tree.moduleName; + Name moduleName = TreeInfo.fullName(qualId); + PermitsDirective d = new PermitsDirective(moduleName); + if (env.info.getDirectives(Directive.Kind.PERMITS, d.moduleId.name).isEmpty()) { + env.info.addDirective(d, tree, d.moduleId.name); + } else { + log.error(tree.moduleName, "dupl.permits", d.moduleId.name); + } + } + + @Override + public void visitProvidesModule(JCProvidesModuleDirective tree) { + JCModuleId moduleId = tree.moduleId; + ProvidesModuleDirective d = new ProvidesModuleDirective( + new ModuleId(TreeInfo.fullName(moduleId.qualId), moduleId.version)); + if (env.info.getDirectives(Directive.Kind.PROVIDES_MODULE, d.moduleId.name).isEmpty()) { + env.info.addDirective(d, tree, d.moduleId.name); + if (isBaseModuleName(d.moduleId.name)) + env.info.requiresBaseModule = false; + } else { + log.error(tree.moduleId, "dupl.provides", d.moduleId.name); + } + } + + @Override + public void visitProvidesService(JCProvidesServiceDirective tree) { + } + + @Override + public void visitRequiresModule(JCRequiresModuleDirective tree) { + if (!env.tree.hasTag(JCTree.Tag.MODULE)) { + log.error(tree, "requires.not.allowed.in.view"); + return; + } + + JCModuleQuery moduleQuery = tree.moduleQuery; + ModuleQuery mq = new ModuleQuery(TreeInfo.fullName(moduleQuery.qualId), moduleQuery.versionQuery); + Set<Directive.RequiresFlag> flags = EnumSet.noneOf(Directive.RequiresFlag.class); + for (RequiresFlag f: tree.flags) { + switch (f) { + case REEXPORT: + flags.add(Directive.RequiresFlag.REEXPORT); + break; + case OPTIONAL: + flags.add(Directive.RequiresFlag.OPTIONAL); + break; + case LOCAL: + flags.add(Directive.RequiresFlag.LOCAL); + break; + } + } + RequiresModuleDirective d = new RequiresModuleDirective(mq, flags); + if (env.info.getDirectives(Directive.Kind.REQUIRES_MODULE, mq.name).isEmpty()) { + env.info.addDirective(d, tree, mq.name); + if (isBaseModuleName(mq.name)) + env.info.requiresBaseModule = false; + } else { + log.error(tree, "dupl.requires", mq.name); + } + } + + @Override + public void visitRequiresService(JCRequiresServiceDirective tree) { + if (!env.tree.hasTag(JCTree.Tag.MODULE)) { + log.error(tree, "requires.not.allowed.in.view"); + return; + } + } + + @Override + public void visitView(JCViewDecl tree) { + List<Directive> viewDirectives; + Env<ModuleContext> prevEnv = env; + env = env.dup(tree, env.info.dup()); + try { + acceptAll(tree.directives); + } finally { + viewDirectives = env.info.directives.toList(); + env = prevEnv; + } + + if (!env.tree.hasTag(JCTree.Tag.MODULE)) { + log.error(tree, "nested.view.not.allowed"); + return; + } + + ViewDeclaration v = new ViewDeclaration(TreeInfo.fullName(tree.name), + viewDirectives); + if (!env.info.getDirectives(Directive.Kind.VIEW, v.name).isEmpty() + || v.name.equals(((JCModuleDecl) env.tree).sym.fullname)) { + log.error(tree, "dupl.view", v.name); + return; + } + + env.info.addDirective(v, tree, v.name); + if (isBaseModuleName(v.name)) + env.info.requiresBaseModule = false; + } + + @Override + public void visitTree(JCTree tree) { } + + private boolean resolve(List<JCCompilationUnit> trees) { + if (moduleFileManagerUnavailable) + return false; + + DEBUG("Modules.resolve: resolve modules"); + + DEBUG("Modules.resolve mode=" + mode + ", rootLocns=" + rootLocns + " (" + rootLocns.size() + ")" ); + if (mode == ModuleMode.SINGLE && rootLocns.isEmpty()) { + if (moduleFileManager != null) { + rootLocns.add(moduleFileManager.join(List.of(CLASS_PATH, SOURCE_PATH))); + } else { + // TODO: check for module-info.{java,class} and give error if found + // TODO?? use a custom DEFAULT locn, instead of null?? + return true; + } + } + + DEBUG("Modules.resolve: building roots, rootLocns=" + rootLocns); + if (debug.isEnabled("initialRootLocns")) + showRootLocations(rootLocns); + + List<ModuleSymbol> roots = List.nil(); + for (Location locn: rootLocns) { + DEBUG("Modules.resolve: building roots: locn: " + locn); + ModuleSymbol msym = reader.enterModule(locn); + DEBUG("Modules.resolve: building roots: msym: " + msym); + msym.complete(); + DEBUG("Modules.resolve: building roots: completed: " + msym); + roots = roots.prepend(msym); + } + roots = roots.reverse(); + DEBUG("Modules.resolve: roots: " + roots); + + updateTrees(trees); + + DEBUG("Modules.resolve: modules so far: " + allModules); + + DEBUG("Modules.resolve: reading module-info as needed"); + Location l = (moduleFileManager.getModuleMode() == ModuleMode.SINGLE) + ? MODULE_PATH : moduleFileManager.join(List.of(MODULE_PATH, SOURCE_PATH)); + for (Location locn: moduleFileManager.getModuleLocations(l)) { + DEBUG("Modules.resolve: ensuring module-info for " + locn); + reader.enterModule(locn).complete(); + } + + ListBuffer<ModuleSymbol> namedModules = new ListBuffer<ModuleSymbol>(); + for (ModuleSymbol msym: allModules.values()) { + if (msym.name != names.empty) + namedModules.add(msym); + } + + if (debug.isEnabled("resolve")) { + debug.println("Module resolver: " + moduleResolver.getClass().getSimpleName()); + showModules("Module resolution roots:", roots); + showModules("Modules in compilation environment:", namedModules); + } + + Iterable<? extends ModuleSymbol> modules = moduleResolver.resolve(roots, namedModules); + if (modules == null) + return false; + + // modules is returned in an order such that if A requires B, then + // A will be earlier than B. This means that the root modules, such + // as the unnamed module appear ahead of the platform modules, + // which will appear last. This is the reverse of the traditional + // ordering, in which the platform classes are read ahead of classes + // on the user class path. Therefore, we build and use a reversed + // list of modules before converting the modules to the path used by + // ClassReader. + + List<ModuleSymbol> msyms = List.nil(); + for (ModuleSymbol sym: modules) + msyms = msyms.prepend(sym); + + if (debug.isEnabled("resolve")) + showModules("Resolved modules: ", msyms); + + JavacFileManager jfm = (fileManager instanceof JavacFileManager) + ? (JavacFileManager)fileManager : null; + + ModuleSymbol firstPlatformModule = null; + ModuleSymbol lastPlatformModule = null; + for (ModuleSymbol msym: msyms) { + DEBUG("Modules.resolve: " + msym.fullname + " " + isPlatformModule(msym)); + if (isPlatformModule(msym)) { + if (firstPlatformModule == null) + firstPlatformModule = msym; + lastPlatformModule = msym; + } + } + + ListBuffer<Location> locns = new ListBuffer<Location>(); + for (ModuleSymbol msym: msyms) { + DEBUG("Modules.resolve: msym: " + msym); + DEBUG("Modules.resolve: msym.location: " + msym.location); + if (jfm != null && isPlatformModule(msym)) { + locns.addAll(jfm.augmentPlatformLocation(msym.location, + msym == firstPlatformModule, + msym == lastPlatformModule)); + } else + locns.add(msym.location); + } + Location merged = moduleFileManager.join(locns); + DEBUG("Modules.resolve: merged result: " + merged); + reader.setPathLocation(merged); + + return true; + } + + boolean isBaseModuleName(Name name) { + return name.equals(syms.baseModule.name); + } + + boolean isPlatformModule(ModuleSymbol msym) { + return isPlatformModuleName(msym.name) || definesPlatformModule(msym.directives); + } + + boolean isPlatformModuleName(Name name) { + return name.toString().startsWith("java.") || name.toString().startsWith("jdk.") ; + } + + boolean definesPlatformModule(List<Directive> directives) { + for (Directive d: directives) { + switch (d.getKind()) { + case PROVIDES_MODULE: + if (isPlatformModuleName(((ProvidesModuleDirective) d).moduleId.name)) + return true; + break; + case VIEW: + ViewDeclaration v = (ViewDeclaration) d; + if (isPlatformModuleName(v.name) || definesPlatformModule(v.directives)) + return true; + break; + } + } + return false; + } + + protected ModuleResolver getModuleResolver() { + return moduleResolver; + } + + protected void initModuleResolver(Context context) { + Options options = Options.instance(context); + boolean useZeroMod = (options.get("zeroMod") != null); + + if (!useZeroMod) { +// ServiceLoader<ModuleResolver> loader = ServiceLoader.load(ModuleResolver.class); +// // for now, use the first available, if any +// for (Iterator<ModuleResolver> iter = loader.iterator(); iter.hasNext(); ) { +// moduleResolver = iter.next(); +// moduleResolver.init(options); +// return; +// } + + String library = options.get(Option.L); + if (library != null || !isLegacyRuntime()) { + // use Class.forName on jigsaw module resolver, to avoid bootstrap dependency + try { + String jigsawModuleResolver = "com.sun.tools.javac.jigsaw.JigsawModuleResolver"; + Class<? extends ModuleResolver> c = + Class.forName(jigsawModuleResolver).asSubclass(ModuleResolver.class); + Constructor<? extends ModuleResolver> constr = + c.getDeclaredConstructor(new Class<?>[] { Context.class }); + moduleResolver = constr.newInstance(context); + DEBUG("Modules.initModuleResolver: " + moduleResolver); + + Option[] unsupportedOptions = { + // XBOOTCLASSPATH_PREPEND, + ENDORSEDDIRS, + // BOOTCLASSPATH, + // XBOOTCLASSPATH_APPEND, + EXTDIRS + }; + for (Option o: unsupportedOptions) { + if (options.get(o) != null) { + + } + } + context.put(ModuleResolver.class, moduleResolver); + return; + } catch (ClassNotFoundException e) { + // running in JDK 7 mode + DEBUG("Modules.initModuleResolver: " + e); + } catch (IllegalAccessException e) { + // FIXME: fall through for now; should report error + DEBUG("Modules.initModuleResolver: " + e); + } catch (NoSuchMethodException e) { + // FIXME: fall through for now; should report error + DEBUG("Modules.initModuleResolver: " + e); + } catch (InstantiationException e) { + // FIXME: fall through for now; should report error + DEBUG("Modules.initModuleResolver: " + e); + } catch (InvocationTargetException e) { + DEBUG("Modules.initModuleResolver: " + e); + Throwable t = e.getTargetException(); + if (t instanceof FileNotFoundException) + log.error("module.library.not.found", t.getMessage()); + else if (t instanceof IOException) + log.error("cannot.open.module.library", t.getMessage()); // FIXME, t.getMessage is a barely helpful string + else if (t instanceof RuntimeException) + throw new RuntimeException(t); + else if (t instanceof Error) + throw new Error(t); + else + throw new AssertionError(t); + } + } + } + + // use ZeroMod + moduleResolver = new ZeroMod(new ErrorHandler() { + public void report(ModuleSymbol msym, ModuleId mid, String key, Object... args) { + error(msym, mid, key, args); + } + public void report(ModuleSymbol msym, ModuleQuery mq, String key, Object... args) { + error(msym, mq, key, args); + } + }); + DEBUG("Modules.initModuleResolver: zeromod: " + moduleResolver); + context.put(ModuleResolver.class, moduleResolver); + } + // where + private ModuleResolver moduleResolver; + + private boolean isLegacyRuntime() { + File javaHome = new File(System.getProperty("java.home")); + File rt_jar = new File(new File(javaHome, "lib"), "rt.jar"); + return rt_jar.exists(); + } + + private void error(ModuleSymbol msym, ModuleQuery mq, String key, Object... args) { + error(msym, new ModuleId(mq.name, mq.versionQuery), key, args); + } + + private void error(ModuleSymbol msym, ModuleId id, String key, Object... args) { + if (msym == null) { + log.error(key, args); + } else { + // TODO, determine error location from msym, mid + ClassSymbol minfo = msym.module_info; + + Env<ModuleContext> menv = moduleEnvs.get(msym); + DEBUG("Modules.error " + msym + " -- " + moduleEnvs.get(msym)); + JavaFileObject fo; + JCDiagnostic.DiagnosticPosition pos; + if (menv == null) { + fo = (minfo.sourcefile != null ? minfo.sourcefile : minfo.classfile); + if (fo == null) + fo = msym.module_info.classfile; + pos = null; + } else { + fo = menv.toplevel.sourcefile; + pos = treeFinder.find(menv.tree, id); + } + + JavaFileObject prev = log.useSource(fo); + try { + log.error(pos, key, args); + } finally { + log.useSource(prev); + } + } + } + + class TreeFinder extends JCTree.Visitor { + ModuleId mid; + JCTree result; + + JCTree find(JCTree tree, ModuleId mid) { + DEBUG("Modules.TreeFinder.find mid=" + mid); + this.mid = mid; + result = null; + tree.accept(this); + DEBUG("Modules.TreeFinder.find result=" + result); + return result; + } + + @Override + public void visitModuleDef(JCModuleDecl tree) { + search(tree.id); + search(tree.directives); + } + + @Override + public void visitExports(JCExportDirective tree) { + } + + @Override + public void visitPermits(JCPermitsDirective tree) { + if (equal(TreeInfo.fullName(tree.moduleName), mid.name) && mid.version == null) + result = tree; + } + + @Override + public void visitRequiresModule(JCRequiresModuleDirective tree) { + search(tree.moduleQuery); + } + + @Override + public void visitModuleId(JCModuleId tree) { + DEBUG("Modules.treeFinder.visitModuleId " + tree + " " + mid); + if (equal(TreeInfo.fullName(tree.qualId), mid.name) && equal(tree.version, mid.version)) + result = tree; + DEBUG("Modules.treeFinder.visitModuleId result " + result); + } + + @Override + public void visitModuleQuery(JCModuleQuery tree) { + DEBUG("Modules.treeFinder.visitModuleId " + tree + " " + mid); + if (equal(TreeInfo.fullName(tree.qualId), mid.name) && equal(tree.versionQuery, mid.version)) + result = tree; + DEBUG("Modules.treeFinder.visitModuleId result " + result); + } + + void search(JCTree tree) { + if (result != null) + return; + + tree.accept(this); + } + + void search(List<? extends JCTree> trees) { + if (result != null) + return; + + for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) { + l.head.accept(this); + if (result != null) + return; + } + } + + <T> boolean equal(T t1, T t2) { + DEBUG("Modules.treeFinder.equal " + t1 + " " + t2 + (t1 == null ? t2 == null : t1.equals(t2))); + return t1 == null ? t2 == null : t1.equals(t2); + } + } + TreeFinder treeFinder = new TreeFinder(); + + private void updateTrees(List<JCCompilationUnit> trees) { + if (mode == ModuleMode.SINGLE) { + assert rootLocns.size() == 1; + Location locn = rootLocns.iterator().next(); + locn.getClass(); // debug + ModuleSymbol msym = allModules.get(locn); + DEBUG("Modules.updateTrees: update SINGLE trees: " + locn + " " + msym); + if (msym == null) { + msym = syms.unnamedModule; + DEBUG("Modules.updateTrees: using unnamed module " + syms.unnamedModule.completer); + } + for (List<JCCompilationUnit> l = trees; l.nonEmpty(); l = l.tail) { + JCCompilationUnit tree = l.head; + assert tree.locn == null || tree.locn == locn; + tree.locn = locn; + assert tree.modle == null || tree.modle == msym; + tree.modle = msym; + } + } else { + for (List<JCCompilationUnit> l = trees; l.nonEmpty(); l = l.tail) { + JCCompilationUnit t = l.head; + ModuleSymbol msym = allModules.get(t.locn); + if (msym == null) { + msym = syms.unnamedModule; + DEBUG("Modules.updateTrees: using unnamed module " + syms.unnamedModule.completer); + } + t.modle = msym; + DEBUG("Modules.updateTrees: update MULTIPLE trees: " + t.locn + " " + t.modle); + } + } + } + + private enum State { INITIAL, RESOLVING, RESOLVED}; + private State state = State.INITIAL; + + private int enterCount = 0; // debug only + + public boolean enter(List<JCCompilationUnit> trees) { + if (!enabled) { + CheckNoModulesVisitor v = new CheckNoModulesVisitor(log); + return v.checkNoModules(trees); + } + + int count = enterCount++; + DEBUG("Modules.enter " + count + " " + state); + + DEBUG("Modules.enter " + count + ": acceptAll"); + acceptAll(trees); + + try { // debug + + switch (state) { + case INITIAL: + state = State.RESOLVING; + try { + return resolve(trees); + } finally { + state = State.RESOLVED; + } + + case RESOLVING: + updateTrees(trees); + return true; + + case RESOLVED: + return true; + + default: + throw new AssertionError(); + } + + // debug + } finally { + DEBUG("Modules.enter " + count + ": exit " + state); + } + } + // where + private static class CheckNoModulesVisitor extends TreeScanner { + private final Log log; + private boolean result = true; + CheckNoModulesVisitor(Log log) { + this.log = log; + } + boolean checkNoModules(List<? extends JCTree> trees) { + scan(trees); + return result; + } + @Override + public void visitClassDef(JCClassDecl tree) { + } + @Override + public void visitModuleDef(JCModuleDecl tree) { + result = false; + log.error(tree, "module.decl.not.permitted"); + } + @Override + public void visitTopLevel(JCCompilationUnit tree) { + JavaFileObject prev = log.useSource(tree.sourcefile); + try { + super.visitTopLevel(tree); + } finally { + log.useSource(prev); + } + } + } + + // Quick and dirty temporary debug printing; + // this should all be removed prior to final integration + boolean DEBUG = (System.getProperty("javac.debug.modules") != null); + void DEBUG(String s) { + if (DEBUG) + System.err.println(s); + } + + void showModuleResolver(ModuleResolver mr) { + debug.println("Module resolver: " + mr.getClass().getSimpleName()); + } + + void showRootLocations(Collection<Location> rootLocns) { + debug.println("Module root locations: (" + (rootLocns == null ? "null" : rootLocns.size()) + ")"); + if (rootLocns == null) + return; + int i = 0; + for (Location l: rootLocns) { + debug.println(" " + (i++) +": " + l); + } + } + + void showModules(String desc, Collection<ModuleSymbol> msyms) { + boolean showAll = debug.isEnabled("all"); + boolean showLocation = showAll || debug.isEnabled("location"); + boolean showRequires = showAll || debug.isEnabled("requires"); + if (showLocation || showRequires || showAll) { + debug.println(desc + " (" + msyms.size() + ")"); + for (ModuleSymbol msym: msyms) { + debug.println(" " + msym); + if (showLocation) { + debug.println(" location: " + msym.location); + } + if (showRequires) { + // short form only, for now + debug.print(" requires: "); + String sep = ""; + for (RequiresModuleDirective d: msym.getRequiredModules()) { + debug.print(sep); + showNameAndVersion(d.moduleQuery.name, d.moduleQuery.versionQuery); + sep = ", "; + } + debug.println(); + } + } + + } else { + debug.print(desc + " (" + msyms.size() + ")"); + debug.print(" "); + String sep = ""; + for (ModuleSymbol msym: msyms) { + debug.print(sep + msym); + sep = ", "; + } + debug.println(); + } + } + + void showModuleIds(String desc, Collection<ModuleId> mids) { + debug.print(desc + " (" + mids.size() + ")"); + debug.print(" "); + String sep = ""; + for (ModuleId mid: mids) { + debug.print(sep); + showNameAndVersion(mid.name, mid.version); + sep = ", "; + } + debug.println(); + } + + private void showNameAndVersion(Name name, Name version) { + debug.print(name); + if (version != null) { + debug.print("@"); + debug.print(version); + } + } + + private static <T> String toString(Iterable<T> items) { + StringBuilder sb = new StringBuilder(); + sb.append("["); + String sep = ""; + for (T t: items) { + sb.append(sep); + sb.append(t); + sep = ","; + } + sb.append("]"); + return sb.toString(); + } + + // should be static within ZeroMod + enum VersionErrorKind { + NO_VERSION_AVAILABLE("mdl.no.version.available"), + NO_UNIQUE_VERSION_AVAILABLE("mdl.no.unique.version.available"), + REQUIRED_VERSION_NOT_AVAILABLE("mdl.required.version.not.available"); + VersionErrorKind(String key) { this.key = key; } + final String key; + }; + + interface ErrorHandler { + void report(ModuleSymbol msym, ModuleId mid, String key, Object... args); + void report(ModuleSymbol msym, ModuleQuery mq, String key, Object... args); + } + + /** + * Module resolver for modules defined in the Java™ Programming Language. + * + * Given a set of root modules, and an overall set of modules, the resolver determines + * which modules are visible from the root modules. + */ + public interface ModuleResolver { + + /** + * Resolve a set of modules. The resolution may take additional modules into + * account, such as may be found in a system module library. + * Returns null if the modules cannot be resolved. + * @param roots The root modules whose dependencies need to be resolved + * @param modules A set of modules in which to find any dependencies. + * @throws ResolutionException if the resolution cannot be successfully completed. + */ + Iterable<? extends ModuleSymbol> resolve( + Iterable<? extends ModuleSymbol> roots, + Iterable<? extends ModuleSymbol> modules); + + boolean isPackageVisible(ModuleSymbol msym, PackageSymbol psym); + } + + class ZeroMod implements ModuleResolver { + private ErrorHandler errorHandler; + + ZeroMod(ErrorHandler e) { + errorHandler = e; + } + + public Iterable<? extends ModuleSymbol> resolve( + Iterable<? extends ModuleSymbol> roots, + Iterable<? extends ModuleSymbol> modules) + { + DEBUG("ZeroMod: roots: " + Modules.toString(roots)); + DEBUG("ZeroMod: modules: " + Modules.toString(modules)); + roots.getClass(); + modules.getClass(); + + moduleTable = buildModuleTable(modules); + List<Node> rootNodes = getNodes(roots); + tarjan(rootNodes); + + DEBUG("ZeroMod.NODE MAP {"); + for (Node n: nodeMap.values()) + DEBUG(" Node " + n + " " + n.scc); + DEBUG("}"); + + ListBuffer<ModuleSymbol> results = new ListBuffer<ModuleSymbol>(); + for (Node node: rootNodes) { + if (!results.contains(node.sym)) + getVisibleModules(node.scc, results); + } + + DEBUG("ZeroMod: results: " + Modules.toString(results)); + return results; + } + + @Override + public boolean isPackageVisible(ModuleSymbol msym, PackageSymbol psym) { + return true; + } + + private void getVisibleModules(SCC scc, ListBuffer<ModuleSymbol> results) { + for (Node n: scc.nodes) + results.add(n.sym); + for (SCC child: scc.getChildren()) + getVisibleModules(child, results); + } + + private Map<Name, Map<Name, ModuleSymbol>> buildModuleTable( + Iterable<? extends ModuleSymbol> modules) { + Map<Name, Map<Name, ModuleSymbol>> table = new HashMap<Name, Map<Name, ModuleSymbol>>(); + // build module index + for (ModuleSymbol sym: modules) { + add(table, sym, new ModuleId(sym.name, sym.version)); + for (ViewDeclaration v : sym.getViews()) { + for (ProvidesModuleDirective d : v.getAliases()) + add(table, sym, d.moduleId); + } + } + + // Add entry for default platform module if needed + for (ModuleId p: Arrays.asList(syms.baseModule, syms.jdkLegacyModule)) { + Map<Name,ModuleSymbol> versions = table.get(p.name); + ModuleSymbol psym = (versions == null) ? null : versions.get(p.version); + if (psym == null) { + if (versions == null) + table.put(p.name, versions = new HashMap<Name,ModuleSymbol>()); + psym = new ModuleSymbol(p.name, syms.rootModule); + psym.location = StandardLocation.PLATFORM_CLASS_PATH; + versions.put(p.version, psym); + psym.directives = List.nil(); + } + } + + return table; + } + + private void add(Map<Name, Map<Name, ModuleSymbol>> table, + ModuleSymbol sym, ModuleId mid) { + Map<Name, ModuleSymbol> versions = table.get(mid.name); + if (versions == null) + table.put(mid.name, versions = new HashMap<Name, ModuleSymbol>()); + ModuleSymbol m = versions.get(mid.version); + if (m != null) + // TODO ?? enhance error to disambiguate between define and provides + errorHandler.report(sym, mid, "mdl.duplicate.definition", m); + else + versions.put(mid.version, sym); + } + + private ModuleSymbol getModule(ModuleQuery mid) throws ModuleException { + Map<Name, ModuleSymbol> versions = moduleTable.get(mid.name); + if (versions == null) + throw new ModuleException("mdl.no.version.available", mid); + if (mid.versionQuery == null) { + if (versions.size() > 1) + throw new ModuleException("mdl.no.unique.version.available", mid); + return versions.values().iterator().next(); + } else { + Name q = mid.versionQuery; + Name ge = names.fromString(">="); + if (q.startsWith(ge)) q = q.subName(2, q.length()); + ModuleSymbol sym = versions.get(q); + if (sym == null) + throw new ModuleException("mdl.required.version.not.available", mid); + return sym; + } + } + // where + private Map<Name, Map<Name, ModuleSymbol>> moduleTable; + + private class ModuleException extends Exception { + private static final long serialVersionUID = 0; + ModuleException(String key, ModuleQuery moduleQuery) { + this.key = key; + this.moduleQuery = moduleQuery; + } + final String key; + final ModuleQuery moduleQuery; + } + + List<Node> getNodes(Iterable<? extends ModuleSymbol> syms) { + ListBuffer<Node> lb = new ListBuffer<Node>(); + for (ModuleSymbol sym: syms) { + lb.add(getNode(sym)); + } + return lb.toList(); + } + + Node getNode(ModuleSymbol sym) { + Node node = nodeMap.get(sym); + if (node == null) + nodeMap.put(sym, (node = new Node(sym))); + return node; + } + // where + private Map<ModuleSymbol, Node> nodeMap= new HashMap<ModuleSymbol, Node>(); + + private class Node implements Comparable<Node> { + final ModuleSymbol sym; + SCC scc; + int index = -1; + int lowlink; + boolean active; + + Node(ModuleSymbol sym) { + this.sym = sym; + } + + Iterable<Node> getDependencies() { + DEBUG("ZeroMod.Node.getDependencies: " + sym + " " + sym.getRequiredModules()); + ListBuffer<Node> nodes = new ListBuffer<Node>(); + for (RequiresModuleDirective d: sym.getRequiredModules()) { + try { + nodes.add(getNode(getModule(d.moduleQuery))); + } catch (ModuleException e) { + errorHandler.report(sym, e.moduleQuery, e.key, e.moduleQuery); + } + } + return nodes.toList(); + } + + @Override + public String toString() { + return sym.name + "@" + sym.version + "(index:" + index +",low:" + lowlink + ",active:" + active + ")" ; + } + + public int compareTo(Node o) { + return (index < o.index) ? -1 : (index == o.index) ? 0 : 1; + } + } + + private class SCC { + void add(Node node) { + nodes.add(node); + node.scc = this; + } + + Set<SCC> getChildren() { + if (children == null) { + children = new LinkedHashSet<SCC>(); + for (Node node: nodes) { + for (Node n: node.getDependencies()) { + n.scc.getClass(); // nullcheck + if (n.scc != this) + children.add(n.scc); + } + } + } + return children; + } + + @Override + public String toString() { + return nodes.toString(); + } + + private SortedSet<Node> nodes = new TreeSet<Node>(); + private Set<SCC> children; + } + + // Tarjan's algorithm to determine strongly connected components of a + // directed graph in linear time. + + void tarjan(Iterable<? extends Node> nodes) { + for (Node node: nodes) { + if (node.index == -1) + tarjan(node); + } + } + + void tarjan(Node v) { + v.index = index; + v.lowlink = index; + index++; + stack.add(0, v); + v.active = true; + for (Node n: v.getDependencies()) { + if (n.index == -1) { + tarjan(n); + v.lowlink = Math.min(v.lowlink, n.lowlink); + } else if (stack.contains(n)) { + v.lowlink = Math.min(v.lowlink, n.index); + } + } + if (v.lowlink == v.index) { + Node n; + SCC scc = new SCC(); + do { + n = stack.remove(0); + n.active = false; + scc.add(n); + } while (n != v); + } + } + + private int index = 0; + private ArrayList<Node> stack = new ArrayList<Node>(); + } +}
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Tue May 07 17:14:17 2013 -0700 @@ -25,6 +25,15 @@ package com.sun.tools.javac.comp; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.lang.model.element.ElementVisitor; + import com.sun.tools.javac.api.Formattable.LocalizedString; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Symbol.*; @@ -46,18 +55,6 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; - -import java.util.Arrays; -import java.util.Collection; -import java.util.EnumMap; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; - -import javax.lang.model.element.ElementVisitor; - import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Flags.BLOCK; import static com.sun.tools.javac.code.Kinds.*; @@ -284,7 +281,7 @@ public boolean isAccessible(Env<AttrContext> env, TypeSymbol c, boolean checkInner) { boolean isAccessible = false; - switch ((short)(c.flags() & AccessFlags)) { + switch ((int)(c.flags() & AccessFlags)) { case PRIVATE: isAccessible = env.enclClass.sym.outermostClass() == @@ -354,7 +351,7 @@ } public boolean isAccessible(Env<AttrContext> env, Type site, Symbol sym, boolean checkInner) { if (sym.name == names.init && sym.owner != site.tsym) return false; - switch ((short)(sym.flags() & AccessFlags)) { + switch ((int)(sym.flags() & AccessFlags)) { case PRIVATE: return (env.enclClass.sym == sym.owner // fast special case
--- a/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java Tue May 07 17:14:17 2013 -0700 @@ -32,13 +32,13 @@ import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.CharsetDecoder; + import javax.lang.model.element.Modifier; import javax.lang.model.element.NestingKind; import javax.tools.FileObject; +import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileObject; -import static javax.tools.JavaFileObject.Kind.*; - import com.sun.tools.javac.util.BaseFileManager; /** @@ -47,9 +47,10 @@ * This code and its internal interfaces are subject to change or * deletion without notice.</b> */ -public abstract class BaseFileObject implements JavaFileObject { - protected BaseFileObject(JavacFileManager fileManager) { +public abstract class BaseFileObject implements JavaFileObject, FileObject.Locatable { + protected BaseFileObject(JavacFileManager fileManager, Location location) { this.fileManager = fileManager; + this.location = location; } /** Return a short name for the object, such as for use in raw diagnostics @@ -61,8 +62,10 @@ return getClass().getSimpleName() + "[" + getName() + "]"; } + @Override public NestingKind getNestingKind() { return null; } + @Override public Modifier getAccessLevel() { return null; } public Reader openReader(boolean ignoreEncodingErrors) throws IOException { @@ -75,6 +78,8 @@ protected abstract String inferBinaryName(Iterable<? extends File> path); + protected abstract String inferModuleTag(String binaryName); + protected static JavaFileObject.Kind getKind(String filename) { return BaseFileManager.getKind(filename); } @@ -115,6 +120,11 @@ } + @Override + public Location getLocation() { + return location; + } + // force subtypes to define equals @Override public abstract boolean equals(Object other); @@ -125,4 +135,7 @@ /** The file manager that created this JavaFileObject. */ protected final JavacFileManager fileManager; + + /** The location from which this file object was created, or null if none. */ + protected final Location location; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/javac/file/CompositeLocation.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.file; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Set; +import javax.tools.ExtendedLocation; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileManager.Location; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.StandardJavaFileManager; + +import com.sun.tools.javac.util.ListBuffer; + +/** + * A location composed of a list of component locations. + */ +class CompositeLocation implements ExtendedLocation { + final JavaFileManager fileManager; + final Iterable<? extends Location> locations; + final String name; + private static int count; // FIXME, move count/name to creator, or move CompositeLocation to Locations + + CompositeLocation(Iterable<? extends Location> locations, JavaFileManager fileManager) { + this.locations = locations; + this.fileManager = fileManager; + ListBuffer<String> names = new ListBuffer<String>(); + for (Location l: locations) + names.add(l.getName()); + name = "multiLocation#" + (count++) + names.toString(); + } + + @Override // javax.tools.ExtendedLocation + public Iterable<JavaFileObject> list(String packageName, Set<Kind> kinds, boolean recurse) throws IOException { + ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>(); + for (Location l: locations) { + Iterable<JavaFileObject> fileObjects; + if (l instanceof ExtendedLocation) + fileObjects = ((ExtendedLocation) l).list(packageName, kinds, recurse); + else + fileObjects = fileManager.list(l, packageName, kinds, recurse); + for (JavaFileObject fo: fileObjects) + results.add(fo); + } + return results.toList(); + } + + @Override // javax.tools.ExtendedLocation + public String inferBinaryName(JavaFileObject file) { + for (Location l: locations) { + String binaryName; + if (l instanceof ExtendedLocation) + binaryName = ((ExtendedLocation) l).inferBinaryName(file); + else + binaryName = fileManager.inferBinaryName(l, file); + if (binaryName != null) + return binaryName; + } + return null; + } + + @Override // javax.tools.JavaFileManager.Location + public String getName() { + return name; + } + + @Override // javax.tools.JavaFileManager.Location + public boolean isOutputLocation() { + return false; + } + + @Override + public String toString() { + return getName(); + } + + Collection<File> getLocation() { + if (!(fileManager instanceof StandardJavaFileManager)) + throw new IllegalStateException(); + StandardJavaFileManager fm = (StandardJavaFileManager) fileManager; + ListBuffer<File> files = new ListBuffer<File>(); + for (Location l: locations) { + Iterable<? extends File> iter = fm.getLocation(l); + // FIXME: need a way to distinguish between empty locations and + // non-standard locations +// if (iter == null) +// throw new IllegalStateException(); + if (iter != null) + for (File f: iter) files.add(f); + } + return files.toList(); + } +}
--- a/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Tue May 07 17:14:17 2013 -0700 @@ -44,16 +44,25 @@ import java.util.EnumSet; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.zip.ZipFile; import javax.lang.model.SourceVersion; +import javax.tools.ExtendedLocation; import javax.tools.FileObject; import javax.tools.JavaFileManager; +import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileObject; +import javax.tools.ModuleFileManager; import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import static javax.tools.StandardLocation.*; + +import com.sun.tools.javac.file.Locations.Path; import com.sun.tools.javac.file.RelativePath.RelativeFile; import com.sun.tools.javac.file.RelativePath.RelativeDirectory; import com.sun.tools.javac.util.BaseFileManager; @@ -61,7 +70,7 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; -import static javax.tools.StandardLocation.*; +import static com.sun.tools.javac.main.Option.*; /** * This class provides access to the source, class and other files @@ -72,7 +81,9 @@ * This code and its internal interfaces are subject to change or * deletion without notice.</b> */ -public class JavacFileManager extends BaseFileManager implements StandardJavaFileManager { +public class JavacFileManager + extends BaseFileManager + implements StandardJavaFileManager, ModuleFileManager { public static char[] toArray(CharBuffer buffer) { if (buffer.hasArray()) @@ -167,7 +178,7 @@ } public JavaFileObject getRegularFile(File file) { - return new RegularFileObject(this, file); + return new RegularFileObject(this, null, file); } public JavaFileObject getFileForOutput(String classname, @@ -254,7 +265,7 @@ * Insert all files in subdirectory subdirectory of directory directory * which match fileKinds into resultList */ - private void listDirectory(File directory, + private void listDirectory(Location location, File directory, RelativeDirectory subdirectory, Set<JavaFileObject.Kind> fileKinds, boolean recurse, @@ -274,7 +285,8 @@ String fname = f.getName(); if (f.isDirectory()) { if (recurse && SourceVersion.isIdentifier(fname)) { - listDirectory(directory, + listDirectory(location, + directory, new RelativeDirectory(subdirectory, fname), fileKinds, recurse, @@ -283,7 +295,7 @@ } else { if (isValidFile(fname, fileKinds)) { JavaFileObject fe = - new RegularFileObject(this, fname, new File(d, fname)); + new RegularFileObject(this, location, fname, new File(d, fname)); resultList.append(fe); } } @@ -326,7 +338,7 @@ * Insert all files in subdirectory subdirectory of container which * match fileKinds into resultList */ - private void listContainer(File container, + private void listContainer(Location location, File container, RelativeDirectory subdirectory, Set<JavaFileObject.Kind> fileKinds, boolean recurse, @@ -335,7 +347,8 @@ if (archive == null) { // archives are not created for directories. if (fsInfo.isDirectory(container)) { - listDirectory(container, + listDirectory(location, + container, subdirectory, fileKinds, recurse, @@ -345,7 +358,7 @@ // Not a directory; either a file or non-existant, create the archive try { - archive = openArchive(container); + archive = openArchive(location, container); } catch (IOException ex) { log.error("error.reading.file", container, getMessage(ex)); @@ -397,6 +410,178 @@ return j < 0; } + private ModuleMode moduleMode; + + @Override // javax.tools.ModuleFileManager + public ModuleMode getModuleMode() { + if (moduleMode == null) { +// boolean cp = hasLocation(StandardLocation.CLASS_PATH) || options.isSet(CLASSPATH); + // MUST-FIX: mp && !cp does not work well in 199 mode, need something better, + // either explicit setModuleMode, or ability to test explicit setLocation -- uugh + boolean cp = options.isSet(CLASSPATH); + boolean mp = hasLocation(StandardLocation.MODULE_PATH) || options.isSet(MODULEPATH); + if (mp && !cp) + moduleMode = ModuleMode.MULTIPLE; + else + moduleMode = ModuleMode.SINGLE; + } + return moduleMode; + } + + @Override // javax.tools.ModuleFileManager + public Location getModuleLocation(Location locn, JavaFileObject fo, String pkgName) + throws InvalidLocationException, InvalidFileObjectException { + if (getModuleMode() == ModuleMode.SINGLE) + return locn; + else { + fo.getClass(); // null check + if (!(fo instanceof BaseFileObject)) + throw new IllegalArgumentException(); + + if (!hasLocation(locn)) + throw new InvalidLocationException(); + String tag = ((BaseFileObject) fo).inferModuleTag(pkgName); + if (tag == null) + throw new InvalidFileObjectException(); + return getModuleLocation(locn, tag); + } + } + + private Map<Location,Iterable<Location>> moduleLocations = + new LinkedHashMap<Location,Iterable<Location>>(); + + @Override // javax.tools.ModuleFileManager + public Iterable<Location> getModuleLocations(Location locn) { + //System.err.println("JavacFileManager.getModuleLocations " + getModuleMode() + " " + locn); + + Iterable<Location> result = moduleLocations.get(locn); + if (result == null) { + Iterable<File> files = locations.getLocation(locn); + if (files == null) + result = List.<Location>nil(); + else { + Set<Location> locns = new LinkedHashSet<Location>(); + for (File file: files) { + if (file.isDirectory()) { + for (File f: file.listFiles()) { + String tag = null; + if (f.isDirectory()) + tag = f.getName(); +// else if (isArchive(f)) { +// String name = f.getName(); +// tag = name.substring(0, name.lastIndexOf(".")); +// } + // FIXME: check if tag has already been seen + if (tag != null) + locns.add(getModuleLocation(locn, tag)); + } + } else { + // ignore archive files for now, these would be "module archive + // files", containing multiple modules in a new but obvious way + } + + } + result = locns; + } + } + +// System.err.println("JavacFileManager.getModuleLocations.result " + result); + return result; + } + + // cleared by setLocation + private Map<String, Location> locationCache = new HashMap<String,Location>(); + + @Override // javax.tools.ModuleFileManager + public Location join(Iterable<? extends Location> list) + throws IllegalArgumentException { + StringBuilder sb = new StringBuilder("{"); + String sep = ""; + for (Location l: list) { + if (!locations.isSupportedLocation(l)) + throw new IllegalArgumentException(l.toString()); + sb.append(sep); + sb.append(l.getName()); + sep = ","; + } + sb.append("}"); + String name = sb.toString(); + + // ugly, rethink this (using name for key) + Location result = locationCache.get(name); + if (result == null) { + // FIXME, could flatten list, and/or use a LinkedHashSet to + // canonicalize list + result = new CompositeLocation(list, this); + locationCache.put(name, result); + } + +// System.err.println("JavacFileManager.join: " + toString(locations) + " = " + result); + return result; + } + + // Get a location for all the containers named "tag" on given location + // Containers may be either directories or archive files. + protected Location getModuleLocation(Location location, String tag) { + // TODO: should reject bad use when location is already a module location + // TODO: should honor location.isOutput() + String name = location.getName() + "[" + tag + "]"; + Location result = locationCache.get(name); + if (result == null) { + Iterable<? extends File> files = locations.getLocation(location); + if (files == null) + throw new IllegalArgumentException(location.getName()); + Path p = locations.new Path(); + if (files != null) { + for (File file: files) { + File dir = new File(file, tag); + if (dir.exists() && dir.isDirectory() || location.isOutputLocation()) + p.addFile(dir); + else { + File jar = new File(file, tag + ".jar"); + if (jar.exists() && jar.isFile()) + p.addFile(jar); + } + } + } + result = locations.createLocation(p, name, locations.getOrigin(location)); + locationCache.put(name, result); + } + return result; + } + + /** + * Update a location based on the bootclasspath options. + * @param l the default platform location if no bootclasspath options are given + * @param first whether or not this is the first platform location + * @param last whether or not this is the last platform location + * @return a list of locations based on the default location and on the + * values of any bootclasspath options. + */ + public List<Location> augmentPlatformLocation(Location l, boolean first, boolean last) { + if (l == StandardLocation.PLATFORM_CLASS_PATH) { + assert (first && last); + return List.of(l); + } + + Path ppPrepend = first ? locations.getPlatformPathPrepend() : null; + Path ppBase = locations.getPlatformPathBase(); + Path ppAppend = last ? locations.getPlatformPathAppend() : null; + + ListBuffer<Location> results = new ListBuffer<Location>(); + if (ppPrepend != null) + results.add(locations.createLocation(ppPrepend, StandardLocation.PLATFORM_CLASS_PATH)); + if (ppBase != null) { + if (first) + results.add(locations.createLocation(ppBase, StandardLocation.PLATFORM_CLASS_PATH)); + } else + results.add(l); + if (ppAppend != null) + results.add(locations.createLocation(ppAppend, StandardLocation.PLATFORM_CLASS_PATH)); + //System.out.println("JFM:augmentPlatformLocation: " + l + " " + first + " " + last + " " + results); + return results.toList(); + } + /** * An archive provides a flat directory structure of a ZipFile by * mapping directory names to lists of files (basenames). @@ -457,12 +642,12 @@ * fail over to the platform zip, and allow it to deal with a potentially * non compliant zip file. */ - protected Archive openArchive(File zipFilename) throws IOException { + protected Archive openArchive(Location location, File zipFilename) throws IOException { try { - return openArchive(zipFilename, contextUseOptimizedZip); + return openArchive(location, zipFilename, contextUseOptimizedZip); } catch (IOException ioe) { if (ioe instanceof ZipFileIndex.ZipFormatException) { - return openArchive(zipFilename, false); + return openArchive(location, zipFilename, false); } else { throw ioe; } @@ -471,7 +656,7 @@ /** Open a new zip file directory, and cache it. */ - private Archive openArchive(File zipFileName, boolean useOptimizedZip) throws IOException { + private Archive openArchive(Location location, File zipFileName, boolean useOptimizedZip) throws IOException { File origZipFileName = zipFileName; if (symbolFileEnabled && locations.isDefaultBootClassPathRtJar(zipFileName)) { File file = zipFileName.getParentFile().getParentFile(); // ${java.home} @@ -523,9 +708,9 @@ if (origZipFileName == zipFileName) { if (!useOptimizedZip) { - archive = new ZipArchive(this, zdir); + archive = new ZipArchive(this, location, zdir); } else { - archive = new ZipFileIndexArchive(this, + archive = new ZipFileIndexArchive(this, location, zipFileIndexCache.getZipFileIndex(zipFileName, null, usePreindexedCache, @@ -534,9 +719,9 @@ } } else { if (!useOptimizedZip) { - archive = new SymbolArchive(this, origZipFileName, zdir, symbolFilePrefix); + archive = new SymbolArchive(this, location, origZipFileName, zdir, symbolFilePrefix); } else { - archive = new ZipFileIndexArchive(this, + archive = new ZipFileIndexArchive(this, location, zipFileIndexCache.getZipFileIndex(zipFileName, symbolFilePrefix, usePreindexedCache, @@ -560,6 +745,7 @@ /** Flush any output resources. */ + @Override // javax.tools.JavaFileManager public void flush() { contentCache.clear(); } @@ -567,6 +753,7 @@ /** * Close the JavaFileManager, releasing resources. */ + @Override // javax.tools.JavaFileManager public void close() { for (Iterator<Archive> i = archives.values().iterator(); i.hasNext(); ) { Archive a = i.next(); @@ -587,6 +774,7 @@ return defaultEncodingName; } + @Override // javax.tools.JavaFileManager public ClassLoader getClassLoader(Location location) { nullCheck(location); Iterable<? extends File> path = getLocation(location); @@ -604,6 +792,7 @@ return getClassLoader(lb.toArray(new URL[lb.size()])); } + @Override // javax.tools.JavaFileManager public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, @@ -611,23 +800,35 @@ throws IOException { // validatePackageName(packageName); + nullCheck(location); nullCheck(packageName); nullCheck(kinds); - Iterable<? extends File> path = getLocation(location); - if (path == null) + if (location instanceof ExtendedLocation) { + return ((ExtendedLocation) location).list(packageName, kinds, recurse); + } + + Iterable<? extends File> files = locations.getLocation(location); + if (files == null) return List.nil(); RelativeDirectory subdirectory = RelativeDirectory.forPackage(packageName); ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>(); - for (File directory : path) - listContainer(directory, subdirectory, kinds, recurse, results); + for (File file: files) { + listContainer(location, file, subdirectory, kinds, recurse, results); + } + return results.toList(); } + @Override // javax.tools.JavaFileManager public String inferBinaryName(Location location, JavaFileObject file) { file.getClass(); // null check location.getClass(); // null check + + if (location instanceof ExtendedLocation) + return ((ExtendedLocation) location).inferBinaryName(file); + // Need to match the path semantics of list(location, ...) Iterable<? extends File> path = getLocation(location); if (path == null) { @@ -637,9 +838,11 @@ if (file instanceof BaseFileObject) { return ((BaseFileObject) file).inferBinaryName(path); } else - throw new IllegalArgumentException(file.getClass().getName()); +// throw new IllegalArgumentException(file.getClass().getName() + ":" + file.toString()); + return null; // FIXME -- seems OK per spec but need to check } + @Override // javax.tools.JavaFileManager public boolean isSameFile(FileObject a, FileObject b) { nullCheck(a); nullCheck(b); @@ -650,24 +853,28 @@ return a.equals(b); } + @Override // javax.tools.JavaFileManager public boolean hasLocation(Location location) { - return getLocation(location) != null; + return (location instanceof ExtendedLocation || (getLocation(location) != null)); } + @Override // javax.tools.JavaFileManager public JavaFileObject getJavaFileForInput(Location location, String className, JavaFileObject.Kind kind) throws IOException { nullCheck(location); - // validateClassName(className); + // validateClassName(className);g518 + nullCheck(className); nullCheck(kind); if (!sourceOrClass.contains(kind)) throw new IllegalArgumentException("Invalid kind: " + kind); - return getFileForInput(location, RelativeFile.forClass(className, kind)); + return getFileForInput(location, RelativeFile.forClass(className, kind), kind); } + @Override // javax.tools.JavaFileManager public FileObject getFileForInput(Location location, String packageName, String relativeName) @@ -681,25 +888,44 @@ RelativeFile name = packageName.length() == 0 ? new RelativeFile(relativeName) : new RelativeFile(RelativeDirectory.forPackage(packageName), relativeName); - return getFileForInput(location, name); + return getFileForInput(location, name, getKindForName(name.path)); + } + + private JavaFileObject.Kind getKindForName(String name) { + for (JavaFileObject.Kind k: JavaFileObject.Kind.values()) { + if (k != JavaFileObject.Kind.OTHER && name.endsWith(k.extension)) { + return k; + } + } + return JavaFileObject.Kind.OTHER; } - private JavaFileObject getFileForInput(Location location, RelativeFile name) throws IOException { - Iterable<? extends File> path = getLocation(location); - if (path == null) + private JavaFileObject getFileForInput(Location location, RelativeFile name, + JavaFileObject.Kind kind) throws IOException { + if (location instanceof CompositeLocation) { + for (Location l: ((CompositeLocation) location).locations) { + JavaFileObject fo = getFileForInput(l, name, kind); + if (fo != null) + return fo; + } + return null; + } + + Iterable<? extends File> files = locations.getLocation(location); + if (files == null) return null; - for (File dir: path) { - Archive a = archives.get(dir); + for (File file: files) { + Archive a = archives.get(file); if (a == null) { - if (fsInfo.isDirectory(dir)) { - File f = name.getFile(dir); + if (fsInfo.isDirectory(file)) { + File f = name.getFile(file); if (f.exists()) - return new RegularFileObject(this, f); + return new RegularFileObject(this, location, f); continue; } // Not a directory, create the archive - a = openArchive(dir); + a = openArchive(location, file); } // Process the archive if (a.contains(name)) { @@ -709,6 +935,7 @@ return null; } + @Override // javax.tools.JavaFileManager public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, @@ -724,6 +951,7 @@ return getFileForOutput(location, RelativeFile.forClass(className, kind), sibling); } + @Override // javax.tools.JavaFileManager public FileObject getFileForOutput(Location location, String packageName, String relativeName, @@ -741,6 +969,7 @@ return getFileForOutput(location, name, sibling); } + // FIXME: compare against tl private JavaFileObject getFileForOutput(Location location, RelativeFile fileName, FileObject sibling) @@ -755,24 +984,28 @@ if (sibling != null && sibling instanceof RegularFileObject) { siblingDir = ((RegularFileObject)sibling).file.getParentFile(); } - return new RegularFileObject(this, new File(siblingDir, fileName.basename())); + return new RegularFileObject(this, location, new File(siblingDir, fileName.basename())); } } else if (location == SOURCE_OUTPUT) { dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir()); } else { + dir = null; Iterable<? extends File> path = locations.getLocation(location); - dir = null; - for (File f: path) { - dir = f; - break; + if (path != null) { + for (File e: path) { + dir = e; + break; + } } + //System.err.println("JavacFileManager.getFileForOutput location:" + location + " path:" + toString(path) + " dir:" + dir); } File file = fileName.getFile(dir); // null-safe - return new RegularFileObject(this, file); + return new RegularFileObject(this, location, file); } + @Override // javax.tools.StandardJavaFileManager public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles( Iterable<? extends File> files) { @@ -782,23 +1015,32 @@ else result = new ArrayList<RegularFileObject>(); for (File f: files) - result.add(new RegularFileObject(this, nullCheck(f))); + result.add(new RegularFileObject(this, null, nullCheck(f))); return result; } + @Override // javax.tools.StandardJavaFileManager public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) { return getJavaFileObjectsFromFiles(Arrays.asList(nullCheck(files))); } + @Override // javax.tools.StandardJavaFileManager public void setLocation(Location location, Iterable<? extends File> path) throws IOException { nullCheck(location); locations.setLocation(location, path); + locationCache.clear(); } - public Iterable<? extends File> getLocation(Location location) { + @Override // javax.tools.StandardJavaFileManager + public Iterable<File> getLocation(Location location) { + return locations.getLocation(location); + } + + @Deprecated // remove uses of this method + Iterable<File> getEntriesForLocation(Location location) { nullCheck(location); return locations.getLocation(location); }
--- a/src/share/classes/com/sun/tools/javac/file/Locations.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/file/Locations.java Tue May 07 17:14:17 2013 -0700 @@ -25,8 +25,8 @@ package com.sun.tools.javac.file; +import javax.tools.ExtendedLocation; import java.io.FileNotFoundException; -import java.util.Iterator; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; @@ -37,12 +37,13 @@ import java.util.EnumMap; import java.util.EnumSet; import java.util.HashMap; -import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.zip.ZipFile; + import javax.tools.JavaFileManager.Location; import javax.tools.StandardLocation; @@ -52,15 +53,15 @@ import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Options; -import javax.tools.JavaFileManager; import javax.tools.StandardJavaFileManager; import static javax.tools.StandardLocation.*; import static com.sun.tools.javac.main.Option.*; -/** This class converts command line arguments, environment variables +/** + * This class converts command line arguments, environment variables * and system properties (in File.pathSeparator-separated String form) * into a boot class path, user class path, and source path (in - * {@code Collection<String>} form). + * Collection<PathEntry> form). * * <p><b>This is NOT part of any supported API. * If you write code that depends on this, you do so at your own risk. @@ -98,6 +99,16 @@ this.fsInfo = fsInfo; } + boolean isSupportedLocation(Location l) { + return (l instanceof StandardLocation) + || (l instanceof PathLocation) + || (l instanceof ExtendedLocation); + } + + Location getOrigin(Location l) { + return (l instanceof PathLocation) ? ((PathLocation) l).origin : l; + } + public Collection<File> bootClassPath() { return getLocation(PLATFORM_CLASS_PATH); } @@ -158,15 +169,88 @@ return entries; } + Location createLocation(Path path, Location origin) { + return new PathLocation(path, origin); + } + + Location createLocation(Path path, String name, Location origin) { + return new PathLocation(path, name, origin); + } + + private static class PathLocation implements Location { + final Collection<File> files; + final String name; + final Location origin; + + @Deprecated // FIXME should not use static count + static int count; + + PathLocation(Path p, Location origin) { + files = p.toFiles(); + //name = "pathLocation#" + (count++) + p; + name = "pathLocation#" + (count++) + "(path=" + p + ")"; + this.origin = origin; + } + + PathLocation(Path p, String name, Location origin) { + files = p.toFiles(); + this.name = name; + this.origin = origin; + } + + public String getName() { + return name; + } + + public boolean isOutputLocation() { + return false; + } + + @Override + public String toString() { + return getName(); + } + } + + private class PathEntry { + PathEntry(File file) { + file.getClass(); // null check + this.file = file; + this.canonFile = fsInfo.getCanonicalFile(file); + } + + @Override + public boolean equals(Object other) { + if (this == other) + return true; + if (!(other instanceof PathEntry)) + return false; + PathEntry o = (PathEntry) other; + return canonFile.equals(o.canonFile); + } + + @Override + public int hashCode() { + return canonFile.hashCode(); + } + + @Override + public String toString() { + return file.getPath(); + } + + final File file; + final File canonFile; + } + /** * Utility class to help evaluate a path option. * Duplicate entries are ignored, jar class paths can be expanded. */ - private class Path extends LinkedHashSet<File> { + class Path extends LinkedHashSet<PathEntry> { private static final long serialVersionUID = 0; private boolean expandJarClassPaths = false; - private Set<File> canonicalValues = new HashSet<File>(); public Path expandJarClassPaths(boolean x) { expandJarClassPaths = x; @@ -181,8 +265,10 @@ return this; } - public Path() { super(); } - + /** Add all the jar files found in one or more directories. + * @param dirs one or more directories separated by path separator char + * @param whether to generate a warning if a given directory does not exist + */ public Path addDirectories(String dirs, boolean warn) { boolean prev = expandJarClassPaths; expandJarClassPaths = true; @@ -196,10 +282,18 @@ } } + /** Add all the jar files found in one or more directories. + * Warnings about non-existent directories are given iff Paths.warn is set. + * @param dirs one or more directories separated by path separator char + */ public Path addDirectories(String dirs) { return addDirectories(dirs, warn); } + /** Add all the jar files found in a directory. + * @param dirs one or more directories separated by path separator char + * @param whether to generate a warning if a given directory does not exist + */ private void addDirectory(File dir, boolean warn) { if (!dir.isDirectory()) { if (warn) @@ -218,6 +312,10 @@ } } + /** Add directories and archive files. + * @param files one or more directories and archive files separated by path separator char + * @param whether to generate a warning if a given entry does not exist + */ public Path addFiles(String files, boolean warn) { if (files != null) { addFiles(getPathEntries(files, emptyPathDefault), warn); @@ -241,25 +339,31 @@ return addFiles(files, warn); } + /** Add a directory or archive file. + * @param file directory or archive file to be added + */ + public void addFile(File file) { + addFile(file, warn); + } + + /** Add a directory or archive file. + * @param file directory or archive file to be added + * @param warn whether to generate a warning if the file does not exist + */ public void addFile(File file, boolean warn) { - if (contains(file)) { - // discard duplicates + PathEntry entry = new PathEntry(file); + if (contains(entry)) { + /* Discard duplicates and avoid infinite recursion */ return; } - if (! fsInfo.exists(file)) { + if (!fsInfo.exists(file)) { /* No such file or directory exists */ if (warn) { log.warning(Lint.LintCategory.PATH, "path.element.not.found", file); } - super.add(file); - return; - } - - File canonFile = fsInfo.getCanonicalFile(file); - if (canonicalValues.contains(canonFile)) { - /* Discard duplicates and avoid infinite recursion */ + super.add(entry); return; } @@ -288,8 +392,7 @@ /* Now what we have left is either a directory or a file name conforming to archive naming convention */ - super.add(file); - canonicalValues.add(canonFile); + super.add(entry); if (expandJarClassPaths && fsInfo.isFile(file)) addJarClassPath(file, warn); @@ -308,6 +411,24 @@ log.error("error.reading.file", jarFile, JavacFileManager.getMessage(e)); } } + + void addAll(Iterable<PathEntry> entries) { + for (PathEntry e: entries) + add(e); + } + + Collection<File> toFiles() { + ListBuffer<File> files = new ListBuffer<File>(); + for (PathEntry e: this) + files.add(e.file); + return files.toList(); + } + + // DEBUG + @Override + public String toString() { + return "Path(" + super.toString() + ")"; + } } /** @@ -345,9 +466,9 @@ /** @see JavaFileManager#handleOption */ abstract boolean handleOption(Option option, String value); - /** @see StandardJavaFileManager#getLocation */ + /** @see StandardJavaFileManager#getLocation. */ abstract Collection<File> getLocation(); - /** @see StandardJavaFileManager#setLocation */ + /** @see StandardJavaFileManager#setLocation. */ abstract void setLocation(Iterable<? extends File> files) throws IOException; } @@ -419,8 +540,7 @@ boolean handleOption(Option option, String value) { if (!options.contains(option)) return false; - searchPath = value == null ? null : - Collections.unmodifiableCollection(createPath().addFiles(value)); + searchPath = (value == null) ? null : computePath(value).toFiles(); return true; } @@ -437,7 +557,7 @@ } else { p = createPath().addFiles(files); } - searchPath = Collections.unmodifiableCollection(p); + searchPath = p.toFiles(); } protected Path computePath(String value) { @@ -585,7 +705,7 @@ defaultBootClassPathRtJar = null; isDefaultBootClassPath = false; Path p = new Path().addFiles(files, false); - searchPath = Collections.unmodifiableCollection(p); + searchPath = p.toFiles(); optionValues.clear(); } } @@ -639,7 +759,7 @@ private void lazy() { if (searchPath == null) - searchPath = Collections.unmodifiableCollection(computePath()); + searchPath = computePath().toFiles(); } } @@ -653,6 +773,7 @@ LocationHandler[] handlers = { new BootClassPathLocationHandler(), new ClassPathLocationHandler(), + new SimpleLocationHandler(StandardLocation.MODULE_PATH, Option.MODULEPATH), new SimpleLocationHandler(StandardLocation.SOURCE_PATH, Option.SOURCEPATH), new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_PATH, Option.PROCESSORPATH), new OutputLocationHandler((StandardLocation.CLASS_OUTPUT), Option.D), @@ -673,6 +794,11 @@ } Collection<File> getLocation(Location location) { + if (location instanceof PathLocation) + return ((PathLocation) location).files; + if (location instanceof CompositeLocation) + return ((CompositeLocation) location).getLocation(); + LocationHandler h = getHandler(location); return (h == null ? null : h.getLocation()); } @@ -685,6 +811,7 @@ } void setLocation(Location location, Iterable<? extends File> files) throws IOException { + //FIXME: should we be able to set values for PathLocation and ExtendedLocation LocationHandler h = getHandler(location); if (h == null) { if (location.isOutputLocation()) @@ -715,6 +842,65 @@ } } + /** + * Get any classes that should appear before the main platform classes. + * For compatibility, this is the classes defined by -Xbootclasspath/p: + * and the contents of the endorsed directories. + * See computeBootClassPath() for the full definition of the legacy + * platform class path. + */ + Path getPlatformPathPrepend() { + //return getPathForOption(XBOOTCLASSPATH_PREPEND, EnumSet.of(JavaFileObject.Kind.CLASS)); + Path path = new Path(); + + path.addFiles(options.get(XBOOTCLASSPATH_PREPEND)); + + String optionValue; + if ((optionValue = options.get(ENDORSEDDIRS)) != null) + path.addDirectories(optionValue); + else + path.addDirectories(System.getProperty("java.endorsed.dirs"), false); + + return (path.size() == 0 ? null : path); + } + + /** + * Get the main platform classes. + * For now, this is just the classes defined by -bootclasspath or -Xbootclasspath. + * See computeBootClassPath() for the full definition of the legacy + * platform class path. + */ + Path getPlatformPathBase() { + Path path = new Path(); + path.addFiles(options.get(BOOTCLASSPATH)); + return (path.size() == 0 ? null : path); + } + + /** + * Get any classes that should appear after the main platform classes. + * For compatibility, this is the classes defined by -Xbootclasspath/a: + * and the contents of the extension directories. + * See computeBootClassPath() for the full definition of the legacy + * platform class path. + */ + Path getPlatformPathAppend() { + //return getPathForOption(XBOOTCLASSPATH_APPEND, EnumSet.of(JavaFileObject.Kind.CLASS)); + Path path = new Path(); + + path.addFiles(options.get(XBOOTCLASSPATH_APPEND)); + + // Strictly speaking, standard extensions are not bootstrap + // classes, but we treat them identically, so we'll pretend + // that they are. + String optionValue; + if ((optionValue = options.get(EXTDIRS)) != null) + path.addDirectories(optionValue); + else + path.addDirectories(System.getProperty("java.ext.dirs"), false); + + return (path.size() == 0 ? null : path); + } + /** Is this the name of an archive file? */ private boolean isArchive(File file) { String n = file.getName().toLowerCase();
--- a/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java Tue May 07 17:14:17 2013 -0700 @@ -39,6 +39,7 @@ import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharsetDecoder; +import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileObject; /** @@ -58,12 +59,12 @@ final File file; private Reference<File> absFileRef; - public RegularFileObject(JavacFileManager fileManager, File f) { - this(fileManager, f.getName(), f); + public RegularFileObject(JavacFileManager fileManager, Location location, File f) { + this(fileManager, location, f.getName(), f); } - public RegularFileObject(JavacFileManager fileManager, String name, File f) { - super(fileManager); + public RegularFileObject(JavacFileManager fileManager, Location location, String name, File f) { + super(fileManager, location); if (f.isDirectory()) { throw new IllegalArgumentException("directories not supported"); } @@ -169,6 +170,25 @@ return null; } + protected String inferModuleTag(String pkgName) { + File fn = file.getAbsoluteFile(); + //System.err.println("RegularFileObject.inferModuleTag.args " + fn + " '" + pkgName + "'"); + fn = fn.getParentFile(); + if (pkgName.length() > 0) { + String[] pn = pkgName.replace('/', '.').split("\\."); + //System.err.println("RegularFileObject.inferModuleTag.pn " + Arrays.asList(pn) + " " + pn.length); + for (int i = pn.length - 1; i >= 0; i--) { + String n = fn.getName(); + if (n.equalsIgnoreCase(pn[i])) // FIXME: should be File.equals + fn = fn.getParentFile(); + else + return null; + } + } + //System.err.println("RegularFileObject.inferModuleTag.result " + (fn == null ? null : fn.getName())); + return (fn == null ? null : fn.getName()); + } + @Override public boolean isNameCompatible(String cn, JavaFileObject.Kind kind) { cn.getClass();
--- a/src/share/classes/com/sun/tools/javac/file/SymbolArchive.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/file/SymbolArchive.java Tue May 07 17:14:17 2013 -0700 @@ -29,6 +29,8 @@ import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; + +import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileObject; import com.sun.tools.javac.file.RelativePath.RelativeDirectory; @@ -46,8 +48,8 @@ final File origFile; final RelativeDirectory prefix; - public SymbolArchive(JavacFileManager fileManager, File orig, ZipFile zdir, RelativeDirectory prefix) throws IOException { - super(fileManager, zdir, false); + public SymbolArchive(JavacFileManager fileManager, Location location, File orig, ZipFile zdir, RelativeDirectory prefix) throws IOException { + super(fileManager, location, zdir, false); this.origFile = orig; this.prefix = prefix; initMap();
--- a/src/share/classes/com/sun/tools/javac/file/ZipArchive.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/file/ZipArchive.java Tue May 07 17:14:17 2013 -0700 @@ -30,6 +30,8 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.Writer; +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; import java.net.URI; import java.nio.ByteBuffer; import java.nio.CharBuffer; @@ -41,14 +43,13 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileObject; import com.sun.tools.javac.file.JavacFileManager.Archive; import com.sun.tools.javac.file.RelativePath.RelativeDirectory; import com.sun.tools.javac.file.RelativePath.RelativeFile; import com.sun.tools.javac.util.List; -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; /** * <p><b>This is NOT part of any supported API. @@ -58,12 +59,13 @@ */ public class ZipArchive implements Archive { - public ZipArchive(JavacFileManager fm, ZipFile zfile) throws IOException { - this(fm, zfile, true); + public ZipArchive(JavacFileManager fm, Location location, ZipFile zfile) throws IOException { + this(fm, location, zfile, true); } - protected ZipArchive(JavacFileManager fm, ZipFile zfile, boolean initMap) throws IOException { + protected ZipArchive(JavacFileManager fm, Location location, ZipFile zfile, boolean initMap) throws IOException { this.fileManager = fm; + this.location = location; this.zfile = zfile; this.map = new HashMap<RelativeDirectory,List<String>>(); if (initMap) @@ -141,7 +143,13 @@ /** * The file manager that created this archive. */ - protected JavacFileManager fileManager; + protected final JavacFileManager fileManager; + + /** + * The location containing this archive. + */ + protected final Location location; + /** * The index for the contents of this archive. */ @@ -165,7 +173,7 @@ ZipEntry entry; protected ZipFileObject(ZipArchive zarch, String name, ZipEntry entry) { - super(zarch.fileManager); + super(zarch.fileManager, zarch.location); this.zarch = zarch; this.name = name; this.entry = entry; @@ -252,6 +260,12 @@ } @Override + protected String inferModuleTag(String binaryName) { + File zf = new File(zarch.zfile.getName()); + return removeExtension(zf.getName()); + } + + @Override public boolean isNameCompatible(String cn, JavaFileObject.Kind k) { cn.getClass(); // null check
--- a/src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java Tue May 07 17:14:17 2013 -0700 @@ -25,12 +25,9 @@ package com.sun.tools.javac.file; -import java.io.IOException; -import java.util.Set; -import javax.tools.JavaFileObject; - import java.io.ByteArrayInputStream; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Writer; @@ -38,6 +35,10 @@ import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharsetDecoder; +import java.util.Set; + +import javax.tools.JavaFileManager.Location; +import javax.tools.JavaFileObject; import com.sun.tools.javac.file.JavacFileManager.Archive; import com.sun.tools.javac.file.RelativePath.RelativeDirectory; @@ -54,11 +55,13 @@ public class ZipFileIndexArchive implements Archive { private final ZipFileIndex zfIndex; - private JavacFileManager fileManager; + private final JavacFileManager fileManager; + private final Location location; - public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException { + public ZipFileIndexArchive(JavacFileManager fileManager, Location location, ZipFileIndex zdir) throws IOException { super(); this.fileManager = fileManager; + this.location = location; this.zfIndex = zdir; } @@ -73,7 +76,7 @@ public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) { RelativeFile fullZipFileName = new RelativeFile(subdirectory, file); ZipFileIndex.Entry entry = zfIndex.getZipIndexEntry(fullZipFileName); - JavaFileObject ret = new ZipFileIndexFileObject(fileManager, zfIndex, entry, zfIndex.getZipFile()); + JavaFileObject ret = new ZipFileIndexFileObject(fileManager, location, zfIndex, entry, zfIndex.getZipFile()); return ret; } @@ -116,8 +119,8 @@ File zipName; - ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndex.Entry entry, File zipFileName) { - super(fileManager); + ZipFileIndexFileObject(JavacFileManager fileManager, Location location, ZipFileIndex zfIndex, ZipFileIndex.Entry entry, File zipFileName) { + super(fileManager, location); this.name = entry.getFileName(); this.zfIndex = zfIndex; this.entry = entry; @@ -249,6 +252,9 @@ else return entry.getName(); } + protected String inferModuleTag(String binaryName) { + return removeExtension(zfIndex.getZipFile().getName()); + } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/javac/jigsaw/JavacCatalog.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.jigsaw; + +import java.io.File; +import java.io.IOException; +import java.lang.module.Dependence; +import java.lang.module.ModuleId; +import java.lang.module.ModuleIdQuery; +import java.lang.module.ModuleInfo; +import java.lang.module.ModuleView; +import java.lang.module.ServiceDependence; +import java.lang.module.ViewDependence; +import java.lang.module.Version; +import java.lang.module.VersionQuery; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import javax.lang.model.element.ModuleElement; + +import org.openjdk.jigsaw.Catalog; +import org.openjdk.jigsaw.JigsawModuleSystem; +import org.openjdk.jigsaw.Library; +import org.openjdk.jigsaw.SimpleLibrary; + +import com.sun.tools.javac.code.Directive.PermitsDirective; +import com.sun.tools.javac.code.Directive.ProvidesModuleDirective; +import com.sun.tools.javac.code.Directive.ProvidesServiceDirective; +import com.sun.tools.javac.code.Directive.RequiresFlag; +import com.sun.tools.javac.code.Directive.RequiresModuleDirective; +import com.sun.tools.javac.code.Directive.ViewDeclaration; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.code.Symbol.ClassSymbol; +import com.sun.tools.javac.code.Symbol.ModuleSymbol; +import com.sun.tools.javac.jvm.ClassFile; +import com.sun.tools.javac.util.Name; + + +/* + * Implementation of a Jigsaw catalog providing access to the modules + * in a compilation found with command line options such as modulepath, + * classpath and sourcepath. + */ +public class JavacCatalog extends Catalog { + final JigsawModuleSystem jigsaw; + final Library library; + + private Map<String, Map<Version, ModuleSymbol>> moduleMap = + new HashMap<String, Map<Version, ModuleSymbol>>(); + private Version nullVersion; // used in the moduleMap + + boolean DEBUG = (System.getProperty("javac.debug.modules") != null); + void DEBUG(String s) { + if (DEBUG) + System.err.println(s); + } + + JavacCatalog(File library) throws IOException/*FIXME*/ { + jigsaw = JigsawModuleSystem.instance(); + nullVersion = jigsaw.parseVersion("0"); + if (library == null) + this.library = Library.openSystemLibrary(); + else + this.library = SimpleLibrary.open(library); + DEBUG("JavacCatalog: library:" + library + " this.library:" + this.library); + } + + @Override + public String name() { + return "javac"; // can we do anything better here? + } + + @Override + public Catalog parent() { + return library; + } + + void init(Iterable<? extends ModuleElement> modules) { + DEBUG("JavacCatalog.init: " + modules); + for (ModuleElement me: modules) { + ModuleSymbol msym = (ModuleSymbol) me; + DEBUG("JavacCatalog.init: msym:" + msym + " msym.fullname:" + msym.fullname + " msym.version:" + msym.version); + addModule(msym.fullname, msym.version, msym); + for (ViewDeclaration v: msym.getViews()) { + if (v.name != null) { + addModule(v.name, msym.version, msym); + } + for (ProvidesModuleDirective d: v.getAliases()) { + com.sun.tools.javac.code.ModuleId alias = d.moduleId; + addModule(alias.name, alias.version, msym); + } + } + } + DEBUG("JavacCatalog.init: map:" + moduleMap); + } + + private void addModule(Name name, Name version, ModuleSymbol msym) { + String n = name.toString(); + Version v = getVersion(version); + Map<Version,ModuleSymbol> map = moduleMap.get(n); + if (map == null) + moduleMap.put(n, map = new HashMap<Version,ModuleSymbol>()); + if (v != null) + map.put(v, msym); + else + map.put(nullVersion, msym); + } + + @Override + protected void gatherLocalModuleIds(String moduleName, Set<ModuleId> mids) throws IOException { + DEBUG("JavacCatalog.gatherLocalModuleIds: " + moduleName); + if (moduleName != null) { + Map<Version,ModuleSymbol> syms = moduleMap.get(moduleName); + if (syms == null) + return; + addModuleIds(syms, moduleName, mids); + } else { + for (String mn : moduleMap.keySet()) { + addModuleIds(moduleMap.get(mn), moduleName, mids); + } + } + DEBUG("JavacCatalog.gatherLocalModuleIds: moduleName:" + moduleName + "--" + mids); + } + + protected void gatherLocalDeclaringModuleIds(Set<ModuleId> mids) throws IOException { + DEBUG("JavacCatalog.gatherLocalDeclaringModuleIds"); + for (Map<Version,ModuleSymbol> map : moduleMap.values()) { + for (ModuleSymbol sym : map.values()) { + ModuleId mid = getModuleId(sym); + mids.add(mid); + } + } + DEBUG("JavacCatalog.gatherLocalDeclaringModuleIds: " + "--" + mids); + } + + // add all ModuleIds of the given name + private void addModuleIds(Map<Version,ModuleSymbol> map, + String mn, Set<ModuleId> mids) { + for (ModuleSymbol sym : map.values()) { + ModuleId mid = getModuleId(sym); + if (mn == null || mid.name().equals(mn)) { + mids.add(mid); + } + for (ViewDeclaration v : sym.getViews()) { + Name n = v.name == null ? sym.fullname : v.name; + if (mn == null || mn.equals(n.toString())) { + mid = getModuleId(n, sym.version); + if (!mids.contains(mid)) + mids.add(mid); + } + + for (ProvidesModuleDirective d : v.getAliases()) { + mids.add(getModuleId(d.moduleId)); + } + } + } + } + + @Override + protected ModuleInfo readLocalModuleInfo(ModuleId mid) throws IOException { + DEBUG("JavacCatalog.readLocalModuleInfo " + mid); + ModuleSymbol msym = getModuleSymbol(mid); + DEBUG("JavacCatalog.readLocalModuleInfo " + mid + "--" + ((msym == null) ? null : new JavacModuleInfo(msym))); + return (msym == null) ? null : new JavacModuleInfo(msym); + } + +// private ModuleId getModuleId(ModuleSymbol msym) { +// return getModuleId(new ClassFile.ModuleId(msym.fullname, msym.version)); +// } +// +// private ModuleId getModuleId(ClassFile.ModuleId cf_mid) { +// ModuleId id = moduleIdCache.get(cf_mid); +// if (id == null) { +// Name name = cf_mid.name; +// Name version = cf_mid.version; +// String s = (version == null) ? name.toString() : (name + "@" + version); +// moduleIdCache.put(cf_mid, id = jigsaw.parseModuleId(s)); +// } +// return id; +// } +// + ModuleSymbol getModuleSymbol(ModuleId mid) { + Map<Version,ModuleSymbol> map = moduleMap.get(mid.name()); + if (map == null) + return null; + return (mid.version() == null) ? map.get(nullVersion) : map.get(mid.version()); + } + + Version getVersion(Name v) { + return (v == null) ? null : jigsaw.parseVersion(v.toString()); // FIXME -- throws IllegalArgumentException + } + + VersionQuery getVersionQuery(Name vq) { + return (vq == null) ? null : jigsaw.parseVersionQuery(vq.toString()); // FIXME -- throws IllegalArgumentException + } + + ModuleId getModuleId(ModuleSymbol sym) { + return getModuleId(sym.fullname, sym.version); // FIXME -- throws IllegalArgumentException + } + + ModuleId getModuleId(com.sun.tools.javac.code.ModuleId mid) { + return getModuleId(mid.name, mid.version); // FIXME -- throws IllegalArgumentException + } + + ModuleId getModuleId(Name n, Name v) { + String mid = (v == null) ? n.toString() : (n + "@" + v); + return jigsaw.parseModuleId(mid); // FIXME -- throws IllegalArgumentException + } + + ModuleIdQuery getModuleQuery(com.sun.tools.javac.code.ModuleQuery midq) { + return getModuleIdQuery(midq.name, midq.versionQuery); // FIXME -- throws IllegalArgumentException + } + + ModuleIdQuery getModuleIdQuery(ModuleElement.ModuleQuery midq) { + return getModuleIdQuery(midq.getName(), midq.getVersionQuery()); + } + + ModuleIdQuery getModuleIdQuery(Name n, Name vq) { + String midq = (vq == null) ? n.toString() : (n + "@" + vq); + return jigsaw.parseModuleIdQuery(midq); // FIXME -- throws IllegalArgumentException + } + + ModuleIdQuery getModuleIdQuery(CharSequence n, CharSequence vq) { + String q = (vq == null || vq.length() == 0) ? String.valueOf(n) : (n + "@" + vq); + return jigsaw.parseModuleIdQuery(q); + } + + Dependence.Modifier getModifier(RequiresFlag f) { + switch (f) { + case LOCAL: + return Dependence.Modifier.LOCAL; + case OPTIONAL: + return Dependence.Modifier.OPTIONAL; + case REEXPORT: + return Dependence.Modifier.PUBLIC; + case SYNTHETIC: + return Dependence.Modifier.SYNTHETIC; + case SYNTHESIZED: + return Dependence.Modifier.SYNTHESIZED; + default: + throw new IllegalArgumentException(f.toString()); // FIXME -- throws IllegalArgumentException + } + } + + class JavacModuleInfo implements ModuleInfo { + ModuleSymbol msym; + + ModuleId id; + Set<ViewDependence> requiresModules; + Map<ModuleId, ModuleView> views; + + JavacModuleInfo(ModuleSymbol msym) { + msym.getClass(); // null check + DEBUG("JavacModuleInfo: msym: " + msym); + + this.msym = msym; + this.views = new HashMap<ModuleId, ModuleView>(); + + this.id = getModuleId(msym); // FIXME -- throws IllegalArgumentException + + for (ViewDeclaration v : msym.getViews()) { + String mainClass = null; + + if (v.hasEntrypoint()) { + mainClass = new String(ClassFile.externalize(v.getEntrypoint().flatname)); + } + + Set<String> permits = new LinkedHashSet<String>(); + for (PermitsDirective d : v.getPermits()) { + permits.add(d.moduleId.name.toString()); // FIXME: validate name? + } + + Set<String> exports = new LinkedHashSet<String>(); + + Set<ModuleId> provides = new LinkedHashSet<ModuleId>(); + for (ProvidesModuleDirective d : v.getAliases()) { + provides.add(getModuleId(d.moduleId)); + } + + Map<String,Set<String>> services = new LinkedHashMap<String,Set<String>>(); + for (ProvidesServiceDirective s : v.getServices()) { + String sn = new String(ClassFile.externalize(s.service.flatname)); + String pn = new String(ClassFile.externalize(s.impl.flatname)); + Set<String> providers = services.get(sn); + if (providers == null) { + providers = new LinkedHashSet<String>(); + services.put(sn, providers); + } + providers.add(pn); + } + + ModuleId vid = (v.name == null) + ? id + : getModuleId(v.name, msym.version); + ModuleView view = new JavacModuleView(this, + vid, + mainClass, + provides, + exports, + permits, + services); + views.put(vid, view); + } + + if (!views.containsKey(id)) { + // create the default view if not exists + views.put(id, new JavacModuleView(this, + id, + null, + Collections.<ModuleId>emptySet(), + Collections.<String>emptySet(), + Collections.<String>emptySet(), + Collections.<String,Set<String>>emptyMap())); + } + + requiresModules = new LinkedHashSet<ViewDependence>(); + for (RequiresModuleDirective r: msym.getRequiredModules()) { + DEBUG("JavacModuleInfo: require " + r); + ModuleIdQuery q = getModuleQuery(r.moduleQuery); + EnumSet<Dependence.Modifier> mods = EnumSet.noneOf(Dependence.Modifier.class); + for (com.sun.tools.javac.code.Directive.RequiresFlag f: r.flags) { + mods.add(getModifier(f)); // FIXME -- throws IllegalArgumentException + } + requiresModules.add(new ViewDependence(mods, q)); + } + DEBUG("JavacModuleInfo: msym: " + msym + "[id:" + id + " views:" + views + " requires:" + requiresModules + "]"); + } + + @Override + public ModuleId id() { + return id; + } + + @Override + public Set<ViewDependence> requiresModules() { + return requiresModules; + } + + public Set<ServiceDependence> requiresServices() { + return Collections.emptySet(); + } + + public ModuleView defaultView() { + return views.get(id); + } + + public Set<ModuleView> views() { + return Collections.unmodifiableSet(new HashSet<ModuleView>(views.values())); + } + } + + class JavacModuleView + implements ModuleView + { + private final ModuleInfo mi; + private final ModuleId id; + private final Set<String> exports; + private final Set<ModuleId> aliases; + private final Map<String,Set<String>> services; + private final Set<String> permits; + private final String mainClass; + + JavacModuleView(ModuleInfo mi, + ModuleId id, + String mainClass, + Set<ModuleId> aliases, + Set<String> exports, + Set<String> permits, + Map<String,Set<String>> serviceProviders) { + this.mi = mi; + this.id = id; + this.mainClass = mainClass; + this.aliases = aliases; + this.exports = exports; + this.permits = permits; + this.services = serviceProviders; + } + + public ModuleInfo moduleInfo() { + return mi; + } + + public ModuleId id() { + return id; + } + + public Set<ModuleId> aliases() { + return Collections.unmodifiableSet(aliases); + } + + public Set<String> exports() { + return Collections.unmodifiableSet(exports); + } + + public Set<String> permits() { + return Collections.unmodifiableSet(permits); + } + + public Map<String,Set<String>> services() { + return Collections.unmodifiableMap(services); + } + + public String mainClass() { + return mainClass; + } + + @Override + public String toString() { + return "View { id: " + id + + ", provides: " + aliases + + ", provides service: " + services + + ", permits: " + permits + + ", mainClass: " + mainClass + + " }"; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/javac/jigsaw/JigsawLibraryLocation.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.jigsaw; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.lang.module.ModuleId; +import java.net.URI; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import javax.lang.model.element.Modifier; +import javax.lang.model.element.NestingKind; +import javax.tools.ExtendedLocation; +import javax.tools.FileObject; +import javax.tools.JavaFileManager.Location; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; + +import org.openjdk.jigsaw.Library; + +import com.sun.tools.javac.util.ListBuffer; + +/** + * A location to represent a Jigsaw module in a Jigsaw module library. + */ +public class JigsawLibraryLocation implements ExtendedLocation { + private Library library; + private ModuleId mid; + + // Quick and dirty temporary debug printing; + // this should all be removed prior to final integration + boolean DEBUG = (System.getProperty("javac.debug.modules") != null); + void DEBUG(String s) { + if (DEBUG) + System.err.println(s); + } + + JigsawLibraryLocation(Library library, ModuleId mid) { + library.getClass(); // null check + this.library = library; + mid.getClass(); // null check + this.mid = mid; + } + + @Override + public String getName() { + return mid.toString(); + } + + @Override + public boolean isOutputLocation() { + // only input locations supported + return false; + } + + @Override + public Iterable<JavaFileObject> list(String packageName, Set<Kind> kinds, boolean recurse) + throws IOException { + // only Kind.CLASS supported + if (!kinds.contains(Kind.CLASS)) + return Collections.emptySet(); + ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>(); + packageName = normalize(packageName); + String subpackagePrefix = packageName + "."; + for (Library l = library; l != null; l = l.parent()) { + List<String> classes = l.listLocalClasses(mid, true); + if (classes != null) { + for (String cn: classes) { + //DEBUG("LIST raw " + cn); + cn = normalize(cn); + String pn = packagePart(cn); + if (pn.equals(packageName) || (recurse && pn.startsWith(subpackagePrefix))) { + results.add(new LibraryFileObject(library, mid, cn)); + } + } + } + } + DEBUG("JigsawLibraryLocation:" + library + ":" + mid + ": list " + packageName + "," + kinds + "--" + (results.size() < 5 ? results : (results.size() + " classes"))); + return results; + } + + public String inferBinaryName(JavaFileObject file) { + if (file instanceof LibraryFileObject) + return ((LibraryFileObject) file).className; + else + return null; + } + + @Override + public String toString() { + return ("JigsawLibrary[" + library + "," + mid + "]"); + } + + private static String normalize(String name) { + return name.replace('/', '.'); + } + + private static String packagePart(String className) { + int sep = className.lastIndexOf('.'); + return (sep == -1) ? "" : className.substring(0, sep); + } + + private static String simpleNamePart(String className) { + int sep = className.lastIndexOf('.'); + return (sep == -1) ? className : className.substring(sep + 1); + } + + class LibraryFileObject implements JavaFileObject, FileObject.Locatable { + Library library; + ModuleId mid; + String className; + + private LibraryFileObject(Library library, ModuleId mid, String className) { + this.library = library; + this.mid = mid; + this.className = className; + } + + public Kind getKind() { + return Kind.CLASS; + } + + public boolean isNameCompatible(String simpleName, Kind kind) { + return (kind == Kind.CLASS) && simpleName.equals(simpleNamePart(className)); + } + + public NestingKind getNestingKind() { + return null; + } + + public Modifier getAccessLevel() { + return null; + } + + public URI toUri() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getName() { + return library.name() + ":" + mid.toString() + ":" + className; + } + + public InputStream openInputStream() throws IOException { + byte[] data; + if (className.endsWith(".module-info")) // FIXME? + data = library.readModuleInfoBytes(mid); + else + data = library.readClass(mid, className); + return new ByteArrayInputStream(data); + } + + public OutputStream openOutputStream() throws IOException { + throw new UnsupportedOperationException(); + } + + public Reader openReader(boolean ignoreEncodingErrors) throws IOException { + throw new UnsupportedOperationException(); + } + + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + throw new UnsupportedOperationException(); + } + + public Writer openWriter() throws IOException { + throw new UnsupportedOperationException(); + } + + public long getLastModified() { + return 0; + } + + public boolean delete() { + throw new UnsupportedOperationException(); + } + + @Override + public String toString() { + return getName(); + } + + @Override + public Location getLocation() { + return JigsawLibraryLocation.this; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof LibraryFileObject)) + return false; + LibraryFileObject o = (LibraryFileObject) other; + return (library == o.library) + && mid.equals(o.mid) + && className.equals(o.className); + + } + + @Override + public int hashCode() { + return library.hashCode() + mid.hashCode() + className.hashCode(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/javac/jigsaw/JigsawModuleResolver.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.jigsaw; + +import java.io.File; +import java.io.IOException; +import java.lang.module.ModuleIdQuery; +import java.lang.module.ModuleInfo; +import java.lang.module.ModuleView; +import java.lang.module.ServiceDependence; +import java.lang.module.Version; +import java.lang.module.VersionQuery; +import java.lang.module.ViewDependence; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import org.openjdk.jigsaw.Configuration; +import org.openjdk.jigsaw.ConfigurationException; +import org.openjdk.jigsaw.Configurator; +import org.openjdk.jigsaw.JigsawModuleSystem; +import org.openjdk.jigsaw.PathContext; + +import com.sun.tools.javac.code.Directive; +import com.sun.tools.javac.code.ModuleId; +import com.sun.tools.javac.code.ModuleQuery; +import com.sun.tools.javac.code.Symbol.ClassSymbol; +import com.sun.tools.javac.code.Symbol.ModuleSymbol; +import com.sun.tools.javac.code.Symbol.PackageSymbol; +import com.sun.tools.javac.code.Symtab; +import com.sun.tools.javac.comp.Modules.ModuleResolver; +import com.sun.tools.javac.jvm.ClassReader; +import com.sun.tools.javac.main.Option; +import com.sun.tools.javac.util.Assert; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Debug; +import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Log; +import com.sun.tools.javac.util.Name; +import com.sun.tools.javac.util.Names; +import com.sun.tools.javac.util.Options; + +/** + * Jigsaw implementation of javac's simple abstraction of a module resolver. + */ +public class JigsawModuleResolver implements ModuleResolver { + JigsawModuleSystem jigsaw; + JavacCatalog catalog; + Configuration<PathContext> config; + ClassReader reader; + Names names; + Symtab syms; + Debug debug; + Log log; + + Map<String, ModuleView> views; + + public JigsawModuleResolver(Context context) throws IOException/*FIXME*/ { + jigsaw = JigsawModuleSystem.instance(); + + names = Names.instance(context); + syms = Symtab.instance(context); + reader = ClassReader.instance(context); + + Options options = Options.instance(context); + String l = options.get(Option.L); + File library = (l == null ? null : new File(l)); + + catalog = new JavacCatalog(library); + + log = Log.instance(context); + debug = new Debug("jigsaw", options, log); + } + + public Iterable<? extends ModuleSymbol> resolve( + Iterable<? extends ModuleSymbol> roots, + Iterable<? extends ModuleSymbol> modules) { + if (debug.isEnabled()) + debug.println("JigsawModuleResolver starting"); + + catalog.init(modules); + Collection<ModuleIdQuery> jigsawRootQueries = new LinkedHashSet<ModuleIdQuery>(); + for (ModuleSymbol r: roots) { + // should use catalog here + CharSequence rn = r.getModuleId().getName(); + if (rn.length() == 0) { + // unnamed module +//////////// // assert r.getRequires() == default platform module +//////////// q = getDefaultPlatformModule(); + for (Directive.RequiresModuleDirective d: r.getRequiredModules()) { + // assert mr.getFlags().isEmpty() + jigsawRootQueries.add(getModuleIdQuery(d.moduleQuery)); // FIXME: handle IllegalArgumentException + } + } else { + jigsawRootQueries.add(getModuleIdQuery(r.getModuleId())); // FIXME: handle IllegalArgumentException + } + } + + try { + config = Configurator.configurePaths(catalog, jigsawRootQueries); + } catch (IOException e) { + log.error("jigsaw.resolver.ioerror", e); + return null; + } catch (ConfigurationException e) { + log.error("jigsaw.resolver.error", e.getLocalizedMessage()); + return null; + } + + // have config.roots: set of root module ids + // have config.contexts: set of preconfigured PathContexts + // need to flatten the contexts graphs, using tarjan + // then build List<ModuleSymbol> for return. + // some ModuleSymbol will come from the input list + // other ModuleSymbol will have to come from library: create these + // symbols as uncompleted ModuleSymbols, with completer set to ClassReader + // Will need new LibraryLocation interface in ModuleFileManager + // for use by modules in library. Means that FileManager.join + // has to be able to cope. + ListBuffer<PathContext> rootContexts = new ListBuffer<PathContext>(); + for (java.lang.module.ModuleId mid: config.roots()) { + PathContext pcx = config.getContextForModuleName(mid.name()); + rootContexts.add(pcx); + } + + Tarjan<PathContext> t = new Tarjan<PathContext>(rootContexts) { + @Override + protected Iterable<? extends PathContext> getDependencies(PathContext pcx) { + return pcx.remoteContexts(); + } + }; + + ListBuffer<ModuleSymbol> results = new ListBuffer<ModuleSymbol>(); + views = new HashMap<String, ModuleView>(); + // add the unnamed module back into the results because it was skipped as + // an input for the jigsaw module resolver -- yet its location field + // is important -- it contains sourcepath, classpath, etc + for (ModuleSymbol r: roots) { + if (r.getModuleId().getName().length() == 0) // unnamed module + results.add(r); + } + for (PathContext pcx: t.list()) { + for (ModuleInfo minfo: pcx.moduleInfos()) { + java.lang.module.ModuleId mid = minfo.id(); + ModuleSymbol sym = catalog.getModuleSymbol(mid); + if (sym == null) { + Name name = names.fromString(mid.name()); + sym = new ModuleSymbol(name, syms.rootModule); + sym.version = names.fromString(mid.version().toString()); + sym.location = new JigsawLibraryLocation(catalog.library, mid); + sym.directives = getDirectives(minfo); // synthesize java.base? + } + results.add(sym); + for (ModuleView v: minfo.views()) + views.put(v.id().name(), v); + } + } + + if (debug.isEnabled()) + debug.println("JigsawModuleResolver finished; results: (" + results.size() + ")"); + + return results; + } + + private List<Directive> getDirectives(ModuleInfo minfo) { + ListBuffer<Directive> lb = new ListBuffer<Directive>(); + for (ViewDependence vd: minfo.requiresModules()) { + Set<Directive.RequiresFlag> flags = Collections.emptySet(); // FIXME + lb.add(new Directive.RequiresModuleDirective(getModuleQuery(vd.query()), flags)); + } + for (ServiceDependence sd: minfo.requiresServices()) { + ClassSymbol sym = reader.enterClass(names.fromString(sd.service())); + Set<Directive.RequiresFlag> flags = Collections.emptySet(); // FIXME + lb.add(new Directive.RequiresServiceDirective(sym, flags)); + } + addViewDirectives(lb, minfo.defaultView()); + for (ModuleView mview: minfo.views()) { + if (mview == minfo.defaultView()) + continue; + ListBuffer<Directive> vl = new ListBuffer<Directive>(); + addViewDirectives(vl, mview); + Name vn = names.fromString(mview.id().name()); + lb.add(new Directive.ViewDeclaration(vn, vl.toList())); + } + return lb.toList(); + } + + private ModuleQuery getModuleQuery(ModuleIdQuery mq) { + String n = mq.name(); + VersionQuery vq = mq.versionQuery(); + return new ModuleQuery(names.fromString(n), + (vq == null) ? null : names.fromString(vq.toString())); + } + + private ModuleId getModuleId(java.lang.module.ModuleId mid) { + String n = mid.name(); + Version v = mid.version(); + return new ModuleId(names.fromString(n), + (v == null) ? null : names.fromString(v.toString())); + + } + + private void addViewDirectives(ListBuffer<Directive> list, ModuleView mview) { + // In ModuleProvides attribute order, for benefit of javax.lang.model + // entry + String main = mview.mainClass(); + if (main != null) { + ClassSymbol sym = reader.enterClass(names.fromString(main)); + list.add(new Directive.EntrypointDirective(sym)); + } + // aliases + for (java.lang.module.ModuleId a: mview.aliases()) { + list.add(new Directive.ProvidesModuleDirective(getModuleId(a))); + } + // services + for (Map.Entry<String,Set<String>> e: mview.services().entrySet()) { + ClassSymbol srvc = reader.enterClass(names.fromString(e.getKey())); + for (String i: e.getValue()) { + ClassSymbol impl = reader.enterClass(names.fromString(i)); + list.add(new Directive.ProvidesServiceDirective(srvc, impl)); + } + } + // exports + for (String e: mview.exports()) { + PackageSymbol pkg = reader.enterPackage(names.fromString(e)); + list.add(new Directive.ExportsDirective(pkg)); + } + // permits + for (String p: mview.permits()) { + list.add(new Directive.PermitsDirective(names.fromString(p))); + } + } + + @Override + public boolean isPackageVisible(ModuleSymbol msym, PackageSymbol psym) { + Set<PackageSymbol> set = visiblePackages.get(msym); + if (set == null) { + set = new HashSet<PackageSymbol>(); + for (Directive.RequiresModuleDirective d: msym.getRequiredModules()) { + addExportsForView(set, d.moduleQuery.name.toString()); + } + visiblePackages.put(msym, set); + } + return set.contains(psym); + } + + private void addExportsForView(Set<PackageSymbol> exports, String name) { + ModuleView v = views.get(name); + Assert.checkNonNull(v); + for (String e: v.exports()) + exports.add(reader.enterPackage(names.fromString(e))); + for (ViewDependence vd: v.moduleInfo().requiresModules()) { + if (vd.modifiers().contains(ViewDependence.Modifier.PUBLIC)) { + addExportsForView(exports, vd.query().name()); + } + } + } + + Map<ModuleSymbol, Set<PackageSymbol>> visiblePackages = + new HashMap<ModuleSymbol, Set<PackageSymbol>>(); + + private ModuleIdQuery getModuleIdQuery(ModuleId mid) { + return getModuleIdQuery(mid.getName(), mid.getVersion()); + } + + private ModuleIdQuery getModuleIdQuery(ModuleQuery midq) { + return getModuleIdQuery(midq.getName(), midq.getVersionQuery()); + } + + private ModuleIdQuery getModuleIdQuery(CharSequence n, CharSequence vq) { + String q = (vq == null || vq.length() == 0) ? String.valueOf(n) : (n + "@" + vq); + return jigsaw.parseModuleIdQuery(q); + } + + + static abstract class Tarjan<T> { + protected Tarjan(Iterable<T> roots) { + this.roots = roots; + } + + /** + * Given a set of roots defining a directed graph, return an ordered + * list of all the nodes in the graph, such that if node A depends on + * node B, and there is no cycle between A and B, then A appears before + * B in the list. + * @return + */ + public Iterable<? extends T> list() { + List<Node> rootNodes = getNodes(roots); + for (Node node: rootNodes) { + if (node.index == -1) + tarjan(node); + } + LinkedHashSet<T> results = new LinkedHashSet<T>(); + for (Node node: rootNodes) { + if (!results.contains(node.t)) + list(node.scc, results); + } + return Collections.unmodifiableSet(results); + } + + /** + * Get the set of graph nodes on which this node depends. + * @param t + * @return + */ + protected abstract Iterable<? extends T> getDependencies(T t); + + protected String toString(T t) { + return t.toString(); + } + + private void list(SCC scc, LinkedHashSet<T> results) { + for (Node n: scc.nodes) + results.add(n.t); + for (SCC child: scc.getChildren()) + list(child, results); + } + + private List<Node> getNodes(Iterable<? extends T> elems) { + ListBuffer<Node> lb = new ListBuffer<Node>(); + for (T elem: elems) { + lb.add(getNode(elem)); + } + return lb.toList(); + } + + private Node getNode(T sym) { + Node node = nodeMap.get(sym); + if (node == null) + nodeMap.put(sym, (node = new Node(sym))); + return node; + } + // where + private Map<T, Node> nodeMap= new HashMap<T, Node>(); + + + // Tarjan's algorithm to determine strongly connected components of a + // directed graph in linear time. + + void tarjan(Node v) { + v.index = index; + v.lowlink = index; + index++; + stack.add(0, v); + v.active = true; + for (Node n: v.getDependencies()) { + if (n.index == -1) { + tarjan(n); + v.lowlink = Math.min(v.lowlink, n.lowlink); + } else if (stack.contains(n)) { + v.lowlink = Math.min(v.lowlink, n.index); + } + } + if (v.lowlink == v.index) { + Node n; + SCC scc = new SCC(); + do { + n = stack.remove(0); + n.active = false; + scc.add(n); + } while (n != v); + } + } + + private final Iterable<T> roots; + private int index = 0; + private ArrayList<Node> stack = new ArrayList<Node>(); + + private class Node implements Comparable<Node> { + final T t; + SCC scc; + int index = -1; + int lowlink; + boolean active; + + Node(T t) { + this.t = t; + } + + Iterable<Node> getDependencies() { + ListBuffer<Node> nodes = new ListBuffer<Node>(); + for (T dep: Tarjan.this.getDependencies(this.t)) + nodes.add(getNode(dep)); + return nodes.toList(); + } + + @Override + public String toString() { + return Tarjan.this.toString(t) + "(index:" + index +",low:" + lowlink + ",active:" + active + ")" ; + } + + public int compareTo(Node o) { + return (index < o.index) ? -1 : (index == o.index) ? 0 : 1; + } + } + + private class SCC { + void add(Node node) { + nodes.add(node); + node.scc = this; + } + + Set<SCC> getChildren() { + if (children == null) { + children = new LinkedHashSet<SCC>(); + for (Node node: nodes) { + for (Node n: node.getDependencies()) { + n.scc.getClass(); // nullcheck + if (n.scc != this) + children.add(n.scc); + } + } + } + return children; + } + + @Override + public String toString() { + return nodes.toString(); + } + + private SortedSet<Node> nodes = new TreeSet<Node>(); + private Set<SCC> children; + } + } + +}
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassFile.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassFile.java Tue May 07 17:14:17 2013 -0700 @@ -85,6 +85,8 @@ public final static int CONSTANT_MethodHandle = 15; public final static int CONSTANT_MethodType = 16; public final static int CONSTANT_InvokeDynamic = 18; + public final static int CONSTANT_ModuleId = 19; + public final static int CONSTANT_ModuleQuery = 20; public final static int REF_getField = 1; public final static int REF_getStatic = 2; @@ -106,8 +108,9 @@ V45_3(45, 3), // base level for all attributes V49(49, 0), // JDK 1.5: enum, generics, annotations V50(50, 0), // JDK 1.6: stackmaps - V51(51, 0), // JDK 1.7 - V52(52, 0); // JDK 1.8: lambda, type annos, param names + V51(51, 0), // JDK 1.7: invokedynamic + V52(52, 0), // JDK 1.8: lambda, type annos, param names + V53(52, 0); // JDK 1.9: Jigsaw !!! FIXME -- the 52 is deliberate but temporary and should be corrected eventually Version(int major, int minor) { this.major = major; this.minor = minor;
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Tue May 07 17:14:17 2013 -0700 @@ -29,37 +29,53 @@ import java.net.URI; import java.net.URISyntaxException; import java.nio.CharBuffer; -import java.util.Arrays; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; + import javax.lang.model.SourceVersion; -import javax.tools.JavaFileObject; import javax.tools.JavaFileManager; import javax.tools.JavaFileManager.Location; +import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import static javax.tools.StandardLocation.*; -import com.sun.tools.javac.comp.Annotate; import com.sun.tools.javac.code.*; +import com.sun.tools.javac.code.Directive.EntrypointDirective; +import com.sun.tools.javac.code.Directive.ExportsDirective; +import com.sun.tools.javac.code.Directive.PermitsDirective; +import com.sun.tools.javac.code.Directive.ProvidesModuleDirective; +import com.sun.tools.javac.code.Directive.ProvidesServiceDirective; +import com.sun.tools.javac.code.Directive.RequiresFlag; +import com.sun.tools.javac.code.Directive.RequiresModuleDirective; +import com.sun.tools.javac.code.Directive.RequiresServiceDirective; +import com.sun.tools.javac.code.Directive.ViewDeclaration; import com.sun.tools.javac.code.Lint.LintCategory; -import com.sun.tools.javac.code.Type.*; -import com.sun.tools.javac.code.Symbol.*; -import com.sun.tools.javac.code.Symtab; +import com.sun.tools.javac.code.Symbol.ClassSymbol; +import com.sun.tools.javac.code.Symbol.Completer; +import com.sun.tools.javac.code.Symbol.CompletionFailure; +import com.sun.tools.javac.code.Symbol.MethodSymbol; +import com.sun.tools.javac.code.Symbol.ModuleSymbol; +import com.sun.tools.javac.code.Symbol.PackageSymbol; +import com.sun.tools.javac.code.Symbol.TypeSymbol; +import com.sun.tools.javac.code.Symbol.VarSymbol; +import com.sun.tools.javac.code.Type.ArrayType; +import com.sun.tools.javac.code.Type.ClassType; +import com.sun.tools.javac.code.Type.ForAll; +import com.sun.tools.javac.code.Type.MethodType; +import com.sun.tools.javac.code.Type.TypeVar; +import com.sun.tools.javac.code.Type.WildcardType; +import com.sun.tools.javac.comp.Annotate; import com.sun.tools.javac.file.BaseFileObject; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; +import com.sun.tools.javac.util.List; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.TypeTag.CLASS; import static com.sun.tools.javac.jvm.ClassFile.*; import static com.sun.tools.javac.jvm.ClassFile.Version.*; - -import static com.sun.tools.javac.main.Option.*; +import static com.sun.tools.javac.main.Option.VERBOSE; /** This class provides operations to read a classfile into an internal * representation. The internal representation is anchored in a @@ -119,6 +135,10 @@ */ boolean allowDefaultMethods; + /** Switch: allow modules + */ + boolean allowModules; + /** Switch: preserve parameter names from the variable table. */ public boolean saveParameterNames; @@ -178,6 +198,11 @@ */ private Map<Name, PackageSymbol> packages; + /** A hashtable giving the module for each module location. + * + */ + private Map<Location, ModuleSymbol> allModules; + /** The current scope where type variables are entered. */ protected Scope typevars; @@ -258,9 +283,11 @@ packages = syms.packages; Assert.check(classes == null || classes == syms.classes); classes = syms.classes; + allModules = syms.allModules; } else { packages = new HashMap<Name, PackageSymbol>(); classes = new HashMap<Name, ClassSymbol>(); + allModules = new HashMap<Location, ModuleSymbol>(); } packages.put(names.empty, syms.rootPackage); @@ -295,6 +322,7 @@ allowVarargs = source.allowVarargs(); allowAnnotations = source.allowAnnotations(); allowSimplifiedVarargs = source.allowSimplifiedVarargs(); + allowModules = source.allowModules(); allowDefaultMethods = source.allowDefaultMethods(); saveParameterNames = options.isSet("save-parameter-names"); @@ -324,6 +352,7 @@ c.members_field.enter(sym); } + // <editor-fold defaultstate="collapsed" desc="Error diagnoses"> /************************************************************************ * Error Diagnoses ***********************************************************************/ @@ -349,7 +378,9 @@ currentClassFile, diagFactory.fragment(key, args)); } - + // </editor-fold> + + // <editor-fold defaultstate="collapsed" desc="Buffer access"> /************************************************************************ * Buffer Access ***********************************************************************/ @@ -429,6 +460,9 @@ throw new AssertionError(e); } } + // </editor-fold> + + // <editor-fold defaultstate="collapsed" desc="Constant Pool Access"> /************************************************************************ * Constant Pool Access @@ -465,6 +499,8 @@ case CONSTANT_Integer: case CONSTANT_Float: case CONSTANT_InvokeDynamic: + case CONSTANT_ModuleId: + case CONSTANT_ModuleQuery: bp = bp + 4; break; case CONSTANT_Long: @@ -542,6 +578,16 @@ case CONSTANT_InvokeDynamic: skipBytes(5); break; + case CONSTANT_ModuleId: + poolObj[i] = new ModuleId( + readInternalName(getChar(index + 1)), + readName(getChar(index + 3))); + break; + case CONSTANT_ModuleQuery: + poolObj[i] = new ModuleQuery( + readInternalName(getChar(index + 1)), + readName(getChar(index + 3))); + break; default: throw badClassFile("bad.const.pool.tag", Byte.toString(tag)); } @@ -590,6 +636,49 @@ return (Name) (readPool(i)); } + /** Read module id. + */ + ModuleId readModuleId(int i) { + return (ModuleId) (readPool(i)); + } + + /** Read module id query. + */ + ModuleQuery readModuleQuery(int i) { + return (ModuleQuery) (readPool(i)); + } + + /** Read requires_flags. + */ + Set<RequiresFlag> readRequiresFlags(int flags) { + Set<RequiresFlag> set = EnumSet.noneOf(RequiresFlag.class); + for (RequiresFlag f: RequiresFlag.values()) { + if ((flags & f.value) != 0) + set.add(f); + } + return set; + } + + Name readInternalName(int i) { + int index = poolIdx[i]; + return names.fromUtf(internalize(buf, index + 3, getChar(index + 1))); + } + + /** Read module name. + * The module name is in a CONSTANT_Class_info, but we don't want to + * enter a class for it, so can't use readClassSymbol. + */ + Name readModuleInfoName(int i) { + int index = poolIdx[i]; + assert index != 0; + byte tag = buf[index]; + assert tag == CONSTANT_Class; + return readInternalName(getChar(index+1)); + } + // </editor-fold> + + // <editor-fold defaultstate="collapsed" desc="Reading Types"> + /************************************************************************ * Reading Types ***********************************************************************/ @@ -905,6 +994,9 @@ throw badClassFile("undecl.type.var", name); } } + // </editor-fold> + + // <editor-fold defaultstate="collapsed" desc="Reading Attributes"> /************************************************************************ * Reading Attributes @@ -1183,6 +1275,8 @@ } }, + // v52 module attributes + new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { protected void read(Symbol sym, int attrLen) { attachTypeAnnotations(sym); @@ -1195,6 +1289,105 @@ } }, + new AttributeReader(names.Module, V52, CLASS_ATTRIBUTE) { + @Override + protected boolean accepts(AttributeKind kind) { + return super.accepts(kind) && allowModules; + } + protected void read(Symbol sym, int attrLen) { + if (sym.kind == TYP && sym.owner.kind == MDL) { + ModuleSymbol msym = (ModuleSymbol) sym.owner; + ModuleId mid = readModuleId(nextChar()); + msym.name = msym.fullname = mid.name; + msym.version = mid.version; + } + } + }, + + new AttributeReader(names.ModuleProvides, V52, CLASS_ATTRIBUTE) { + @Override + protected boolean accepts(AttributeKind kind) { + return super.accepts(kind) && allowModules; + } + protected void read(Symbol sym, int attrLen) { + if (sym.kind == TYP && sym.owner.kind == MDL) { + ModuleSymbol msym = (ModuleSymbol) sym.owner; + int numViews = nextChar(); + for (int v = 0; v < numViews; v++) { + Name viewName = readName(nextChar()); + List<Directive> directives = + (viewName == null) ? msym.directives : List.<Directive>nil(); + + ClassSymbol entrypoint = readClassSymbol(nextChar()); + if (entrypoint != null) { + EntrypointDirective d = new EntrypointDirective(entrypoint); + directives = directives.prepend(d); + } + + int numAliases = nextChar(); + for (int i = 0; i < numAliases; i++) { + ModuleId id = readModuleId(nextChar()); + ProvidesModuleDirective d = new ProvidesModuleDirective(id); + directives = directives.prepend(d); + } + + int numServices = nextChar(); + for (int i = 0; i < numServices; i++) { + ClassSymbol svcSym = readClassSymbol(nextChar()); + ClassSymbol implSym = readClassSymbol(nextChar()); + ProvidesServiceDirective d = new ProvidesServiceDirective(svcSym, implSym); + directives = directives.prepend(d); + } + + int numExports = nextChar(); + for (int i = 0; i < numExports; i++) { + Name export = readName(nextChar()); + PackageSymbol psym = enterPackage(export); + ExportsDirective d = new ExportsDirective(psym); + directives = directives.prepend(d); + } + + int numPermits = nextChar(); + for (int i = 0; i < numPermits; i++) { + ModuleId id = readModuleId(nextChar()); + PermitsDirective d = new PermitsDirective(id); + directives = directives.prepend(d); + } + + if (viewName != null) { + ViewDeclaration d = new ViewDeclaration(viewName, directives.reverse()); + msym.directives = msym.directives.prepend(d); + } + } + } + } + }, + + new AttributeReader(names.ModuleRequires, V52, CLASS_ATTRIBUTE) { + @Override + protected boolean accepts(AttributeKind kind) { + return super.accepts(kind) && allowModules; + } + protected void read(Symbol sym, int attrLen) { + if (sym.kind == TYP && sym.owner.kind == MDL) { + ModuleSymbol msym = (ModuleSymbol) sym.owner; + int numModules = nextChar(); + for (int r = 0; r < numModules; r++) { + ModuleQuery q = readModuleQuery(nextChar()); + Set<RequiresFlag> flags = readRequiresFlags(nextInt()); + RequiresModuleDirective d = new RequiresModuleDirective(q, flags); + msym.directives = msym.directives.prepend(d); + } + int numServices = nextChar(); + for (int r = 0; r < numServices; r++) { + ClassSymbol csym = readClassSymbol(nextChar()); + Set<RequiresFlag> flags = readRequiresFlags(nextInt()); + RequiresServiceDirective d = new RequiresServiceDirective(csym, flags); + msym.directives = msym.directives.prepend(d); + } + } + } + }, // The following attributes for a Code attribute are not currently handled // StackMapTable @@ -1214,8 +1407,6 @@ printCCF("ccf.unrecognized.attribute", attrName); } - - protected void readEnclosingMethodAttr(Symbol sym) { // sym is a nested class with an "Enclosing Method" attribute // remove sym from it's current owners scope and place it in @@ -1365,6 +1556,9 @@ readMemberAttrs(owner); return null; } + // </editor-fold> + + // <editor-fold defaultstate="collapsed" desc="Reading Java-language annotations"> /************************************************************************ * Reading Java-language annotations @@ -1908,6 +2102,7 @@ } } } + // </editor-fold> class TypeAnnotationCompleter extends AnnotationCompleter { @@ -1942,6 +2137,7 @@ } } + // <editor-fold defaultstate="collapsed" desc="Reading Symbols"> /************************************************************************ * Reading Symbols @@ -2157,11 +2353,20 @@ long flags = adjustClassFlags(nextChar()); if (c.owner.kind == PCK) c.flags_field = flags; - // read own class name and check that it matches - ClassSymbol self = readClassSymbol(nextChar()); - if (c != self) - throw badClassFile("class.file.wrong.class", - self.flatname); + if (c.owner.kind == MDL) { + //System.err.println("ClassReader.readClass getModuleInfoName"); + c.fullname = c.flatname = readModuleInfoName(nextChar()); + c.name = Convert.shortName(c.fullname); + assert c.name == names.module_info; + } else { + // read own class name and check that it matches + ClassSymbol self = readClassSymbol(nextChar()); + if (c != self) { + //System.err.println("ClassReader.readClass c=" + c + " self=" + self); + throw badClassFile("class.file.wrong.class", + self.flatname); + } + } // class attributes must be read before class // skip ahead to read class attributes @@ -2273,6 +2478,9 @@ } readClass(c); } + // </editor-fold> + + // <editor-fold defaultstate="collapsed" desc="Adjusting flags"> /************************************************************************ * Adjusting flags @@ -2297,6 +2505,9 @@ long adjustClassFlags(long flags) { return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded } + // </editor-fold> + + // <editor-fold defaultstate="collapsed" desc="Loading Classes"> /************************************************************************ * Loading Classes @@ -2398,6 +2609,15 @@ } catch (IOException ex) { throw new CompletionFailure(sym, ex.getLocalizedMessage()).initCause(ex); } + } else if (sym.kind == MDL) { + //System.err.println("ClassReader.complete module " + sym + " " + sym.name); + ModuleSymbol msym = (ModuleSymbol) sym; + msym.module_info.members_field = new Scope(sym); // or Scope.empty? + msym.directives = List.nil(); + fillIn(msym.module_info); + msym.directives = msym.directives.reverse(); + assert msym.name != null; + //System.err.println("ClassReader.completed module " + sym + " " + sym.name); } if (!filling && !suppressFlush) annotate.flush(); // finish attaching annotations @@ -2481,6 +2701,15 @@ foundTypeVariables = List.nil(); filling = false; } + + if (allowModules) { + if (!(classfile instanceof JavaFileObject.Locatable)) + throw new CompletionFailure(c, "cannot determine module"); + Location l = ((JavaFileObject.Locatable) classfile).getLocation(); + c.modle = enterModule(l); + } else { + c.modle = syms.noModule; + } } else { if (sourceCompleter != null) { sourceCompleter.complete(c); @@ -2489,6 +2718,7 @@ + classfile.toUri()); } } + Assert.checkNonNull(c.modle); return; } catch (IOException ex) { throw badClassFile("unable.to.access.file", ex.getMessage()); @@ -2579,6 +2809,9 @@ } return c; } + // </editor-fold> + + // <editor-fold defaultstate="collapsed" desc="Loading Packages"> /************************************************************************ * Loading Packages @@ -2616,7 +2849,9 @@ * (2) we have one of the other kind, and the given class file * is older. */ - protected void includeClassFile(PackageSymbol p, JavaFileObject file) { + protected void includeClassFile(PackageSymbol p, JavaFileObject file, Name simpleName) { + boolean isPackageInfo = simpleName == names.package_info; + if ((p.flags_field & EXISTS) == 0) for (Symbol q = p; q != null && q.kind == PCK; q = q.owner) q.flags_field |= EXISTS; @@ -2626,18 +2861,14 @@ seen = CLASS_SEEN; else seen = SOURCE_SEEN; - String binaryName = fileManager.inferBinaryName(currentLoc, file); - int lastDot = binaryName.lastIndexOf("."); - Name classname = names.fromString(binaryName.substring(lastDot + 1)); - boolean isPkgInfo = classname == names.package_info; - ClassSymbol c = isPkgInfo - ? p.package_info - : (ClassSymbol) p.members_field.lookup(classname).sym; + ClassSymbol c = + isPackageInfo ? p.package_info + : (ClassSymbol) p.members_field.lookup(simpleName).sym; if (c == null) { - c = enterClass(classname, p); + c = enterClass(simpleName, p); if (c.classfile == null) // only update the file if's it's newly created c.classfile = file; - if (isPkgInfo) { + if (isPackageInfo) { p.package_info = c; } else { if (c.owner == p) // it might be an inner class @@ -2658,7 +2889,7 @@ * file or a class file when both are present. May be overridden * by subclasses. */ - protected JavaFileObject preferredFileObject(JavaFileObject a, + public JavaFileObject preferredFileObject(JavaFileObject a, JavaFileObject b) { if (preferSource) @@ -2685,17 +2916,29 @@ protected void extraFileActions(PackageSymbol pack, JavaFileObject fe) { } - protected Location currentLoc; // FIXME - + public void setPathLocation(Location pathLocation) { + this.pathLocation = pathLocation; + } + + private Location pathLocation; private boolean verbosePath = true; + /** Load directory of package into members scope. */ private void fillIn(PackageSymbol p) throws IOException { if (p.members_field == null) p.members_field = new Scope(p); String packageName = p.fullname.toString(); - Set<JavaFileObject.Kind> kinds = getPackageFileKinds(); + //System.err.println("ClassReader.fillIn using pathLocation " + (pathLocation != null)); + if (pathLocation != null) { + fillIn(p, pathLocation, + fileManager.list(pathLocation, + packageName, + EnumSet.allOf(JavaFileObject.Kind.class), + false)); + return; + } fillIn(p, PLATFORM_CLASS_PATH, fileManager.list(PLATFORM_CLASS_PATH, @@ -2703,6 +2946,8 @@ EnumSet.of(JavaFileObject.Kind.CLASS), false)); + Set<JavaFileObject.Kind> kinds = getPackageFileKinds(); + Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds); classKinds.remove(JavaFileObject.Kind.SOURCE); boolean wantClassFiles = !classKinds.isEmpty(); @@ -2769,17 +3014,16 @@ Location location, Iterable<JavaFileObject> files) { - currentLoc = location; for (JavaFileObject fo : files) { switch (fo.getKind()) { case CLASS: case SOURCE: { - // TODO pass binaryName to includeClassFile - String binaryName = fileManager.inferBinaryName(currentLoc, fo); + String binaryName = fileManager.inferBinaryName(location, fo); String simpleName = binaryName.substring(binaryName.lastIndexOf(".") + 1); if (SourceVersion.isIdentifier(simpleName) || - simpleName.equals("package-info")) - includeClassFile(p, fo); + simpleName.contentEquals(names.package_info)) { + includeClassFile(p, fo, names.fromString(simpleName)); + } break; } default: @@ -2787,6 +3031,64 @@ } } } + // </editor-fold> + + // <editor-fold defaultstate="collapsed" desc="Loading Modules"> + +/************************************************************************ + * Loading Modules + ***********************************************************************/ + + public ModuleSymbol enterModule(Location locn) { + ModuleSymbol sym = allModules.get(locn); + if (sym == null) { + sym = new ModuleSymbol(null, syms.rootModule); + sym.location = locn; + sym.module_info = new ClassSymbol(0, names.module_info, sym); + sym.module_info.modle = sym; + sym.completer = new Symbol.Completer() { + public void complete(Symbol sym) throws CompletionFailure { + readModule((ModuleSymbol) sym); + } + + void readModule(ModuleSymbol sym) { + Location locn = sym.location; + JavaFileObject srcFile = getModuleInfo(locn, JavaFileObject.Kind.SOURCE); + JavaFileObject classFile = getModuleInfo(locn, JavaFileObject.Kind.CLASS); + JavaFileObject file; + if (srcFile == null) { + if (classFile == null) { + sym.name = sym.fullname = names.empty; // unnamed module + RequiresModuleDirective d = new RequiresModuleDirective(syms.jdkLegacyQuery, + EnumSet.of(Directive.RequiresFlag.SYNTHESIZED)); + sym.directives = List.<Directive>of(d); + return; + } + file = classFile; + } else if (classFile == null) + file = srcFile; + else + file = preferredFileObject(srcFile, classFile); + + sym.module_info.classfile = file; + ClassReader.this.complete(sym); + assert sym.name != null; + } + + JavaFileObject getModuleInfo(Location locn, JavaFileObject.Kind kind) { + try { + return fileManager.getJavaFileForInput(locn, "module-info", kind); + } catch (IOException e) { + return null; + } + } + }; + allModules.put(locn, sym); + } + return sym; + } + + // </editor-fold> /** Output for "-checkclassfile" option. * @param key The key to look up the correct internationalized string. @@ -2802,6 +3104,8 @@ throws CompletionFailure; } + // <editor-fold defaultstate="collapsed" desc="SourceFileObject"> + /** * A subclass of JavaFileObject for the sourcefile attribute found in a classfile. * The attribute is only the last component of the original filename, so is unlikely @@ -2816,7 +3120,7 @@ private Name flatname; public SourceFileObject(Name name, Name flatname) { - super(null); // no file manager; never referenced for this file object + super(null, null); // no file manager or location; never referenced for this file object this.name = name; this.flatname = flatname; } @@ -2886,6 +3190,11 @@ } @Override + protected String inferModuleTag(String binaryName) { + return null; + } + + @Override public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) { return true; // fail-safe mode } @@ -2913,4 +3222,5 @@ return name.hashCode(); } } + // </editor-fold> }
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Tue May 07 17:14:17 2013 -0700 @@ -31,14 +31,16 @@ import java.util.Set; import java.util.HashSet; -import javax.lang.model.type.TypeKind; +import javax.tools.FileObject; import javax.tools.JavaFileManager; -import javax.tools.FileObject; +import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileObject; +import javax.tools.ModuleFileManager; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Attribute.RetentionPolicy; import com.sun.tools.javac.code.Attribute.TypeCompound; +import com.sun.tools.javac.code.Directive.*; import static com.sun.tools.javac.code.BoundKind.EXTENDS; import static com.sun.tools.javac.code.BoundKind.SUPER; import static com.sun.tools.javac.code.BoundKind.UNBOUND; @@ -475,6 +477,21 @@ poolbuf.appendByte(CONSTANT_Class); poolbuf.appendChar(pool.put(xClassName(type))); } + } else if (value instanceof ModuleSymbol) { + ModuleSymbol sym = (ModuleSymbol) value; + poolbuf.appendByte(CONSTANT_ModuleId); + poolbuf.appendChar(pool.put(names.fromUtf(externalize(sym.flatName())))); + poolbuf.appendChar(sym.version == null ? 0 : pool.put(sym.version)); + } else if (value instanceof ModuleId) { + ModuleId mid = (ModuleId)value; + poolbuf.appendByte(CONSTANT_ModuleId); + poolbuf.appendChar(pool.put(names.fromUtf(externalize(mid.name)))); + poolbuf.appendChar(mid.version == null ? 0 : pool.put(mid.version)); + } else if (value instanceof ModuleQuery) { + ModuleQuery mid = (ModuleQuery)value; + poolbuf.appendByte(CONSTANT_ModuleQuery); + poolbuf.appendChar(pool.put(names.fromUtf(externalize(mid.name)))); + poolbuf.appendChar(mid.versionQuery == null ? 0 : pool.put(mid.versionQuery)); } else if (value instanceof MethodHandle) { MethodHandle ref = (MethodHandle)value; poolbuf.appendByte(CONSTANT_MethodHandle); @@ -994,6 +1011,95 @@ } /********************************************************************** + * Writing module attributes + **********************************************************************/ + + /** Write the Module attribute if needed. + * Returns the number of attributes written (0 or 1). + */ + int writeModuleAttribute(ClassSymbol c) { + if (c.modle == null) + return 0; + + int alenIdx = writeAttr(names.Module); + databuf.appendChar(pool.put(c.modle)); + endAttr(alenIdx); + return 1; + } + + int writeModuleMetadata(ModuleSymbol sym) { + int n = 0; + + if (sym.hasRequires()) { + int alenIdx = writeAttr(names.ModuleRequires); + // modules + List<RequiresModuleDirective> modules = sym.getRequiredModules(); + databuf.appendChar(modules.size()); + for (RequiresModuleDirective m: modules) { + databuf.appendChar(pool.put(m.moduleQuery)); + databuf.appendInt(RequiresFlag.value(m.flags)); + } + // services + List<RequiresServiceDirective> services = sym.getRequiredServices(); + databuf.appendChar(services.size()); + for (RequiresServiceDirective s: services) { + databuf.appendChar(pool.put(s.sym)); + databuf.appendInt(RequiresFlag.value(s.flags)); + } + endAttr(alenIdx); + n++; + } + + if (sym.hasViews()) { + int alenIdx = writeAttr(names.ModuleProvides); + List<ViewDeclaration> views = sym.getViews(); + databuf.appendChar(views.size()); + for (ViewDeclaration v: views) { + // name + databuf.appendChar(v.isDefault() ? 0 : pool.put(names.fromUtf(externalize(v.name)))); + // entrypoint, if any + ClassSymbol esym = v.getEntrypoint(); + databuf.appendChar(esym == null ? 0 : pool.put(esym)); + // aliases + List<ProvidesModuleDirective> aliases = v.getAliases(); + databuf.appendChar(aliases.size()); + for (ProvidesModuleDirective a: aliases) + databuf.appendChar(pool.put(a.moduleId)); + // services + List<ProvidesServiceDirective> services = v.getServices(); + databuf.appendChar(services.size()); + for (ProvidesServiceDirective s: services) { + databuf.appendChar(pool.put(s.service)); + databuf.appendChar(pool.put(s.impl)); + } + // exports + Set<PackageSymbol> exports = sym.getExports(v); + databuf.appendChar(exports.size()); + for (PackageSymbol e: exports) { + databuf.appendChar(pool.put(names.fromUtf(externalize(e.flatName())))); + } + // permits + List<PermitsDirective> permits = v.getPermits(); + databuf.appendChar(permits.size()); + for (PermitsDirective p: permits) { + databuf.appendChar(pool.put(p.moduleId)); + } + } + endAttr(alenIdx); + n++; + } + + if (sym.hasExtendedMetadata()) { + int alenIdx = writeAttr(names.ModuleData); + databuf.appendChar(pool.put(sym.extendedMetadata)); + endAttr(alenIdx); + n++; + } + + return n; + } + +/********************************************************************** * Writing Objects **********************************************************************/ @@ -1012,6 +1118,7 @@ if (!c.type.hasTag(CLASS)) return; // arrays if (pool != null && // pool might be null if called from xClassName c.owner.enclClass() != null && + c.owner.kind != MDL && (innerClasses == null || !innerClasses.contains(c))) { // log.errWriter.println("enter inner " + c);//DEBUG enterInner(c.owner.enclClass()); @@ -1613,9 +1720,25 @@ public JavaFileObject writeClass(ClassSymbol c) throws IOException, PoolOverflow, StringOverflow { + String name = (c.owner.kind == MDL ? c.name : c.flatname).toString(); + + Location outLocn; + if (fileManager instanceof ModuleFileManager && fileManager.hasLocation(CLASS_OUTPUT)) { + ModuleFileManager mfm = (ModuleFileManager) fileManager; + String pkgName = c.owner.kind == MDL ? "" : c.packge().fullname.toString(); + try { + outLocn = mfm.getModuleLocation(CLASS_OUTPUT, c.sourcefile, pkgName); + } catch (IllegalArgumentException e) { + throw new AssertionError(); + } + } else + // Note: when CLASS_OUTPUT is not set, getJavaFileForOutput will + // default to writing the output in the same directory as the sourcefile + outLocn = CLASS_OUTPUT; + JavaFileObject outFile - = fileManager.getJavaFileForOutput(CLASS_OUTPUT, - c.flatname.toString(), + = fileManager.getJavaFileForOutput(outLocn, + name, JavaFileObject.Kind.CLASS, c.sourcefile); OutputStream out = outFile.openOutputStream(); @@ -1743,6 +1866,10 @@ acount += writeJavaAnnotations(c.getRawAttributes()); acount += writeTypeAnnotations(c.getRawTypeAttributes()); acount += writeEnclosingMethodAttribute(c); + if (c.owner.kind == MDL) { + acount += writeModuleAttribute(c); + acount += writeModuleMetadata(c.modle); + } acount += writeExtraClassAttributes(c); poolbuf.appendInt(JAVA_MAGIC);
--- a/src/share/classes/com/sun/tools/javac/jvm/Pool.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/jvm/Pool.java Tue May 07 17:14:17 2013 -0700 @@ -39,6 +39,7 @@ import java.util.*; +import com.sun.tools.javac.util.Assert; /** An internal structure that corresponds to the constant pool of a classfile. * * <p><b>This is NOT part of any supported API. @@ -101,6 +102,7 @@ * package. Return the object's index in the pool. */ public int put(Object value) { + Assert.checkNonNull(value); value = makePoolValue(value); // assert !(value instanceof Type.TypeVar); Integer index = indices.get(value);
--- a/src/share/classes/com/sun/tools/javac/jvm/Target.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/jvm/Target.java Tue May 07 17:14:17 2013 -0700 @@ -295,4 +295,8 @@ public boolean hasEnclosingMethodAttribute() { return compareTo(JDK1_5) >= 0; } + + public boolean useModules() { + return compareTo(JDK1_7) >= 0; + } }
--- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue May 07 17:14:17 2013 -0700 @@ -44,9 +44,9 @@ import javax.lang.model.SourceVersion; import javax.tools.DiagnosticListener; import javax.tools.JavaFileManager; +import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileObject; import javax.tools.StandardLocation; - import static javax.tools.StandardLocation.CLASS_OUTPUT; import com.sun.source.util.TaskEvent; @@ -64,7 +64,6 @@ import com.sun.tools.javac.util.*; import com.sun.tools.javac.comp.CompileStates.CompileState; import com.sun.tools.javac.util.Log.WriterKind; - import static com.sun.tools.javac.code.TypeTag.CLASS; import static com.sun.tools.javac.main.Option.*; import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*; @@ -81,7 +80,7 @@ * This code and its internal interfaces are subject to change or * deletion without notice.</b> */ -public class JavaCompiler implements ClassReader.SourceCompleter { +public class JavaCompiler { /** The context key for the compiler. */ protected static final Context.Key<JavaCompiler> compilerKey = new Context.Key<JavaCompiler>(); @@ -374,7 +373,7 @@ types = Types.instance(context); taskListener = MultiTaskListener.instance(context); - reader.sourceCompleter = this; + reader.sourceCompleter = new Completer(); options = Options.instance(context); @@ -589,8 +588,7 @@ */ protected JCCompilationUnit parse(JavaFileObject filename, CharSequence content) { long msec = now(); - JCCompilationUnit tree = make.TopLevel(List.<JCTree.JCAnnotation>nil(), - null, List.<JCTree>nil()); + JCCompilationUnit tree = make.TopLevel(List.<JCTree>nil()); if (content != null) { if (verbose) { log.printVerbose("parsing.started", filename); @@ -676,8 +674,7 @@ tree = (tree == null) ? make.Ident(names.fromString(s)) : make.Select(tree, names.fromString(s)); } - JCCompilationUnit toplevel = - make.TopLevel(List.<JCTree.JCAnnotation>nil(), null, List.<JCTree>nil()); + JCCompilationUnit toplevel = make.TopLevel(List.<JCTree>nil()); toplevel.packge = syms.unnamedPackage; return attr.attribIdent(tree, toplevel); } finally { @@ -736,56 +733,83 @@ * by the class file reader. * @param c The class the source file of which needs to be compiled. */ - public void complete(ClassSymbol c) throws CompletionFailure { -// System.err.println("completing " + c);//DEBUG - if (completionFailureName == c.fullname) { - throw new CompletionFailure(c, "user-selected completion failure by class name"); - } - JCCompilationUnit tree; - JavaFileObject filename = c.classfile; - JavaFileObject prev = log.useSource(filename); + protected class Completer implements ClassReader.SourceCompleter { + final boolean allowModules; - try { - tree = parse(filename, filename.getCharContent(false)); - } catch (IOException e) { - log.error("error.reading.file", filename, JavacFileManager.getMessage(e)); - tree = make.TopLevel(List.<JCTree.JCAnnotation>nil(), null, List.<JCTree>nil()); - } finally { - log.useSource(prev); - } - - if (!taskListener.isEmpty()) { - TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree); - taskListener.started(e); + public Completer() { + allowModules = source.allowModules(); } - enter.complete(List.of(tree), c); + public void complete(ClassSymbol c) throws CompletionFailure { + if (completionFailureName == c.fullname) { + throw new CompletionFailure(c, "user-selected completion failure by class name"); + } + JCCompilationUnit tree; + JavaFileObject filename = c.classfile; + JavaFileObject prev = log.useSource(filename); - if (!taskListener.isEmpty()) { - TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree); - taskListener.finished(e); - } + try { + tree = parse(filename, filename.getCharContent(false)); + } catch (IOException e) { + log.error("error.reading.file", filename, JavacFileManager.getMessage(e)); + tree = make.TopLevel(List.<JCTree>nil()); + } finally { + log.useSource(prev); + } + + if (allowModules) { + if (!(filename instanceof JavaFileObject.Locatable)) + throw new CompletionFailure(c, "cannot determine module"); + Location l = ((JavaFileObject.Locatable) filename).getLocation(); + tree.modle = reader.enterModule(l); + } else { + tree.modle = syms.noModule; + } + + if (!taskListener.isEmpty()) { + TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree); + taskListener.started(e); + } - if (enter.getEnv(c) == null) { - boolean isPkgInfo = - tree.sourcefile.isNameCompatible("package-info", - JavaFileObject.Kind.SOURCE); - if (isPkgInfo) { - if (enter.getEnv(tree.packge) == null) { + enter.complete(List.of(tree), c); + + if (!taskListener.isEmpty()) { + TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree); + taskListener.finished(e); + } + + if (enter.getEnv(c) == null) { + boolean isPackageInfo = + tree.sourcefile.isNameCompatible("package-info", + JavaFileObject.Kind.SOURCE); + boolean isModuleInfo = + tree.sourcefile.isNameCompatible("module-info", + JavaFileObject.Kind.SOURCE); + if (isPackageInfo) { + if (enter.getEnv(tree.packge) == null) { + JCDiagnostic diag = + diagFactory.fragment("file.does.not.contain.package", + c.location()); + throw reader.new BadClassFile(c, filename, diag); + } + } else if (isModuleInfo) { + if (enter.getEnv(tree.modle) == null) { + JCDiagnostic diag = + diagFactory.fragment("file.does.not.contain.module", + c.location()); + throw reader.new BadClassFile(c, filename, diag); + } + } + else { JCDiagnostic diag = - diagFactory.fragment("file.does.not.contain.package", - c.location()); + diagFactory.fragment("file.doesnt.contain.class", + c.getQualifiedName()); throw reader.new BadClassFile(c, filename, diag); } - } else { - JCDiagnostic diag = - diagFactory.fragment("file.doesnt.contain.class", - c.getQualifiedName()); - throw reader.new BadClassFile(c, filename, diag); } + + implicitSourceFilesRead = true; } - - implicitSourceFilesRead = true; } /** Track when the JavaCompiler has been used to compile something. */ @@ -812,6 +836,7 @@ { if (processors != null && processors.iterator().hasNext()) explicitAnnotationProcessingRequested = true; + // as a JavaCompiler can only be used once, throw an exception if // it has been used before. if (hasBeenUsed) @@ -1404,7 +1429,7 @@ make.at(Position.FIRSTPOS); TreeMaker localMake = make.forToplevel(env.toplevel); - if (env.tree instanceof JCCompilationUnit) { + if (env.tree.hasTag(JCTree.Tag.TOPLEVEL) || env.tree.hasTag(JCTree.Tag.MODULE)) { if (!(stubOutput || sourceOutput || printFlat)) { if (shouldStop(CompileState.LOWER)) return;
--- a/src/share/classes/com/sun/tools/javac/main/Main.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/main/Main.java Tue May 07 17:14:17 2013 -0700 @@ -309,6 +309,37 @@ } } + + Option[] bootclasspathOptions = { +// XBOOTCLASSPATH_PREPEND, + ENDORSEDDIRS, +// BOOTCLASSPATH, +// XBOOTCLASSPATH_APPEND, + EXTDIRS + }; + Option[] moduleOptions = { + L, + MODULEPATH + }; + List<Option> bcpOpts = List.nil(); + List<Option> mOpts = List.nil(); + for (Option n: bootclasspathOptions) { + if (options.get(n) != null) + bcpOpts = bcpOpts.prepend(n); + } + for (Option n: moduleOptions) { + if (options.get(n) != null) + mOpts = mOpts.prepend(n); + } + if (bcpOpts.nonEmpty() && mOpts.nonEmpty()) { + error("err.conficting.options", bcpOpts.head.text, mOpts.head.text); + return null; + } + if (mOpts.nonEmpty() && !source.allowModules()) { + error("err.option.not.supported.in.source", mOpts.head.text, source.name); + return null; + } + String profileString = options.get(PROFILE); if (profileString != null) { Profile profile = Profile.lookup(profileString);
--- a/src/share/classes/com/sun/tools/javac/main/Option.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/main/Option.java Tue May 07 17:14:17 2013 -0700 @@ -153,6 +153,10 @@ } }, + MODULEPATH("-modulepath", "opt.arg.path", "opt.modulepath", STANDARD, FILEMANAGER), + + L("-L", "opt.arg.library", "opt.L", STANDARD, FILEMANAGER), + EXTDIRS("-extdirs", "opt.arg.dirs", "opt.extdirs", STANDARD, FILEMANAGER), DJAVA_EXT_DIRS("-Djava.ext.dirs=", "opt.arg.dirs", "opt.extdirs", EXTENDED, FILEMANAGER) {
--- a/src/share/classes/com/sun/tools/javac/model/JavacElements.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/model/JavacElements.java Tue May 07 17:14:17 2013 -0700 @@ -181,8 +181,8 @@ Symbol sym = cast(Symbol.class, e); class Vis extends JCTree.Visitor { List<JCAnnotation> result = null; - public void visitTopLevel(JCCompilationUnit tree) { - result = tree.packageAnnotations; + public void visitPackage(JCPackageDecl tree) { + result = tree.annots; } public void visitClassDef(JCClassDecl tree) { result = tree.mods.annotations;
--- a/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java Tue May 07 17:14:17 2013 -0700 @@ -101,6 +101,8 @@ } } + protected boolean allowVersionLiteral; + /** * Create a scanner from the input array. This method might * modify the array. To avoid copying the input array, ensure @@ -130,6 +132,14 @@ this.allowUnderscoresInLiterals = source.allowUnderscoresInLiterals(); } + protected boolean allowVersionLiteral() { + return allowVersionLiteral; + } + + protected void allowVersionLiteral(boolean allow) { + allowVersionLiteral = allow; + } + /** Report an error at the given position using the provided arguments. */ protected void lexError(int pos, String key, Object... args) { @@ -445,6 +455,70 @@ } } + /* same as scanIdent, except + * 1. '.' and '-' included + * 2. set tk to VERSION_LITERAL + */ + private void scanVersionLiteral() { + boolean isJavaIdentifierPart; + char high; + do { + reader.putChar(true); + switch (reader.ch) { + case '-': case '.': // specific to version literals + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': + case '$': case '_': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '\u0000': case '\u0001': case '\u0002': case '\u0003': + case '\u0004': case '\u0005': case '\u0006': case '\u0007': + case '\u0008': case '\u000E': case '\u000F': case '\u0010': + case '\u0011': case '\u0012': case '\u0013': case '\u0014': + case '\u0015': case '\u0016': case '\u0017': + case '\u0018': case '\u0019': case '\u001B': + case '\u007F': + break; + case '\u001A': // EOI is also a legal identifier part + if (reader.bp >= reader.buflen) { + name = reader.name(); + tk = TokenKind.VERSIONLITERAL; + return; + } + break; + default: + if (reader.ch < '\u0080') { + // all ASCII range chars already handled, above + isJavaIdentifierPart = false; + } else { + high = reader.scanSurrogates(); + if (high != 0) { + reader.putChar(high); + isJavaIdentifierPart = Character.isJavaIdentifierPart( + Character.toCodePoint(high, reader.ch)); + } else { + isJavaIdentifierPart = Character.isJavaIdentifierPart(reader.ch); + } + } + if (!isJavaIdentifierPart) { + name = reader.name(); + tk = TokenKind.VERSIONLITERAL; + return; + } + } + } while (true); + } + /** Read token. */ public Token readToken() { @@ -496,6 +570,10 @@ scanIdent(); break loop; case '0': + if (allowVersionLiteral) { + scanVersionLiteral(); + break loop; + } reader.scanChar(); if (reader.ch == 'x' || reader.ch == 'X') { reader.scanChar(); @@ -535,6 +613,10 @@ break loop; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + if (allowVersionLiteral) { + scanVersionLiteral(); + break loop; + } scanNumber(pos, 10); break loop; case '.':
--- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Tue May 07 17:14:17 2013 -0700 @@ -28,6 +28,7 @@ import java.util.*; import com.sun.source.tree.MemberReferenceTree.ReferenceMode; +import com.sun.source.tree.RequiresFlag; import com.sun.tools.javac.code.*; import com.sun.tools.javac.parser.Tokens.*; @@ -47,6 +48,7 @@ import static com.sun.tools.javac.parser.Tokens.TokenKind.GT; import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT; import static com.sun.tools.javac.parser.Tokens.TokenKind.LT; +import static com.sun.tools.javac.parser.Tokens.TokenKind.PACKAGE; import static com.sun.tools.javac.tree.JCTree.Tag.*; import static com.sun.tools.javac.util.ListBuffer.lb; @@ -162,6 +164,7 @@ this.allowStaticInterfaceMethods = source.allowStaticInterfaceMethods(); this.allowIntersectionTypesInCast = source.allowIntersectionTypesInCast(); this.allowTypeAnnotations = source.allowTypeAnnotations(); + this.allowModules = source.allowModules(); this.keepDocComments = keepDocComments; docComments = newDocCommentTable(keepDocComments, fac); this.keepLineMap = keepLineMap; @@ -231,6 +234,10 @@ */ boolean allowMethodReferences; + /** Switch: should we recognize modules? + */ + boolean allowModules; + /** Switch: should we allow default methods in interfaces? */ boolean allowDefaultMethods; @@ -656,6 +663,20 @@ } /** + * Qualident = Ident { DOT Ident } + * (used when we've had to lookahead at the first identifier) + */ + public JCExpression qualident(JCExpression head) { + JCExpression t = head; + while (token.kind == DOT) { + int pos = token.pos; + nextToken(); + t = toP(F.at(pos).Select(t, ident())); + } + return t; + } + + /** * Literal = * INTLITERAL * | LONGLITERAL @@ -3035,51 +3056,63 @@ boolean consumedToplevelDoc = false; boolean seenImport = false; boolean seenPackage = false; - List<JCAnnotation> packageAnnotations = List.nil(); - if (token.kind == MONKEYS_AT) + ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); + + if (token.kind == IDENTIFIER && token.name() == names.module) { + defs.append(moduleDecl(mods, token.comment(CommentStyle.JAVADOC))); + consumedToplevelDoc = true; + } else { + List<JCAnnotation> packageAnnotations = List.nil(); + if (token.kind == MONKEYS_AT) mods = modifiersOpt(); - if (token.kind == PACKAGE) { - seenPackage = true; - if (mods != null) { - checkNoMods(mods.flags); - packageAnnotations = mods.annotations; - mods = null; + if (token.kind == PACKAGE) { + seenPackage = true; + if (mods != null) { + checkNoMods(mods.flags); + packageAnnotations = mods.annotations; + mods = null; + } + nextToken(); + pid = qualident(false); + accept(SEMI); + JCPackageDecl pd = F.at(firstToken.pos).Package(packageAnnotations, pid); + Comment docComment = firstToken.comment(CommentStyle.JAVADOC); + consumedToplevelDoc = true; + attach(pd, docComment); + defs.append(pd); } - nextToken(); - pid = qualident(false); - accept(SEMI); - } - ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); - boolean checkForImports = true; - boolean firstTypeDecl = true; - while (token.kind != EOF) { - if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) { - // error recovery - skip(checkForImports, false, false, false); - if (token.kind == EOF) - break; - } - if (checkForImports && mods == null && token.kind == IMPORT) { - seenImport = true; - defs.append(importDeclaration()); - } else { - Comment docComment = token.comment(CommentStyle.JAVADOC); - if (firstTypeDecl && !seenImport && !seenPackage) { - docComment = firstToken.comment(CommentStyle.JAVADOC); - consumedToplevelDoc = true; + + boolean checkForImports = true; + boolean firstTypeDecl = true; + while (token.kind != EOF) { + if (token.pos <= endPosTable.errorEndPos) { + // error recovery + skip(checkForImports, false, false, false); + if (token.kind == EOF) + break; } - JCTree def = typeDeclaration(mods, docComment); - if (def instanceof JCExpressionStatement) - def = ((JCExpressionStatement)def).expr; - defs.append(def); - if (def instanceof JCClassDecl) - checkForImports = false; - mods = null; - firstTypeDecl = false; + if (checkForImports && mods == null && token.kind == IMPORT) { + seenImport = true; + defs.append(importDeclaration()); + } else { + Comment docComment = token.comment(CommentStyle.JAVADOC); + if (firstTypeDecl && !seenImport && !seenPackage) { + docComment = firstToken.comment(CommentStyle.JAVADOC); + consumedToplevelDoc = true; + } + JCTree def = typeDeclaration(mods, docComment); + if (def instanceof JCExpressionStatement) + def = ((JCExpressionStatement)def).expr; + defs.append(def); + if (def instanceof JCClassDecl) + checkForImports = false; + mods = null; + firstTypeDecl = false; + } } } - JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList()); + JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(defs.toList()); if (!consumedToplevelDoc) attach(toplevel, firstToken.comment(CommentStyle.JAVADOC)); if (defs.isEmpty()) @@ -3093,6 +3126,220 @@ return toplevel; } + /** + * ModuleDecl = { "@" Annotation } MODULE ModuleId [ ModuleProvides ] '{' { ModuleMetadata } '}' + * ModuleProvides = PROVIDES ModuleIdList + * + * called after MODULE has been seen + */ + JCModuleDecl moduleDecl(JCModifiers mods, Comment dc) { + int pos = token.pos; + if (!allowModules) { + log.error(pos, "modules.not.supported.in.source", source.name); + allowModules = true; + } + S.allowVersionLiteral(true); + // FIXME: unimpl annots + List<JCAnnotation> annots = List.nil(); + if (mods != null) { + checkNoMods(mods.flags); + annots = mods.annotations; + mods = null; + } + nextToken(); + JCModuleId mid = moduleId(); + List<JCModuleDirective> directives = null; + + accept(LBRACE); + directives = moduleDirectiveList(); + if (token.kind != RBRACE) { + setErrorEndPos(token.pos); + reportSyntaxError(S.prevToken().endPos, "expected", RBRACE); + } + + // The extended metadata is all of the textual content that follows the + // module declaration. + UnicodeReader reader = S.getReader(); + while (reader.bp < reader.buflen && Character.isWhitespace(reader.ch)) + reader.scanChar(); + while (reader.bp < reader.buflen) + reader.putChar(true); + Name moduleData = (reader.sp == 0) ? null : reader.name(); + + JCModuleDecl result = toP(F.at(pos).Module(mid, directives, moduleData)); + attach(result, dc); + return result; + } + + /** + * ModuleMetadataList = ModuleMetadata* + * ModuleMetadata = ModuleRequires | ModulePermits | ModuleProvides + * ModuleRequires = REQUIRES Identifier* ModuleId {',' ModuleId} + * ModulePermits = PERMITS QualifiedIdentifier {',' QualifiedIdentifier} + */ + List<JCModuleDirective> moduleDirectiveList() { + ListBuffer<JCModuleDirective> defs = new ListBuffer<JCModuleDirective>(); + + while (token.kind == IDENTIFIER || token.kind == CLASS) { + int pos = token.pos; + if (token.kind == CLASS) { + nextToken(); + JCExpression qualId = qualident(false); + accept(SEMI); + defs.append(toP(F.at(pos).Entrypoint(qualId))); + } else if (token.name() == names.exports) { + // FIXME, unimpl .**? + nextToken(); + JCExpression exportId = toP(F.at(token.pos).Ident(ident())); + while (token.kind == DOT) { + int pos1 = token.pos; + accept(DOT); + if (token.kind == STAR || token.kind == STARSTAR) { + Name tname = (token.kind == STAR ? names.asterisk : names.double_asterisk); + exportId = to(F.at(pos1).Select(exportId, tname)); + nextToken(); + break; + } else { + exportId = toP(F.at(pos1).Select(exportId, ident())); + } + } + accept(SEMI); + defs.append(toP(F.at(pos).Exports(exportId))); + } else if (token.name() == names.requires) { + ListBuffer<RequiresFlag> flags = new ListBuffer<RequiresFlag>(); + nextToken(); + if (token.kind == IDENTIFIER && token.name() == names.optional) { + flags.add(RequiresFlag.OPTIONAL); + nextToken(); + } + if (token.kind == IDENTIFIER && token.name() == names.service) { + nextToken(); + JCExpression qualId = qualident(false); + accept(SEMI); + defs.append(toP(F.at(pos).RequiresService(flags.toList(), qualId))); + } else { + while ((token.kind == PUBLIC) + || (token.kind == IDENTIFIER && token.name() == names.local)) { + RequiresFlag flag = (token.kind == PUBLIC) + ? RequiresFlag.REEXPORT : RequiresFlag.LOCAL; + // FIXME: check duplicates + flags.append(flag); + nextToken(); + } + JCModuleQuery moduleQuery = moduleQuery(); + accept(SEMI); + defs.append(toP(F.at(pos).RequiresModule(flags.toList(), moduleQuery))); + } + } else if (token.name() == names.permits) { + nextToken(); + JCExpression qualId = qualident(false); + accept(SEMI); + defs.append(toP(F.at(pos).Permits(qualId))); + } else if (token.name() == names.provides) { + nextToken(); + if (token.kind == IDENTIFIER && token.name() == names.service) { + nextToken(); + JCExpression serviceName = qualident(false); + if (token.kind == IDENTIFIER && token.name() == names.with) { + nextToken(); + JCExpression implName = qualident(false); + accept(SEMI); + defs.append(toP(F.at(pos).ProvidesService(serviceName, implName))); + } else { + log.error("with.expected"); + } + } else { + JCModuleId moduleId = moduleId(); + accept(SEMI); + defs.append(toP(F.at(pos).ProvidesModule(moduleId))); + } + } else if (token.name() == names.view) { + nextToken(); + JCExpression qualId = qualident(false); + accept(LBRACE); + List<JCModuleDirective> directives = moduleDirectiveList(); + accept(RBRACE); + defs.append(toP(F.at(pos).View(qualId, directives))); + } else + break; + } + + return defs.toList(); + } + + /** ModuleIdList = ModuleId {"," ModuleId} + */ + List<JCModuleId> moduleIdList() { + ListBuffer<JCModuleId> ts = new ListBuffer<JCModuleId>(); + ts.append(moduleId()); + while (token.kind == COMMA) { + nextToken(); + ts.append(moduleId()); + } + return ts.toList(); + } + + /** ModuleIdList = ModuleId {"," ModuleId} + * used when we've peeked ahead at the first identifier + */ + List<JCModuleId> moduleIdList(JCExpression head) { + ListBuffer<JCModuleId> ts = new ListBuffer<JCModuleId>(); + ts.append(moduleId(head)); + while (token.kind == COMMA) { + nextToken(); + ts.append(moduleId()); + } + return ts.toList(); + } + + JCModuleId moduleId() { + return moduleId(toP(F.at(token.pos).Ident(ident()))); + } + + JCModuleId moduleId(JCExpression head) { + int pos = token.pos; + JCTree qualId = qualident(head); + Name version = null; + if (token.kind == MONKEYS_AT) { + nextToken(); + if (token.kind == VERSIONLITERAL) { + version = token.name(); + } else + log.error(pos, "module.version.literal.expected"); + nextToken(); + } + return toP(F.at(pos).ModuleId(qualId, version)); + } + + JCModuleQuery moduleQuery() { + return moduleQuery(toP(F.at(token.pos).Ident(ident()))); + } + + JCModuleQuery moduleQuery(JCExpression head) { + int pos = token.pos; + JCTree qualId = qualident(head); + Name query = null; + if (token.kind == MONKEYS_AT) { + nextToken(); + if (token.kind == VERSIONLITERAL) { + query = token.name(); + nextToken(); + } else if (optag(token.kind) != Tag.NO_TAG) { // FIXME: close, but not close enough + Token op = token; + nextToken(); + if (token.kind == VERSIONLITERAL) { + query = names.fromString(op.kind.name + token.name()); + nextToken(); + } else { + log.error(token.pos, "module.version.literal.expected"); + } + } else { + log.error(pos, "module.version.query.expected"); + } + } + return toP(F.at(pos).ModuleQuery(qualId, query)); + } + /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";" */ JCTree importDeclaration() {
--- a/src/share/classes/com/sun/tools/javac/parser/Lexer.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/parser/Lexer.java Tue May 07 17:14:17 2013 -0700 @@ -25,7 +25,7 @@ package com.sun.tools.javac.parser; -import com.sun.tools.javac.parser.Tokens.*; +import com.sun.tools.javac.parser.Tokens.Token; import com.sun.tools.javac.util.Position.LineMap; /** @@ -84,4 +84,9 @@ * @return a LineMap */ LineMap getLineMap(); + + boolean allowVersionLiteral(); + void allowVersionLiteral(boolean allow); + + UnicodeReader getReader(); }
--- a/src/share/classes/com/sun/tools/javac/parser/Scanner.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/parser/Scanner.java Tue May 07 17:14:17 2013 -0700 @@ -134,4 +134,16 @@ public void errPos(int pos) { tokenizer.errPos(pos); } + + public boolean allowVersionLiteral() { + return tokenizer.allowVersionLiteral(); + } + + public void allowVersionLiteral(boolean allow) { + tokenizer.allowVersionLiteral(allow); + } + + public UnicodeReader getReader() { + return tokenizer.reader; + } }
--- a/src/share/classes/com/sun/tools/javac/parser/Tokens.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/parser/Tokens.java Tue May 07 17:14:17 2013 -0700 @@ -173,6 +173,7 @@ DOUBLELITERAL(Tag.NUMERIC), CHARLITERAL(Tag.NUMERIC), STRINGLITERAL(Tag.STRING), + VERSIONLITERAL(Tag.NAMED), TRUE("true", Tag.NAMED), FALSE("false", Tag.NAMED), NULL("null", Tag.NAMED), @@ -207,6 +208,7 @@ PLUS("+"), SUB("-"), STAR("*"), + STARSTAR("**"), SLASH("/"), AMP("&"), BAR("|"), @@ -230,14 +232,15 @@ CUSTOM; public final String name; - public final Tag tag; + final Tag tag; TokenKind() { this(null, Tag.DEFAULT); } TokenKind(String name) { - this(name, Tag.DEFAULT); + // TEMP HACK + this(name, Character.isLetter(name.charAt(0)) ? Tag.NAMED : Tag.DEFAULT); } TokenKind(Tag tag) { @@ -249,6 +252,7 @@ this.tag = tag; } + @Override public String toString() { switch (this) { case IDENTIFIER: @@ -265,6 +269,8 @@ return "token.float"; case DOUBLELITERAL: return "token.double"; + case VERSIONLITERAL: + return "token.version"; case ERROR: return "token.bad-symbol"; case EOF: @@ -422,6 +428,7 @@ this.name = name; } + @Override protected void checkKind() { if (kind.tag != Tag.NAMED) { throw new AssertionError("Bad token kind - expected " + Tag.NAMED); @@ -443,6 +450,7 @@ this.stringVal = stringVal; } + @Override protected void checkKind() { if (kind.tag != Tag.STRING) { throw new AssertionError("Bad token kind - expected " + Tag.STRING); @@ -464,6 +472,7 @@ this.radix = radix; } + @Override protected void checkKind() { if (kind.tag != Tag.NUMERIC) { throw new AssertionError("Bad token kind - expected " + Tag.NUMERIC);
--- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Tue May 07 17:14:17 2013 -0700 @@ -1332,9 +1332,19 @@ node.type = null; } public void visitTopLevel(JCCompilationUnit node) { + node.locn = null; + node.modle = null; node.packge = null; super.visitTopLevel(node); } + public void visitModuleDef(JCModuleDecl node) { + node.sym = null; + super.visitModuleDef(node); + } + public void visitPackageDef(JCPackageDecl node) { + node.sym = null; + super.visitPackageDef(node); + } public void visitClassDef(JCClassDecl node) { node.sym = null; super.visitClassDef(node);
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue May 07 17:14:17 2013 -0700 @@ -1082,6 +1082,100 @@ compiler.misc.inaccessible.varargs.type=\ formal varargs element type {0} is not accessible from {1} {2} +compiler.err.mdl.no.version.available=\ + no version available for module {0} +compiler.err.mdl.no.unique.version.available=\ + no unique version available for module {0} +compiler.err.mdl.required.version.not.available=\ + required version not available for module {0} +compiler.err.mdl.duplicate.definition=\ + duplicate definition of module {0} +compiler.err.mdl.file.in.wrong.directory=\ + file is not in the expected subdirectory within its package hierarchy +compiler.err.module.library.not.found=\ + module library not found: {0} +compiler.err.module.decl.not.permitted=\ + module declaration not permitted +compiler.misc.cant.resolve.modules=\ + cannot resolve module dependencies +compiler.err.jigsaw.resolver.error=\ + Cannot resolve module dependencies using Jigsaw module resolver\n{0} +compiler.err.jigsaw.resolver.ioerror=\ + IO error while resolving modules using Jigsaw module resolver\n{0} + +# 0: string +compiler.err.cannot.open.module.library=\ + cannot open module library: {0} + +compiler.err.dupl.entrypoint=\ + entry point already specified for module or view. + +# 0: symbol +compiler.err.dupl.exports=\ + ''export'' directive for package {0} already specified + +# 0: symbol +compiler.err.dupl.permits=\ + ''permits'' directive for module {0} already specified + +# 0: symbol +compiler.err.dupl.provides=\ + ''provides'' directive for module {0} already specified + +# 0: symbol +compiler.err.dupl.provides.service=\ + ''provides'' directive service {0} with {1} already specified + +# 0: symbol +compiler.err.dupl.requires=\ + ''requires'' directive for module {0} already specified + +# 0: symbol +compiler.err.dupl.requires.service=\ + ''requires'' directive for service {0} already specified + +# 0: string +compiler.err.dupl.view=\ + view {0} already defined in this module + +# 0: symbol +compiler.err.mdl.already.defined=\ + module {0} already defined + +compiler.err.mdl.module.file.manager.required=\ + module file manager required + +compiler.err.module.version.literal.expected=\ + version literal expected + +compiler.err.module.version.query.expected=\ + version query expected + +compiler.err.nested.view.not.allowed=\ + nested view not permitted + +compiler.err.requires.not.allowed.in.view=\ + ''requires'' directive not permitted in view + +compiler.err.with.expected=\ + ''with'' expected + +# 0: symbol +compiler.err.no.psv.main=\ + class {0} does not define public static void main(String[]) + +# 0: symbol +compiler.err.service.impl.is.abstract=\ + service implementation class {0} is abstract + +# 0: symbol +compiler.err.service.impl.no.default.constr=\ + class {0} does not define a public no-args constructor + +# 0: symbol +compiler.err.service.impl.is.inner=\ + service implemention class {0} is an inner class + # In the following string, {1} will always be the detail message from # java.io.IOException. # 0: symbol, 1: string @@ -1588,6 +1682,9 @@ compiler.misc.token.double=\ <double> +compiler.misc.token.version=\ + <version> + compiler.misc.token.bad-symbol=\ <bad symbol> @@ -1644,6 +1741,9 @@ compiler.misc.unnamed.package=\ unnamed package +compiler.misc.unnamed.module=\ + unnamed module + ##### # 0: symbol, 1: message segment @@ -1700,9 +1800,14 @@ compiler.misc.file.doesnt.contain.class=\ file does not contain class {0} +# 0: symbol compiler.misc.file.does.not.contain.package=\ file does not contain package {0} +# 0: symbol +compiler.misc.file.does.not.contain.module=\ + file does not contain module {0} + compiler.misc.illegal.start.of.class.file=\ illegal start of class file @@ -2045,6 +2150,9 @@ compiler.misc.kindname.instance.init=\ instance initializer +compiler.misc.kindname.module=\ + module + ##### compiler.misc.no.args=\ @@ -2259,6 +2367,11 @@ (use -source 8 or higher to enable method references) # 0: string +compiler.err.modules.not.supported.in.source=\ + modules are not supported in -source {0}\n\ +(use -source 8 or higher to enable modules) + +# 0: string compiler.err.default.methods.not.supported.in.source=\ default methods are not supported in -source {0}\n\ (use -source 8 or higher to enable default methods)
--- a/src/share/classes/com/sun/tools/javac/resources/javac.properties Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/resources/javac.properties Tue May 07 17:14:17 2013 -0700 @@ -41,6 +41,8 @@ Specify where to find user class files and annotation processors javac.opt.sourcepath=\ Specify where to find input source files +javac.opt.modulepath=\ + Specify where to find module source and class files javac.opt.bootclasspath=\ Override location of bootstrap class files javac.opt.Xbootclasspath.p=\ @@ -83,12 +85,16 @@ Specify whether or not to generate class files for implicitly referenced files javac.opt.pkginfo=\ Specify handling of package-info files +javac.opt.L=\ + Specify location of module library javac.opt.arg.class=\ <class> javac.opt.arg.class.list=\ <class1>[,<class2>,<class3>...] javac.opt.arg.flag=\ <flag> +javac.opt.arg.library=\ + <library> javac.opt.arg.key.equals.value=\ key[=value] javac.opt.arg.path=\ @@ -207,6 +213,11 @@ not a directory: {0} javac.err.file.not.file=\ not a file: {0} +javac.err.conficting.options=\ + cannot specify both {0} and {1} +javac.err.option.not.supported.in.source=\ + option {0} not supported with -source {1}\n\ +(use -source 7 or higher to enable module options) javac.msg.plugin.not.found=\ plug-in not found: {0} ## messages
--- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java Tue May 07 17:14:17 2013 -0700 @@ -31,6 +31,7 @@ import javax.lang.model.element.Modifier; import javax.lang.model.type.TypeKind; +import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileObject; import com.sun.source.tree.*; @@ -342,6 +343,19 @@ DIV_ASG(DIV), // /= MOD_ASG(MOD), // %= + MODULE, + MODULE_ID, + MODULE_QUERY, + VIEW_DECLARATION, + ENTRYPOINT_DIRECTIVE, + EXPORT_DIRECTIVE, + PERMITS_DIRECTIVE, + PROVIDES_MODULE_DIRECTIVE, + PROVIDES_SERVICE_DIRECTIVE, + REQUIRES_MODULE_DIRECTIVE, + REQUIRES_SERVICE_DIRECTIVE, + PACKAGE, + /** A synthetic let expression, of type LetExpr. */ LETEXPR; // ala scheme @@ -385,6 +399,7 @@ } } + /* The (encoded) position in the source file. @see util.Position. */ public int pos; @@ -444,7 +459,7 @@ public Object clone() { try { return super.clone(); - } catch(CloneNotSupportedException e) { + } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } @@ -479,13 +494,14 @@ * Everything in one source file is kept in a {@linkplain JCCompilationUnit} structure. */ public static class JCCompilationUnit extends JCTree implements CompilationUnitTree { - public List<JCAnnotation> packageAnnotations; - /** The tree representing the package clause. */ - public JCExpression pid; - /** All definitions in this file (ClassDef, Import, and Skip) */ + /** All definitions in this file (Package, Import, ClassDef, and Skip) */ public List<JCTree> defs; - /* The source file name. */ + /** The source file name. */ public JavaFileObject sourcefile; + /** The module to which this compilation unit belongs. */ + public ModuleSymbol modle; + /** The location in which this compilation unit was found. */ + public Location locn; /** The package to which this compilation unit belongs. */ public PackageSymbol packge; /** A scope for all named imports. */ @@ -500,15 +516,11 @@ /* An object encapsulating ending positions of source ranges indexed by * the tree nodes they belong to. Defined only if option -Xjcov is set. */ public EndPosTable endPositions = null; - protected JCCompilationUnit(List<JCAnnotation> packageAnnotations, - JCExpression pid, - List<JCTree> defs, + protected JCCompilationUnit(List<JCTree> defs, JavaFileObject sourcefile, PackageSymbol packge, ImportScope namedImportScope, StarImportScope starImportScope) { - this.packageAnnotations = packageAnnotations; - this.pid = pid; this.defs = defs; this.sourcefile = sourcefile; this.packge = packge; @@ -520,7 +532,8 @@ public Kind getKind() { return Kind.COMPILATION_UNIT; } public List<JCAnnotation> getPackageAnnotations() { - return packageAnnotations; + JCPackageDecl pd = TreeInfo.getPackage(this); + return pd == null ? List.<JCAnnotation>nil() : pd.getAnnotations(); } public List<JCImport> getImports() { ListBuffer<JCImport> imports = new ListBuffer<JCImport>(); @@ -532,7 +545,10 @@ } return imports.toList(); } - public JCExpression getPackageName() { return pid; } + public JCExpression getPackageName() { + JCPackageDecl pd = TreeInfo.getPackage(this); + return pd == null ? null : pd.getPackageId(); + } public JavaFileObject getSourceFile() { return sourcefile; } @@ -2347,6 +2363,446 @@ } } + public static class JCModuleId extends JCTree implements ModuleIdTree { + public JCTree qualId; + public Name version; + protected JCModuleId(JCTree qualId, Name version) { + this.qualId = qualId; + this.version = version; + } + + @Override + public void accept(Visitor v) { v.visitModuleId(this); } + + @Override + public Kind getKind() { + return Kind.MODULE_ID; + } + + @Override + public JCTree getName() { + return qualId; + } + + @Override + public Name getVersion() { + return version; + } + + @Override + public <R, D> R accept(TreeVisitor<R, D> v, D d) { + return v.visitModuleId(this, d); + } + + @Override + public Tag getTag() { + return MODULE_ID; + } + } + + public static class JCModuleQuery extends JCTree implements ModuleQueryTree { + public JCTree qualId; + public Name versionQuery; + protected JCModuleQuery(JCTree qualId, Name versionQuery) { + this.qualId = qualId; + this.versionQuery = versionQuery; + } + + @Override + public void accept(Visitor v) { v.visitModuleQuery(this); } + + @Override + public Kind getKind() { + return Kind.MODULE_QUERY; + } + + @Override + public JCTree getName() { + return qualId; + } + + @Override + public Name getVersionQuery() { + return versionQuery; + } + + @Override + public <R, D> R accept(TreeVisitor<R, D> v, D d) { + return v.visitModuleQuery(this, d); + } + + @Override + public Tag getTag() { + return MODULE_QUERY; + } + } + + public static class JCModuleDecl extends JCTree implements ModuleTree { + public JCModuleId id; + public List<JCModuleDirective> directives; + public Name metadata; + public ModuleSymbol sym; + + protected JCModuleDecl(JCModuleId id, + List<JCModuleDirective> directives, Name metadata) { + this.id = id; + this.directives = directives; + this.metadata = metadata; + } + + @Override + public void accept(Visitor v) { v.visitModuleDef(this); } + + @Override + public Kind getKind() { + return Kind.MODULE; + } + + @Override + public JCModuleId getId() { + return id; + } + + @Override + public List<JCModuleDirective> getDirectives() { + return directives; + } + + @Override + public Name getExtendedMetadata() { + return metadata; + } + + @Override + public <R, D> R accept(TreeVisitor<R, D> v, D d) { + return v.visitModule(this, d); + } + + @Override + public Tag getTag() { + return MODULE; + } + } + + public static abstract class JCModuleDirective extends JCTree implements ModuleDirectiveTree { + } + + public static class JCViewDecl extends JCModuleDirective implements ViewDeclarationTree { + public JCExpression name; + public List<JCModuleDirective> directives; + + protected JCViewDecl(JCExpression name, List<JCModuleDirective> directives) { + this.name = name; + this.directives = directives; + } + + @Override + public void accept(Visitor v) { v.visitView(this); } + + @Override + public Kind getKind() { + return Kind.VIEW_DECLARATION; + } + + @Override + public JCExpression getName() { + return name; + } + + @Override + public List<JCModuleDirective> getDirectives() { + return directives; + } + + @Override + public <R, D> R accept(TreeVisitor<R, D> v, D d) { + return v.visitView(this, d); + } + + @Override + public Tag getTag() { + return VIEW_DECLARATION; + } + } + + public static class JCEntrypointDirective extends JCModuleDirective + implements EntrypointDirectiveTree { + public JCExpression qualId; + protected JCEntrypointDirective(JCExpression qualId) { + this.qualId = qualId; + } + + @Override + public void accept(Visitor v) { v.visitEntrypoint(this); } + + @Override + public Kind getKind() { + return Kind.ENTRYPOINT_DIRECTIVE; + } + + @Override + public JCExpression getClassName() { + return qualId; + } + + @Override + public <R, D> R accept(TreeVisitor<R, D> v, D d) { + return v.visitEntrypoint(this, d); + } + + @Override + public Tag getTag() { + return ENTRYPOINT_DIRECTIVE; + } + } + + public static class JCExportDirective extends JCModuleDirective + implements ExportDirectiveTree { + public JCExpression qualid; + + protected JCExportDirective(JCExpression qualId) { + this.qualid = qualId; + } + + @Override + public void accept(Visitor v) { v.visitExports(this); } + + @Override + public Kind getKind() { + return Kind.EXPORT_DIRECTIVE; + } + + @Override + public JCExpression getExportName() { + return qualid; + } + + @Override + public <R, D> R accept(TreeVisitor<R, D> v, D d) { + return v.visitExport(this, d); + } + + @Override + public Tag getTag() { + return EXPORT_DIRECTIVE; + } + } + + public static class JCPermitsDirective extends JCModuleDirective + implements PermitsDirectiveTree { + public JCExpression moduleName; + + protected JCPermitsDirective(JCExpression moduleName) { + this.moduleName = moduleName; + } + + @Override + public void accept(Visitor v) { v.visitPermits(this); } + + @Override + public Kind getKind() { + return Kind.PERMITS_DIRECTIVE; + } + + @Override + public <R, D> R accept(TreeVisitor<R, D> v, D d) { + return v.visitPermits(this, d); + } + + @Override + public JCExpression getModuleName() { + return moduleName; + } + + @Override + public Tag getTag() { + return PERMITS_DIRECTIVE; + } + } + + public static class JCRequiresModuleDirective extends JCModuleDirective + implements RequiresModuleDirectiveTree { + public List<RequiresFlag> flags; + public JCModuleQuery moduleQuery; + + protected JCRequiresModuleDirective(List<RequiresFlag> flags, JCModuleQuery moduleQuery) { + this.flags = flags; + this.moduleQuery = moduleQuery; + } + + @Override + public void accept(Visitor v) { v.visitRequiresModule(this); } + + @Override + public Kind getKind() { + return Kind.REQUIRES_MODULE_DIRECTIVE; + } + + @Override + public <R, D> R accept(TreeVisitor<R, D> v, D d) { + return v.visitRequiresModule(this, d); + } + + @Override + public List<RequiresFlag> getFlags() { + return flags; + } + + @Override + public JCModuleQuery getModuleQuery() { + return moduleQuery; + } + + @Override + public Tag getTag() { + return REQUIRES_MODULE_DIRECTIVE; + } + } + + public static class JCRequiresServiceDirective extends JCModuleDirective + implements RequiresServiceDirectiveTree { + public List<RequiresFlag> flags; + public JCExpression serviceName; + + protected JCRequiresServiceDirective(List<RequiresFlag> flags, JCExpression serviceName) { + this.flags = flags; + this.serviceName = serviceName; + } + + @Override + public void accept(Visitor v) { v.visitRequiresService(this); } + + @Override + public Kind getKind() { + return Kind.REQUIRES_SERVICE_DIRECTIVE; + } + + @Override + public <R, D> R accept(TreeVisitor<R, D> v, D d) { + return v.visitRequiresService(this, d); + } + + @Override + public List<RequiresFlag> getFlags() { + return flags; + } + + @Override + public JCExpression getServiceName() { + return serviceName; + } + + @Override + public Tag getTag() { + return REQUIRES_SERVICE_DIRECTIVE; + } + } + + public static class JCProvidesModuleDirective extends JCModuleDirective + implements ProvidesModuleDirectiveTree { + public JCModuleId moduleId; + + protected JCProvidesModuleDirective(JCModuleId moduleId) { + this.moduleId = moduleId; + } + + @Override + public void accept(Visitor v) { v.visitProvidesModule(this); } + + @Override + public Kind getKind() { + return Kind.PROVIDES_MODULE_DIRECTIVE; + } + + @Override + public <R, D> R accept(TreeVisitor<R, D> v, D d) { + return v.visitProvidesModule(this, d); + } + + @Override + public JCModuleId getModuleId() { + return moduleId; + } + + @Override + public Tag getTag() { + return PROVIDES_MODULE_DIRECTIVE; + } + } + + public static class JCProvidesServiceDirective extends JCModuleDirective + implements ProvidesServiceDirectiveTree { + public JCExpression serviceName; + public JCExpression implName; + + protected JCProvidesServiceDirective(JCExpression serviceName, JCExpression implName) { + this.serviceName = serviceName; + this.implName = implName; + } + + @Override + public void accept(Visitor v) { v.visitProvidesService(this); } + + @Override + public Kind getKind() { + return Kind.PROVIDES_SERVICE_DIRECTIVE; + } + + @Override + public <R, D> R accept(TreeVisitor<R, D> v, D d) { + return v.visitProvidesService(this, d); + } + + @Override + public JCExpression getServiceName() { + return serviceName; + } + + @Override + public JCExpression getImplementationName() { + return implName; + } + + @Override + public Tag getTag() { + return PROVIDES_SERVICE_DIRECTIVE; + } + } + + public static class JCPackageDecl extends JCTree implements com.sun.source.tree.PackageTree { + public List<JCAnnotation> annots; + public JCExpression packageId; + public PackageSymbol sym; + protected JCPackageDecl(List<JCAnnotation> annots, JCExpression packageId) { + this.annots = annots; + this.packageId = packageId; + } + @Override + public void accept(Visitor v) { v.visitPackageDef(this); } + + public Kind getKind() { + return Kind.PACKAGE; + } + + public List<JCAnnotation> getAnnotations() { + return annots; + } + + public JCExpression getPackageId() { + return packageId; + } + + @Override + public <R, D> R accept(TreeVisitor<R, D> v, D d) { + return v.visitPackage(this, d); + } + + @Override + public Tag getTag() { + return PACKAGE; + } + } + public static class JCErroneous extends JCExpression implements com.sun.source.tree.ErroneousTree { public List<? extends JCTree> errs; @@ -2399,9 +2855,7 @@ /** An interface for tree factories */ public interface Factory { - JCCompilationUnit TopLevel(List<JCAnnotation> packageAnnotations, - JCExpression pid, - List<JCTree> defs); + JCCompilationUnit TopLevel(List<JCTree> defs); JCImport Import(JCTree qualid, boolean staticImport); JCClassDecl ClassDef(JCModifiers mods, Name name, @@ -2482,6 +2936,17 @@ JCAnnotation Annotation(JCTree annotationType, List<JCExpression> args); JCModifiers Modifiers(long flags, List<JCAnnotation> annotations); JCErroneous Erroneous(List<? extends JCTree> errs); + JCModuleDecl Module(JCModuleId moduleId, List<JCModuleDirective> directives, Name metadata); + JCViewDecl View(JCExpression name, List<JCModuleDirective> directives); + JCModuleId ModuleId(JCTree qualId, Name version); + JCModuleQuery ModuleQuery(JCTree qualId, Name versionQuery); + JCEntrypointDirective Entrypoint(JCExpression qualId); + JCExportDirective Exports(JCExpression qualId); + JCPermitsDirective Permits(JCExpression qualId); + JCProvidesModuleDirective ProvidesModule(JCModuleId moduleId); + JCProvidesServiceDirective ProvidesService(JCExpression serviceName, JCExpression implementationName); + JCRequiresModuleDirective RequiresModule(List<RequiresFlag> flags, JCModuleQuery moduleQuery); + JCRequiresServiceDirective RequiresService(List<RequiresFlag> flags, JCExpression serviceName); LetExpr LetExpr(List<JCVariableDecl> defs, JCTree expr); } @@ -2541,6 +3006,18 @@ public void visitModifiers(JCModifiers that) { visitTree(that); } public void visitAnnotatedType(JCAnnotatedType that) { visitTree(that); } public void visitErroneous(JCErroneous that) { visitTree(that); } + public void visitModuleDef(JCModuleDecl that) { visitTree(that); } + public void visitEntrypoint(JCEntrypointDirective that) { visitTree(that); } + public void visitExports(JCExportDirective that) { visitTree(that); } + public void visitModuleId(JCModuleId that) { visitTree(that); } + public void visitModuleQuery(JCModuleQuery that) { visitTree(that); } + public void visitPermits(JCPermitsDirective that) { visitTree(that); } + public void visitProvidesModule(JCProvidesModuleDirective that) { visitTree(that); } + public void visitProvidesService(JCProvidesServiceDirective that) { visitTree(that); } + public void visitRequiresModule(JCRequiresModuleDirective that) { visitTree(that); } + public void visitRequiresService(JCRequiresServiceDirective that) { visitTree(that); } + public void visitView(JCViewDecl that) { visitTree(that); } + public void visitPackageDef(JCPackageDecl that) { visitTree(that); } public void visitLetExpr(LetExpr that) { visitTree(that); } public void visitTree(JCTree that) { Assert.error(); }
--- a/src/share/classes/com/sun/tools/javac/tree/Pretty.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/tree/Pretty.java Tue May 07 17:14:17 2013 -0700 @@ -25,6 +25,7 @@ package com.sun.tools.javac.tree; +import com.sun.source.tree.RequiresFlag; import java.io.*; import com.sun.source.tree.MemberReferenceTree.ReferenceMode; @@ -366,33 +367,40 @@ * @param cdef The class definition, which is assumed to be part of the * toplevel tree. */ + @SuppressWarnings("fallthrough") public void printUnit(JCCompilationUnit tree, JCClassDecl cdef) throws IOException { docComments = tree.docComments; printDocComment(tree); - if (tree.pid != null) { - print("package "); - printExpr(tree.pid); - print(";"); - println(); - } - boolean firstImport = true; - for (List<JCTree> l = tree.defs; - l.nonEmpty() && (cdef == null || l.head.hasTag(IMPORT)); - l = l.tail) { - if (l.head.hasTag(IMPORT)) { - JCImport imp = (JCImport)l.head; - Name name = TreeInfo.name(imp.qualid); - if (name == name.table.names.asterisk || - cdef == null || - isUsed(TreeInfo.symbol(imp.qualid), cdef)) { - if (firstImport) { - firstImport = false; + boolean inImports = false; + for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { + switch (l.head.getTag()) { + case IMPORT: + JCImport imp = (JCImport)l.head; + Name name = TreeInfo.name(imp.qualid); + if (name == name.table.names.asterisk || + cdef == null || + isUsed(TreeInfo.symbol(imp.qualid), cdef)) { + if (!inImports) { + inImports = true; + println(); + } + printStat(imp); + } + break; + + default: + if (cdef != null) + break; + // fall-through + + case MODULE: + case PACKAGE: + if (inImports) { + inImports = false; println(); } - printStat(imp); - } - } else { - printStat(l.head); + printStat(l.head); + break; } } if (cdef != null) { @@ -428,6 +436,159 @@ } } + @Override + public void visitModuleDef(JCModuleDecl tree) { + try { + print("module "); + printExpr(tree.id); + if (tree.directives == null) { + print(";"); + } else { + printBlock(tree.directives); + } + println(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void visitModuleId(JCModuleId tree) { + try { + printExpr(tree.qualId); + if (tree.version != null) { + print(" @ "); + print(tree.version); // JIGSAW FIXME -- CHECK IF QUOTES REQUIRED + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void visitModuleQuery(JCModuleQuery tree) { + try { + printExpr(tree.qualId); + if (tree.versionQuery != null) { + print(" @ "); + print(tree.versionQuery); // JIGSAW FIXME -- CHECK IF QUOTES REQUIRED + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void visitEntrypoint(JCEntrypointDirective tree) { + try { + print("class "); + printExpr(tree.qualId); + print(";"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void visitExports(JCExportDirective tree) { + try { + print("export "); + printExpr(tree.qualid); + print(";"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void visitPermits(JCPermitsDirective tree) { + try { + print("permits "); + printExpr(tree.moduleName); + print(";"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void visitProvidesModule(JCProvidesModuleDirective tree) { + try { + print("provides "); + printExpr(tree.moduleId); + print(";"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void visitProvidesService(JCProvidesServiceDirective tree) { + try { + print("provides service "); + printExpr(tree.serviceName); + print(" with "); + printExpr(tree.implName); + print(";"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void visitRequiresModule(JCRequiresModuleDirective tree) { + try { + print("requires "); + for (List<RequiresFlag> l = tree.flags; l.nonEmpty(); l = l.tail ) { + print(l.head); + print(" "); + } + printExpr(tree.moduleQuery); + print(";"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void visitRequiresService(JCRequiresServiceDirective tree) { + try { + print("requires service "); + for (List<RequiresFlag> l = tree.flags; l.nonEmpty(); l = l.tail ) { + print(l.head); + print(" "); + } + printExpr(tree.serviceName); + print(";"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void visitView(JCViewDecl tree) { + try { + print("module "); + printExpr(tree.name); + printBlock(tree.directives); + println(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public void visitPackageDef(JCPackageDecl tree) { + try { + printAnnotations(tree.annots); + print("package "); + printExpr(tree.packageId); + print(";"); + println(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + public void visitImport(JCImport tree) { try { print("import ");
--- a/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java Tue May 07 17:14:17 2013 -0700 @@ -29,6 +29,7 @@ import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Name; /** * Creates a copy of a tree, using a given TreeMaker. @@ -346,10 +347,8 @@ public JCTree visitCompilationUnit(CompilationUnitTree node, P p) { JCCompilationUnit t = (JCCompilationUnit) node; - List<JCAnnotation> packageAnnotations = copy(t.packageAnnotations, p); - JCExpression pid = copy(t.pid, p); List<JCTree> defs = copy(t.defs, p); - return M.at(t.pos).TopLevel(packageAnnotations, pid, defs); + return M.at(t.pos).TopLevel(defs); } public JCTree visitTry(TryTree node, P p) { @@ -440,6 +439,97 @@ return M.at(t.pos).Wildcard(kind, inner); } + @Override + public JCTree visitModule(ModuleTree node, P p) { + JCModuleDecl t = (JCModuleDecl) node; + JCModuleId moduleId = copy(t.id); + List<JCModuleDirective> directives = copy(t.directives); + return M.at(t.pos).Module(moduleId, directives, t.metadata); + } + + @Override + public JCTree visitView(ViewDeclarationTree node, P p) { + JCViewDecl t = (JCViewDecl) node; + JCExpression name = copy(t.name); + List<JCModuleDirective> directives = copy(t.directives); + return M.at(t.pos).View(name, directives); + } + + @Override + public JCEntrypointDirective visitEntrypoint(EntrypointDirectiveTree node, P p) { + JCEntrypointDirective t = (JCEntrypointDirective) node; + JCExpression qualId = copy(t.qualId, p); + return M.at(t.pos).Entrypoint(qualId); + } + + @Override + public JCExportDirective visitExport(ExportDirectiveTree node, P p) { + JCExportDirective t = (JCExportDirective) node; + JCExpression qualId = copy(t.qualid, p); + return M.at(t.pos).Exports(qualId); + } + + @Override + public JCModuleId visitModuleId(ModuleIdTree node, P p) { + JCModuleId t = (JCModuleId) node; + JCTree qualId = copy(t.qualId, p); + Name version = t.version; + return M.at(t.pos).ModuleId(qualId, version); + } + + @Override + public JCModuleQuery visitModuleQuery(ModuleQueryTree node, P p) { + JCModuleQuery t = (JCModuleQuery) node; + JCTree qualId = copy(t.qualId, p); + Name versionQuery = t.versionQuery; + return M.at(t.pos).ModuleQuery(qualId, versionQuery); + } + + @Override + public JCPermitsDirective visitPermits(PermitsDirectiveTree node, P p) { + JCPermitsDirective t = (JCPermitsDirective) node; + JCExpression moduleName = copy(t.moduleName, p); + return M.at(t.pos).Permits(moduleName); + } + + @Override + public JCProvidesModuleDirective visitProvidesModule(ProvidesModuleDirectiveTree node, P p) { + JCProvidesModuleDirective t = (JCProvidesModuleDirective) node; + JCModuleId moduleId = copy(t.moduleId, p); + return M.at(t.pos).ProvidesModule(moduleId); + } + + @Override + public JCProvidesServiceDirective visitProvidesService(ProvidesServiceDirectiveTree node, P p) { + JCProvidesServiceDirective t = (JCProvidesServiceDirective) node; + JCExpression serviceName = copy(t.serviceName, p); + JCExpression implName = copy(t.implName, p); + return M.at(t.pos).ProvidesService(serviceName, implName); + } + + @Override + public JCRequiresModuleDirective visitRequiresModule(RequiresModuleDirectiveTree node, P p) { + JCRequiresModuleDirective t = (JCRequiresModuleDirective) node; + List<RequiresFlag> flags = t.flags; + JCModuleQuery moduleQuery = copy(t.moduleQuery, p); + return M.at(t.pos).RequiresModule(flags, moduleQuery); + } + + @Override + public JCRequiresServiceDirective visitRequiresService(RequiresServiceDirectiveTree node, P p) { + JCRequiresServiceDirective t = (JCRequiresServiceDirective) node; + List<RequiresFlag> flags = t.flags; + JCExpression serviceName = copy(t.serviceName, p); + return M.at(t.pos).RequiresService(flags, serviceName); + } + + public JCTree visitPackage(PackageTree node, P p) { + JCPackageDecl t = (JCPackageDecl) node; + List<JCAnnotation> annots = copy(t.annots, p); + JCExpression packageId = copy(t.packageId); + return M.at(t.pos).Package(annots, packageId); + } + public JCTree visitOther(Tree node, P p) { JCTree tree = (JCTree) node; switch (tree.getTag()) {
--- a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Tue May 07 17:14:17 2013 -0700 @@ -35,6 +35,7 @@ import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; +import javax.tools.JavaFileObject; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.TypeTag.BOT; import static com.sun.tools.javac.tree.JCTree.Tag.*; @@ -470,6 +471,16 @@ return getStartPos(node.vartype); } } + case PACKAGE: { + JCPackageDecl node = (JCPackageDecl)tree; + if (node.annots.nonEmpty()) + return getStartPos(node.annots.head); + break; + } + case MODULE_ID: { + JCModuleId node = (JCModuleId)tree; + return getStartPos(node.qualId); + } case ERRONEOUS: { JCErroneous node = (JCErroneous)tree; if (node.errs != null && node.errs.nonEmpty()) @@ -620,26 +631,32 @@ public static JCTree declarationFor(final Symbol sym, final JCTree tree) { class DeclScanner extends TreeScanner { JCTree result = null; + @Override public void scan(JCTree tree) { if (tree!=null && result==null) tree.accept(this); } + @Override public void visitTopLevel(JCCompilationUnit that) { if (that.packge == sym) result = that; else super.visitTopLevel(that); } + @Override public void visitClassDef(JCClassDecl that) { if (that.sym == sym) result = that; else super.visitClassDef(that); } + @Override public void visitMethodDef(JCMethodDecl that) { if (that.sym == sym) result = that; else super.visitMethodDef(that); } + @Override public void visitVarDef(JCVariableDecl that) { if (that.sym == sym) result = that; else super.visitVarDef(that); } + @Override public void visitTypeParameter(JCTypeParameter that) { if (that.type != null && that.type.tsym == sym) result = that; else super.visitTypeParameter(that); @@ -669,6 +686,7 @@ } class PathFinder extends TreeScanner { List<JCTree> path = List.nil(); + @Override public void scan(JCTree tree) { if (tree != null) { path = path.prepend(tree); @@ -1115,4 +1133,40 @@ finder.scan(e); return finder.foundTypeAnno; } + + public static boolean isModuleInfo(JCCompilationUnit tree) { + return tree.sourcefile.isNameCompatible("module-info", JavaFileObject.Kind.SOURCE); + } + + public static JCModuleDecl getModule(JCCompilationUnit t) { + for (JCTree def: t.defs) { + switch (def.getTag()) { + case IMPORT: + continue; + case MODULE: + return (JCModuleDecl) def; + default: + break; + } + } + return null; + } + + public static boolean isPackageInfo(JCCompilationUnit tree) { + return tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE); + } + + public static JCPackageDecl getPackage(JCCompilationUnit t) { + for (JCTree def: t.defs) { + switch (def.getTag()) { + case IMPORT: + continue; + case PACKAGE: + return (JCPackageDecl) def; + default: + break; + } + } + return null; + } }
--- a/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Tue May 07 17:14:17 2013 -0700 @@ -25,12 +25,13 @@ package com.sun.tools.javac.tree; +import com.sun.source.tree.RequiresFlag; + import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; - import com.sun.tools.javac.tree.JCTree.*; import static com.sun.tools.javac.code.Flags.*; @@ -119,19 +120,18 @@ * Create given tree node at current position. * @param defs a list of ClassDef, Import, and Skip */ - public JCCompilationUnit TopLevel(List<JCAnnotation> packageAnnotations, - JCExpression pid, - List<JCTree> defs) { - Assert.checkNonNull(packageAnnotations); + public JCCompilationUnit TopLevel(List<JCTree> defs) { for (JCTree node : defs) Assert.check(node instanceof JCClassDecl || node instanceof JCImport + || node instanceof JCPackageDecl + || node instanceof JCModuleDecl || node instanceof JCSkip || node instanceof JCErroneous || (node instanceof JCExpressionStatement && ((JCExpressionStatement)node).expr instanceof JCErroneous), node.getClass().getSimpleName()); - JCCompilationUnit tree = new JCCompilationUnit(packageAnnotations, pid, defs, + JCCompilationUnit tree = new JCCompilationUnit(defs, null, null, null, null); tree.pos = pos; return tree; @@ -523,6 +523,91 @@ return Modifiers(flags, List.<JCAnnotation>nil()); } + @Override + public JCModuleDecl Module(JCModuleId moduleId, + List<JCModuleDirective> directives, Name metadata) { + JCModuleDecl tree = new JCModuleDecl(moduleId, directives, metadata); + tree.pos = pos; + return tree; + } + + @Override + public JCViewDecl View(JCExpression name, + List<JCModuleDirective> directives) { + JCViewDecl tree = new JCViewDecl(name, directives); + tree.pos = pos; + return tree; + } + + @Override + public JCEntrypointDirective Entrypoint(JCExpression qualId) { + JCEntrypointDirective tree = new JCEntrypointDirective(qualId); + tree.pos = pos; + return tree; + } + + @Override + public JCExportDirective Exports(JCExpression qualId) { + JCExportDirective tree = new JCExportDirective(qualId); + tree.pos = pos; + return tree; + } + + @Override + public JCModuleId ModuleId(JCTree qualId, Name version) { + JCModuleId tree = new JCModuleId(qualId, version); + tree.pos = pos; + return tree; + } + + @Override + public JCModuleQuery ModuleQuery(JCTree qualId, Name versionQuery) { + JCModuleQuery tree = new JCModuleQuery(qualId, versionQuery); + tree.pos = pos; + return tree; + } + + @Override + public JCPermitsDirective Permits(JCExpression qualId) { + JCPermitsDirective tree = new JCPermitsDirective(qualId); + tree.pos = pos; + return tree; + } + + @Override + public JCProvidesModuleDirective ProvidesModule(JCModuleId moduleId) { + JCProvidesModuleDirective tree = new JCProvidesModuleDirective(moduleId); + tree.pos = pos; + return tree; + } + + @Override + public JCProvidesServiceDirective ProvidesService(JCExpression service, JCExpression impl) { + JCProvidesServiceDirective tree = new JCProvidesServiceDirective(service, impl); + tree.pos = pos; + return tree; + } + + @Override + public JCRequiresModuleDirective RequiresModule(List<RequiresFlag> flags, JCModuleQuery moduleQuery) { + JCRequiresModuleDirective tree = new JCRequiresModuleDirective(flags, moduleQuery); + tree.pos = pos; + return tree; + } + + @Override + public JCRequiresServiceDirective RequiresService(List<RequiresFlag> flags, JCExpression serviceName) { + JCRequiresServiceDirective tree = new JCRequiresServiceDirective(flags, serviceName); + tree.pos = pos; + return tree; + } + + public JCPackageDecl Package(List<JCAnnotation> annots, JCExpression packageId) { + JCPackageDecl tree = new JCPackageDecl(annots, packageId); + tree.pos = pos; + return tree; + } + public JCAnnotatedType AnnotatedType(List<JCAnnotation> annotations, JCExpression underlyingType) { JCAnnotatedType tree = new JCAnnotatedType(annotations, underlyingType); tree.pos = pos;
--- a/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java Tue May 07 17:14:17 2013 -0700 @@ -46,7 +46,8 @@ /** Visitor method: Scan a single node. */ public void scan(JCTree tree) { - if(tree!=null) tree.accept(this); + if (tree != null) + tree.accept(this); } /** Visitor method: scan a list of nodes. @@ -62,12 +63,73 @@ * Visitor methods ****************************************************************************/ + @Override public void visitTopLevel(JCCompilationUnit tree) { - scan(tree.packageAnnotations); - scan(tree.pid); scan(tree.defs); } + @Override + public void visitModuleDef(JCModuleDecl tree) { + scan(tree.id); + scan(tree.directives); + } + + @Override + public void visitModuleId(JCModuleId tree) { + scan(tree.qualId); + } + + @Override + public void visitModuleQuery(JCModuleQuery tree) { + scan(tree.qualId); + } + + @Override + public void visitEntrypoint(JCEntrypointDirective tree) { + scan(tree.qualId); + } + + @Override + public void visitExports(JCExportDirective tree) { + scan(tree.qualid); + } + + @Override + public void visitPermits(JCPermitsDirective tree) { + scan(tree.moduleName); + } + + @Override + public void visitProvidesModule(JCProvidesModuleDirective tree) { + scan(tree.moduleId); + } + + @Override + public void visitProvidesService(JCProvidesServiceDirective tree) { + scan(tree.serviceName); + scan(tree.implName); + } + + @Override + public void visitRequiresModule(JCRequiresModuleDirective tree) { + scan(tree.moduleQuery); + } + + @Override + public void visitRequiresService(JCRequiresServiceDirective tree) { + scan(tree.serviceName); + } + + @Override + public void visitView(JCViewDecl tree) { + scan(tree.directives); + } + + public void visitPackageDef(JCPackageDecl tree) { + scan(tree.annots); + scan(tree.packageId); + } + public void visitImport(JCImport tree) { scan(tree.qualid); }
--- a/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java Tue May 07 17:14:17 2013 -0700 @@ -116,11 +116,15 @@ ****************************************************************************/ public void visitTopLevel(JCCompilationUnit tree) { - tree.pid = translate(tree.pid); tree.defs = translate(tree.defs); result = tree; } + public void visitPackageDef(JCPackageDecl tree) { + tree.packageId = translate(tree.packageId); + result = tree; + } + public void visitImport(JCImport tree) { tree.qualid = translate(tree.qualid); result = tree;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/javac/util/Debug.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.util; + +import java.io.PrintWriter; +import java.util.HashSet; +import java.util.Set; + +public class Debug { + static final boolean ALLOW_OPTION = true; + static final boolean ALLOW_SYSPROP = true; + static final boolean ALLOW_ENVVAR = true; + + public final PrintWriter out; + Set<String> opts; + + public Debug(String name, Options options, Log log) { + this(name, options, log.noticeWriter); + } + + public Debug(String name, Options options, PrintWriter out) { + if (out == null) out = new PrintWriter(System.err); + this.out = new DebugPrinter(name, out); + + if (ALLOW_OPTION && options != null) { + String v = options.get(name + ".debug"); + if (v != null) + setOpts("all"); + String prefix = name + ".debug:"; + for (String k: options.keySet()) { + if (k.startsWith(prefix)) + setOpts(k.substring(prefix.length())); + } + } + + try { + if (opts == null && ALLOW_SYSPROP) + setOpts(System.getProperty("javac." + name + ".debug")); + } catch (SecurityException e) { + // ignore + } + + try { + if (opts == null && ALLOW_ENVVAR) + setOpts(System.getenv("_JAVAC_" + name.toUpperCase() + "_DEBUG")); + } catch (SecurityException e) { + // ignore + } + } + + public boolean isEnabled() { + return (opts != null); + } + + public boolean isEnabled(String opt) { + if (opts == null) + return false; + + return opts.contains(opt) || + (opts.contains("all") && !opts.contains("-" + opt)); + } + + public void print(Object o) { + out.print(o); + } + + public void print(String s) { + out.print(s); + } + + public void println(Object o) { + out.println(o); + out.flush(); + } + + public void println(String s) { + out.println(s); + out.flush(); + } + + public void println() { + out.println(); + out.flush(); + } + + void setOpts(String list) { + if (list == null) + return; + if (list.equals("true")) // common value for sys props and env vars + list = "all"; + for (String opt: list.split("[\\s,]+")) { + if (opt.isEmpty()) + continue; + if (opts == null) + opts = new HashSet<String>(); + opts.add(opt); + } + } + + static class DebugPrinter extends PrintWriter { + final String name; + boolean needLinePrefix = true; + + DebugPrinter(String name, PrintWriter out) { + super(out); + this.name = name; + } + + @Override + public void write(int c) { + checkLinePrefix(); + super.write(c); + } + + @Override + public void write(String s, int off, int len) { + if (len > 0) { + checkLinePrefix(); + super.write(s, off, len); + } + } + + @Override + public void println() { + super.println(); + needLinePrefix = true; + } + + private void checkLinePrefix() { + if (needLinePrefix) { + needLinePrefix = false; + write("[" + name + "] "); + } + } + } +}
--- a/src/share/classes/com/sun/tools/javac/util/Names.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/util/Names.java Tue May 07 17:14:17 2013 -0700 @@ -50,6 +50,7 @@ // operators and punctuation public final Name asterisk; public final Name comma; + public final Name double_asterisk; public final Name empty; public final Name hyphen; public final Name one; @@ -61,8 +62,20 @@ // keywords public final Name _class; public final Name _default; + public final Name _public; public final Name _super; public final Name _this; + public final Name exports; + public final Name local; + public final Name main; + public final Name module; + public final Name optional; + public final Name permits; + public final Name provides; + public final Name requires; + public final Name service; + public final Name view; + public final Name with; // field and method names public final Name _name; @@ -116,6 +129,10 @@ // package names public final Name java_lang; + // module names + public final Name java_base; + public final Name jdk_legacy; + // attribute names public final Name Annotation; public final Name AnnotationDefault; @@ -134,6 +151,10 @@ public final Name LocalVariableTable; public final Name LocalVariableTypeTable; public final Name MethodParameters; + public final Name Module; + public final Name ModuleData; + public final Name ModuleProvides; + public final Name ModuleRequires; public final Name RuntimeInvisibleAnnotations; public final Name RuntimeInvisibleParameterAnnotations; public final Name RuntimeInvisibleTypeAnnotations; @@ -170,6 +191,7 @@ public final Name T; public final Name deprecated; public final Name ex; + public final Name module_info; public final Name package_info; //lambda-related @@ -186,6 +208,7 @@ // operators and punctuation asterisk = fromString("*"); comma = fromString(","); + double_asterisk = fromString("**"); empty = fromString(""); hyphen = fromString("-"); one = fromString("1"); @@ -197,8 +220,20 @@ // keywords _class = fromString("class"); _default = fromString("default"); + _public = fromString("public"); _super = fromString("super"); _this = fromString("this"); + exports = fromString("exports"); + local = fromString("local"); + main = fromString("main"); + module = fromString("module"); + optional = fromString("optional"); + permits = fromString("permits"); + provides = fromString("provides"); + requires = fromString("requires"); + service = fromString("service"); + view = fromString("view"); + with = fromString("with"); // field and method names _name = fromString("name"); @@ -252,6 +287,10 @@ // package names java_lang = fromString("java.lang"); + // module names + java_base = fromString("java.base"); + jdk_legacy = fromString("jdk"); // FIXME: update when alias support working + // attribute names Annotation = fromString("Annotation"); AnnotationDefault = fromString("AnnotationDefault"); @@ -270,6 +309,10 @@ LocalVariableTable = fromString("LocalVariableTable"); LocalVariableTypeTable = fromString("LocalVariableTypeTable"); MethodParameters = fromString("MethodParameters"); + Module = fromString("Module"); + ModuleData = fromString("ModuleData"); + ModuleProvides = fromString("ModuleProvides"); + ModuleRequires = fromString("ModuleRequires"); RuntimeInvisibleAnnotations = fromString("RuntimeInvisibleAnnotations"); RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations"); RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations"); @@ -306,6 +349,7 @@ T = fromString("T"); deprecated = fromString("deprecated"); ex = fromString("ex"); + module_info = fromString("module-info"); package_info = fromString("package-info"); //lambda-related
--- a/src/share/classes/com/sun/tools/javadoc/JavadocTool.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javadoc/JavadocTool.java Tue May 07 17:14:17 2013 -0700 @@ -134,7 +134,7 @@ docenv.setEncoding(encoding); docenv.docClasses = docClasses; docenv.legacyDoclet = legacyDoclet; - javadocReader.sourceCompleter = docClasses ? null : this; + javadocReader.sourceCompleter = docClasses ? null : new Completer(); ListBuffer<String> names = new ListBuffer<String>(); ListBuffer<JCCompilationUnit> classTrees = new ListBuffer<JCCompilationUnit>();
--- a/src/share/classes/com/sun/tools/javap/AttributeWriter.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javap/AttributeWriter.java Tue May 07 17:14:17 2013 -0700 @@ -47,6 +47,10 @@ import com.sun.tools.classfile.LocalVariableTable_attribute; import com.sun.tools.classfile.LocalVariableTypeTable_attribute; import com.sun.tools.classfile.MethodParameters_attribute; +import com.sun.tools.classfile.ModuleData_attribute; +import com.sun.tools.classfile.ModuleProvides_attribute; +import com.sun.tools.classfile.ModuleRequires_attribute; +import com.sun.tools.classfile.Module_attribute; import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute; import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; @@ -389,6 +393,109 @@ return null; } + public Void visitModule(Module_attribute attr, Void ignore) { + println("Module: " + constantWriter.stringValue(attr.module_id_index)); + return null; + } + + String getModuleName(Module_attribute attr) { + try { + return attr.getModuleName(constant_pool); + } catch (ConstantPoolException e) { + return report(e); + } + } + + public Void visitModuleData(ModuleData_attribute attr, Void ignore) { + println("ModuleData: "); + indent(+1); + println("#" + attr.data_index + + "\t// " + constantWriter.stringValue(attr.data_index)); + indent(-1); + return null; + } + + public Void visitModuleProvides(ModuleProvides_attribute attr, Void ignore) { + println("ModuleProvides: "); + indent(+1); + for (int i = 0; i < attr.view_table.length; i++) { + println("View " + i); + indent(+1); + ModuleProvides_attribute.View v = attr.view_table[i]; + String view_name = (v.view_name_index == 0) + ? "(default)" : constantWriter.stringValue(v.view_name_index); + println("#" + v.view_name_index + "\t// view " + view_name); + String entrypoint_name = (v.entrypoint_index == 0) + ? "(none)" : constantWriter.stringValue(v.entrypoint_index); + println("#" + v.entrypoint_index + "\t// class " + entrypoint_name); + println(v.alias_length + "\t// aliases "); + indent(+1); + for (int ai = 0; ai < v.alias_length; ai++) { + int a = v.alias_table[ai]; + println(a + "\t// provides " + constantWriter.stringValue(a)); + } + indent(-1); + println(v.service_length + "\t// services "); + indent(+1); + for (int si = 0; si < v.service_length; si++) { + ModuleProvides_attribute.Service s = v.service_table[si]; + println("#" + s.service_index + ", " + "#" + s.impl_index + +"\t// provides service " + constantWriter.stringValue(s.service_index) + + " with " + constantWriter.stringValue(s.impl_index)); + } + indent(-1); + println(v.export_length + "\t// exports "); + indent(+1); + for (int ei = 0; ei < v.export_length; ei++) { + int e = v.export_table[ei]; + println("#" + e + "\t// exports " + constantWriter.stringValue(e)); + } + indent(-1); + println(v.permit_length + "\t// permits "); + indent(+1); + for (int pi = 0; pi < v.permit_length; pi++) { + int p = v.permit_table[pi]; + println("#" + p +"\t// permits " + constantWriter.stringValue(p)); + } + indent(-1); // end of permits + indent(-1); // end of ModuleProvides + } + indent(-1); + return null; + } + + public Void visitModuleRequires(ModuleRequires_attribute attr, Void ignore) { + println("ModuleRequires: "); + indent(+1); + writeRequiresTable(attr.module_table, false); + writeRequiresTable(attr.service_table, true); + indent(-1); + return null; + } + + protected void writeRequiresTable(ModuleRequires_attribute.Entry[] entries, + boolean service) { + println(entries.length + "\t// " + (service ? "services" : "modules")); + indent(+1); + for (ModuleRequires_attribute.Entry e: entries) { + print("#" + e.index + "," + String.format("%x", e.flags)+ "\t// requires"); + if ((e.flags & ModuleRequires_attribute.ACC_OPTIONAL) != 0) + print(" optional"); + if ((e.flags & ModuleRequires_attribute.ACC_LOCAL) != 0) + print(" local"); + if ((e.flags & ModuleRequires_attribute.ACC_REEXPORT) != 0) + print(" public"); + if ((e.flags & ModuleRequires_attribute.ACC_SYNTHETIC) != 0) + print(" synthetic"); + if ((e.flags & ModuleRequires_attribute.ACC_SYNTHESIZED) != 0) + print(" synthesized"); + if (service) + print(" service"); + println(" " + constantWriter.stringValue(e.index)); + } + indent(-1); + } + private static final String format = "%-31s%s"; public Void visitMethodParameters(MethodParameters_attribute attr,
--- a/src/share/classes/com/sun/tools/javap/ClassWriter.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javap/ClassWriter.java Tue May 07 17:14:17 2013 -0700 @@ -202,13 +202,16 @@ if (options.verbose) { println(); indent(+1); - attrWriter.write(cf, cf.attributes, constant_pool); + if (options.compat) + attrWriter.write(cf, cf.attributes, constant_pool); println("minor version: " + cf.minor_version); println("major version: " + cf.major_version); if (!options.compat) writeList("flags: ", flags.getClassFlags(), "\n"); indent(-1); constantWriter.writeConstantPool(); + if (!options.compat) + attrWriter.write(cf, cf.attributes, constant_pool); } else { print(" "); }
--- a/src/share/classes/com/sun/tools/javap/ConstantWriter.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javap/ConstantWriter.java Tue May 07 17:14:17 2013 -0700 @@ -51,7 +51,6 @@ super(context); context.put(ConstantWriter.class, this); classWriter = ClassWriter.instance(context); - options = Options.instance(context); } protected void writeConstantPool() { @@ -109,6 +108,20 @@ return 2; } + public Integer visitModuleId(CONSTANT_ModuleId_info info, Void p) { + print("#" + info.name_index + ":#" + info.version_index); + tab(); + println("// " + stringValue(info)); + return 1; + } + + public Integer visitModuleQuery(CONSTANT_ModuleQuery_info info, Void p) { + print("#" + info.name_index + ":#" + info.version_index); + tab(); + println("// " + stringValue(info)); + return 1; + } + public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) { print("#" + info.name_index + ":#" + info.type_index); tab(); @@ -234,6 +247,8 @@ return "InvokeDynamic"; case CONSTANT_NameAndType: return "NameAndType"; + case CONSTANT_ModuleId: + return "ModuleId"; default: return "(unknown tag " + tag + ")"; } @@ -248,6 +263,16 @@ } } + String stringValues(int[] constant_pool_indices, String sep) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < constant_pool_indices.length; i++) { + if (i > 0) + sb.append(sep); + sb.append(stringValue(constant_pool_indices[i])); + } + return sb.toString(); + } + String stringValue(CPInfo cpInfo) { return stringValueVisitor.visit(cpInfo); } @@ -304,6 +329,52 @@ return info.value + "l"; } + public String visitModuleId(CONSTANT_ModuleId_info info, Void p) { + if (info.version_index == 0) + return getCheckedName(info); + else + return getCheckedName(info) + "@" + getCheckedVersion(info); + } + + String getCheckedName(CONSTANT_ModuleId_info info) { + try { + return checkName(info.getName()); + } catch (ConstantPoolException e) { + return report(e); + } + } + + String getCheckedVersion(CONSTANT_ModuleId_info info) { + try { + return info.getVersion(); + } catch (ConstantPoolException e) { + return report(e); + } + } + + public String visitModuleQuery(CONSTANT_ModuleQuery_info info, Void p) { + if (info.version_index == 0) + return getCheckedName(info); + else + return getCheckedName(info) + "@" + getCheckedVersion(info); + } + + String getCheckedName(CONSTANT_ModuleQuery_info info) { + try { + return checkName(info.getName()); + } catch (ConstantPoolException e) { + return report(e); + } + } + + String getCheckedVersion(CONSTANT_ModuleQuery_info info) { + try { + return info.getVersion(); + } catch (ConstantPoolException e) { + return report(e); + } + } + public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) { return getCheckedName(info) + ":" + getType(info); } @@ -450,5 +521,4 @@ } private ClassWriter classWriter; - private Options options; }
--- a/src/share/classes/com/sun/tools/javap/JavapTask.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javap/JavapTask.java Tue May 07 17:14:17 2013 -0700 @@ -444,7 +444,7 @@ handleOptions(args); // the following gives consistent behavior with javac - if (classes == null || classes.size() == 0) { + if (classes == null || classes.isEmpty()) { if (options.help || options.version || options.fullVersion) return EXIT_OK; else @@ -531,7 +531,7 @@ throw new BadArgs("err.incompatible.options", sb); } - if ((classes == null || classes.size() == 0) && + if ((classes == null || classes.isEmpty()) && !(noArgs || options.help || options.version || options.fullVersion)) { throw new BadArgs("err.no.classes.specified"); } @@ -573,7 +573,7 @@ } public boolean run() { - if (classes == null || classes.size() == 0) + if (classes == null || classes.isEmpty()) return false; context.put(PrintWriter.class, log);
--- a/src/share/classes/com/sun/tools/javap/resources/javap.properties Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/com/sun/tools/javap/resources/javap.properties Tue May 07 17:14:17 2013 -0700 @@ -1,5 +1,5 @@ -err.prefix=Error: +err.prefix=Error: err.bad.constant.pool=error while reading constant pool for {0}: {1} err.class.not.found=class not found: {0}
--- a/src/share/classes/javax/lang/model/element/Modifier.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/javax/lang/model/element/Modifier.java Tue May 07 17:14:17 2013 -0700 @@ -64,7 +64,8 @@ /** The modifier {@code volatile} */ VOLATILE, /** The modifier {@code synchronized} */ SYNCHRONIZED, /** The modifier {@code native} */ NATIVE, - /** The modifier {@code strictfp} */ STRICTFP; + /** The modifier {@code strictfp} */ STRICTFP, + /** The modifier {@code module} */ MODULE; /** * Returns this modifier's name in lowercase.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/javax/lang/model/element/ModuleElement.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.lang.model.element; + +/** Interim API. */ +public interface ModuleElement extends Element { + + // consider using java.lang.module.ModuleId + interface ModuleId { + CharSequence getName(); + CharSequence getVersion(); + } + + // consider using java.lang.module.ModuleIdQuery + interface ModuleQuery { + CharSequence getName(); + CharSequence getVersionQuery(); + } + + ModuleId getModuleId(); + +}
--- a/src/share/classes/javax/lang/model/type/TypeKind.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/javax/lang/model/type/TypeKind.java Tue May 07 17:14:17 2013 -0700 @@ -134,6 +134,12 @@ EXECUTABLE, /** + * A pseudo-type corresponding to a module element. + * @see NoType + */ + MODULE, + + /** * An implementation-reserved type. * This is not the type you are looking for. */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/javax/tools/ExtendedLocation.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.tools; + +import java.io.IOException; +import java.util.Set; + +/** + * A location that can list its contents. + * @author jjg + */ +public interface ExtendedLocation extends JavaFileManager.Location { + + + /** + * List the contents of this location. + * @param packageName a package name + * @param kinds return objects only of these kinds + * @param recurse if true include "subpackages" + * @return an Iterable of file objects matching the given criteria + * @throws IOException if an I/O error occurred + * @see JavaFileManager#list + */ + Iterable<JavaFileObject> list(String packageName, + Set<JavaFileObject.Kind> kinds, + boolean recurse) + throws IOException; + + /** + * Infers a binary name of a file object returned from this location. + * + * @param file a file object + * @return a binary name or {@code null} if the file object is not + * found in this location + * @see JavaFileManager#inferBinaryName + */ + String inferBinaryName(JavaFileObject file); +}
--- a/src/share/classes/javax/tools/FileObject.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/javax/tools/FileObject.java Tue May 07 17:14:17 2013 -0700 @@ -32,6 +32,8 @@ import java.io.Writer; import java.net.URI; +import javax.tools.JavaFileManager.Location; + /** * File abstraction for tools. In this context, <em>file</em> means * an abstraction of regular files and other sources of data. For @@ -49,6 +51,12 @@ * @since 1.6 */ public interface FileObject { + /** + * Interface to be provided by file objects that can return their location. + */ + interface Locatable { + Location getLocation(); + } /** * Returns a URI identifying this file object.
--- a/src/share/classes/javax/tools/JavaFileManager.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/javax/tools/JavaFileManager.java Tue May 07 17:14:17 2013 -0700 @@ -177,7 +177,7 @@ * * @param location a location * @param file a file object - * @return a binary name or {@code null} the file object is not + * @return a binary name or {@code null} if the file object is not * found in the given location * @throws IllegalStateException if {@link #close} has been called * and this file manager cannot be reopened
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/javax/tools/ModuleFileManager.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.tools; + +public interface ModuleFileManager extends JavaFileManager { + class InvalidLocationException extends IllegalArgumentException { + private static final long serialVersionUID = 2115919242510692026L; + } + + class InvalidFileObjectException extends IllegalArgumentException { + private static final long serialVersionUID = 1234906668846471087L; + } + + enum ModuleMode { SINGLE, MULTIPLE }; + + /** + * Determine if the file manager is running in "single module mode" + * or "multiple module mode". This affects how files are written to + * the class output directory. + * Multiple module mode is active if a module path has been set, + * but not a class path. + */ + ModuleMode getModuleMode(); + + /** + * Get a location representing the "container" for a file object + * for a compilation unit in a given package. + */ + Location getModuleLocation(Location location, JavaFileObject fo, String packageName) + throws IllegalArgumentException; + + /** + * Get the set of "module locations" available on a "module path", + * where each "module location" is determined by the existence of + * a subdirectory on the path containing a module-info file. + */ + Iterable<? extends Location> getModuleLocations(Location location); + + /** + * Join a set of locations into a "search path". + */ + Location join(Iterable<? extends Location> locations); +}
--- a/src/share/classes/javax/tools/StandardLocation.java Thu Apr 25 09:24:40 2013 -0700 +++ b/src/share/classes/javax/tools/StandardLocation.java Tue May 07 17:14:17 2013 -0700 @@ -72,7 +72,12 @@ * Location of new native header files. * @since 1.8 */ - NATIVE_HEADER_OUTPUT; + NATIVE_HEADER_OUTPUT, + + /** + * Location to search for existing module class files. + */ + MODULE_PATH; /** * Gets a location object with the given name. The following
--- a/test/Makefile Thu Apr 25 09:24:40 2013 -0700 +++ b/test/Makefile Tue May 07 17:14:17 2013 -0700 @@ -225,6 +225,17 @@ JCK_COMPILER_OUTPUT_DIR = $(ABS_TEST_OUTPUT_DIR)/jck-compiler JCK_RUNTIME_OUTPUT_DIR = $(ABS_TEST_OUTPUT_DIR)/jck-runtime-Xcompile +PROBLEM_LISTS=ModulesProblemList.txt +EXCLUDELIST=$(ABS_TEST_OUTPUT_DIR)/excludelist.txt + +ifdef NO_EXCLUDES +$(EXCLUDELIST): $(PROBLEM_LISTS) + @echo "NOTHING_EXCLUDED" > $@ +else +$(EXCLUDELIST): $(PROBLEM_LISTS) + @cat $(PROBLEM_LISTS) > $@ +endif + # Default make rule -- warning, may take a while all: $(JPRT_CLEAN) jtreg-tests jck-compiler-tests jck-runtime-tests $(JPRT_ARCHIVE_BUNDLE) all-summary @echo "Testing completed successfully" @@ -266,7 +277,7 @@ # (Optional) reference results (e.g. work, report or summary.txt) # jtreg_tests: jtreg-tests -jtreg-tests: check-jtreg FRC +jtreg-tests: check-jtreg $(EXCLUDELIST) FRC @rm -f -r $(JTREG_OUTPUT_DIR)/JTwork $(JTREG_OUTPUT_DIR)/JTreport \ $(JTREG_OUTPUT_DIR)/diff.html $(JTREG_OUTPUT_DIR)/status.txt @mkdir -p $(JTREG_OUTPUT_DIR) @@ -277,6 +288,7 @@ -r:$(JTREG_OUTPUT_DIR)/JTreport \ -w:$(JTREG_OUTPUT_DIR)/JTwork \ -jdk:$(TESTJAVA) \ + -exclude:$(EXCLUDELIST) \ $(JAVA_ARGS:%=-vmoption:%) \ $(JTREG_OPTIONS) \ $(JTREG_TESTDIRS) \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/ModulesProblemList.txt Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,135 @@ +########################################################################### +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +############################################################################ +# jigsaw legacy image +tools/javac/6302184/T6302184.sh generic-all + +# AsssertionError - package-info.class not found +tools/javac/TestPkgInfo.java generic-all + +# new module-compilation-related message keys are not in the resource bundle +tools/javac/diags/CheckExamples.java generic-all +tools/javac/diags/CheckResourceKeys.java generic-all +tools/javac/diags/MessageInfo.java generic-all + +# wrong size found: 8340; expected: 6655 +tools/javac/nio/compileTest/CompileTest.java generic-all + +# AssertionError - unexpected empty block found +tools/javac/parser/ExtraSemiTest.java generic-all + +# Failures in jdk-module-image + +# rt.jar not found +tools/javadoc/6942366/T6942366.java generic-all + +# error - Locale not available: ja +com/sun/javadoc/testHtmlTag/TestHtmlTag.java generic-all + +# bootclasspath and module content (classes) +tools/javac/api/T6430241.java generic-all +tools/javac/Paths/Diagnostics.sh generic-all + +# sun.misc.Lock is in compat module +tools/javac/warnings/6594914/T6594914b.java generic-all + +############################################################################ +# Following test failures need further investigation + +# Tests timeout + +tools/javac/T7093325.java generic-all +tools/javac/TryWithResources/InterruptedExceptionTest.java generic-all +tools/javac/api/TestContainTypes.java generic-all +tools/javac/failover/CheckAttributedTree.java generic-all +tools/javac/generics/diamond/7030150/GenericConstructorAndDiamondTest.java generic-all +tools/javac/generics/diamond/7046778/DiamondAndInnerClassTest.java generic-all +tools/javac/generics/inference/7086601/T7086601b.java generic-all +tools/javac/generics/rawOverride/7062745/GenericOverrideTest.java generic-all +tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java generic-all +tools/javac/processing/TestWarnErrorCount.java generic-all +tools/javac/varargs/6199075/T6199075.java generic-all +tools/javac/varargs/7042566/T7042566.java generic-all +tools/javac/varargs/warning/Warn4.java generic-all +tools/javac/varargs/warning/Warn5.java generic-all +tools/javac/versions/check.sh generic-all + +############################################################################ + +# Need to investigate what javac needs to do for classpath mode + +com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java generic-all +com/sun/javadoc/testPackageDeprecation/TestPackageDeprecation.java generic-all +tools/javac/4846262/Test.sh generic-all +tools/javac/6589361/T6589361.java generic-all +tools/javac/EarlyAssert.java generic-all +tools/javac/Paths/MineField.sh generic-all +tools/javac/T6351767.java generic-all +tools/javac/T6705935.java generic-all +tools/javac/T6725036.java generic-all +tools/javac/T6993301.java generic-all +tools/javac/annotations/TestAnnotationPackageInfo.java generic-all +tools/javac/api/6411310/T6411310.java generic-all +tools/javac/api/6411333/T6411333.java generic-all +tools/javac/api/6431257/T6431257.java generic-all +tools/javac/api/6437349/T6437349.java generic-all +tools/javac/api/6598108/T6598108.java generic-all +tools/javac/api/6608214/T6608214.java generic-all +tools/javac/api/TestClientCodeWrapper.java generic-all +tools/javac/api/TestEvalExpression.java generic-all +tools/javac/api/guide/Test.java generic-all +tools/javac/modules/RequiresModuleTest02.java generic-all +tools/javac/parser/JavacParserTest.java generic-all +tools/javac/processing/6348193/T6348193.java generic-all +tools/javac/processing/6378728/T6378728.java generic-all +tools/javac/processing/T6920317.java generic-all +tools/javac/processing/errors/TestReturnCode.java generic-all +tools/javac/processing/messager/MessagerDiags.java generic-all +tools/javac/processing/model/TestSymtabItems.java generic-all +tools/javac/processing/model/testgetallmembers/Main.java generic-all +tools/javac/tree/DocCommentToplevelTest.java generic-all +tools/javac/tree/MakeLiteralTest.java generic-all +tools/javac/tree/TreeKindTest.java generic-all +tools/javac/tree/TreePosTest.java generic-all +tools/javac/types/BoxingConversionTest.java generic-all +tools/javac/types/CastTest.java generic-all +tools/javac/types/GenericTypeWellFormednessTest.java generic-all +tools/javac/types/PrimitiveConversionTest.java generic-all +tools/javadoc/6227454/Test.java generic-all +tools/javadoc/6964914/Test.java generic-all +tools/javadoc/6964914/TestStdDoclet.java generic-all +tools/javadoc/6964914/TestUserDoclet.java generic-all +tools/javadoc/annotations/annotatePackage/Main.java generic-all +tools/javah/T6893943.java generic-all +tools/javap/6937244/T6937244.java generic-all +tools/javap/T4880672.java generic-all +tools/javap/T4884240.java generic-all +tools/javap/T4975569.java generic-all +tools/javap/T6729471.java generic-all +tools/javap/T6863746.java generic-all +tools/javap/T6866657.java generic-all +tools/javap/T6980017.java generic-all
--- a/test/TEST.ROOT Thu Apr 25 09:24:40 2013 -0700 +++ b/test/TEST.ROOT Tue May 07 17:14:17 2013 -0700 @@ -3,4 +3,4 @@ # DO NOT EDIT without first contacting jdk-regtest@sun.com. # The list of keywords supported in the entire test suite -keys=2d dnd i18n +keys=jigsaw
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/4846262/Test.sh Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,81 @@ +#!/bin/sh -f + +# +# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# +# @test +# @bug 4846262 +# @summary check that javac operates correctly in EBCDIC locale + +set -x + +if [ "${TESTSRC}" = "" ] +then + echo "TESTSRC not set. Test cannot execute. Failed." + exit 1 +fi +echo "TESTSRC=${TESTSRC}" +if [ "${TESTJAVA}" = "" ] +then + echo "TESTJAVA not set. Test cannot execute. Failed." + exit 1 +fi + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + SunOS | Linux | Darwin ) + FS="/" + ;; + CYGWIN* ) + FS="/" + DIFFOPTS="--strip-trailing-cr" + ;; + Windows* ) + FS="\\" + ;; + * ) + echo "Unrecognized system!" + exit 1; + ;; +esac + +rm -f Test.java Test.out + +"${TESTJAVA}${FS}bin${FS}native2ascii" ${TESTTOOLVMOPTS} -reverse -encoding IBM1047 ${TESTSRC}${FS}Test.java Test.java + +"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -J-Duser.language=en -J-Duser.region=US -J-Dfile.encoding=IBM1047 Test.java 2>Test.tmp + +"${TESTJAVA}${FS}bin${FS}native2ascii" ${TESTTOOLVMOPTS} -encoding IBM1047 Test.tmp Test.out + +diff ${DIFFOPTS} -c "${TESTSRC}${FS}Test.out" Test.out +result=$? + +if [ $result -eq 0 ] +then + echo "Passed" +else + echo "Failed" +fi +exit $result
--- a/test/tools/javac/4880220/T4880220.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/4880220/T4880220.java Tue May 07 17:14:17 2013 -0700 @@ -3,11 +3,11 @@ * @bug 4880220 * @summary Add a warning when accessing a static method via an reference * - * @compile/ref=T4880220.empty.out T4880220.java - * @compile/ref=T4880220.warn.out -XDrawDiagnostics -Xlint:static T4880220.java - * @compile/ref=T4880220.warn.out -XDrawDiagnostics -Xlint:all T4880220.java - * @compile/ref=T4880220.empty.out -XDrawDiagnostics -Xlint:all,-static T4880220.java - * @compile/ref=T4880220.error.out/fail -XDrawDiagnostics -Werror -Xlint:all T4880220.java + * @compile/ref=T4880220.empty.out T4880220.java + * @compile/ref=T4880220.warn.out -XDrawDiagnostics -Xlint:static T4880220.java + * @compile/ref=T4880220.warn.out -XDrawDiagnostics -Xlint:all,-path T4880220.java + * @compile/ref=T4880220.empty.out -XDrawDiagnostics -Xlint:all,-path,-static T4880220.java + * @compile/ref=T4880220.error.out/fail -XDrawDiagnostics -Werror -Xlint:all,-path T4880220.java */ public class T4880220 {
--- a/test/tools/javac/6508981/TestInferBinaryName.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/6508981/TestInferBinaryName.java Tue May 07 17:14:17 2013 -0700 @@ -32,6 +32,8 @@ import java.io.*; import java.util.*; +import java.util.jar.*; +import java.util.zip.*; import javax.tools.*; import com.sun.tools.javac.file.JavacFileManager; @@ -58,8 +60,15 @@ } void run() throws Exception { + javaHome = new File(System.getProperty("java.home")); + if (javaHome.getName().equals("jre")) + javaHome = javaHome.getParentFile(); + modularJDK = file(javaHome, "lib", "modules", "%jigsaw-library").exists(); + //System.err.println(System.getProperties()); testDirectory(); + testUserJar_ZipArchive(); + testUserJar_ZipFileIndex(); testSymbolArchive(); testZipArchive(); testZipFileIndexArchive(); @@ -69,42 +78,91 @@ } void testDirectory() throws IOException { + String testName = "testDirectory"; String testClassName = "p.A"; JavaFileManager fm = getFileManager("test.classes", USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX); - test("testDirectory", + test(testName, fm, testClassName, "com.sun.tools.javac.file.RegularFileObject"); } + void testUserJar_ZipArchive() throws IOException { + String testName = "testUserJar_ZipArchive"; + String testClassName = "p.A"; + File my_jar = createJar("my.jar", getClasses(p.A.class)); + System.setProperty("my.jar", my_jar.getPath()); + + JavaFileManager fm = + getFileManager("my.jar", USE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX); + test(testName, + fm, testClassName, "com.sun.tools.javac.file.ZipArchive$ZipFileObject"); + } + + void testUserJar_ZipFileIndex() throws IOException { + String testName = "testUserJar_ZipFileIndex"; + String testClassName = "p.A"; + File my_jar = createJar("my.jar", getClasses(p.A.class)); + System.setProperty("my.jar", my_jar.getPath()); + + JavaFileManager fm = + getFileManager("my.jar", USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX); + test(testName, + fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject"); + } + void testSymbolArchive() throws IOException { + String testName = "testSymbolArchive"; + if (modularJDK && !file(javaHome, "lib", "ct.sym").exists()) { + skip(testName, "modular JDK found with no ct.sym"); + return; + } + String testClassName = "java.lang.String"; JavaFileManager fm = getFileManager("sun.boot.class.path", USE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX); - test("testSymbolArchive", + test(testName, fm, testClassName, "com.sun.tools.javac.file.SymbolArchive$SymbolFileObject"); } void testZipArchive() throws IOException { + String testName = "testZipArchive"; + if (modularJDK) { + skip(testName, "assumes impl for platform classes"); + return; + } + String testClassName = "java.lang.String"; JavaFileManager fm = getFileManager("sun.boot.class.path", IGNORE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX); - test("testZipArchive", + test(testName, fm, testClassName, "com.sun.tools.javac.file.ZipArchive$ZipFileObject"); } void testZipFileIndexArchive() throws IOException { + String testName = "testZipFileIndexArchive"; + if (modularJDK) { + skip(testName, " assumes impl for platform classes"); + return; + } + String testClassName = "java.lang.String"; JavaFileManager fm = getFileManager("sun.boot.class.path", USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX); - test("testZipFileIndexArchive", + test(testName, fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject"); } void testZipFileIndexArchive2() throws IOException { + String testName = "testZipFileIndexArchive2"; + if (modularJDK) { + skip(testName, "assumes impl for platform classes"); + return; + } + String testClassName = "java.lang.String"; JavaFileManager fm = getFileManager("sun.boot.class.path", IGNORE_SYMBOL_FILE, USE_ZIP_FILE_INDEX); - test("testZipFileIndexArchive2", + test(testName, fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject"); } @@ -168,7 +226,64 @@ } } + Map<String,byte[]> getClasses(Class... classes) throws IOException { + ClassLoader cl = getClass().getClassLoader(); + Map<String,byte[]> results = new HashMap<String, byte[]>(); + for (Class c: classes) { + String name = c.getName().replace(".", "/") + ".class"; + byte[] data = read(cl.getResourceAsStream(name)); + results.put(name, data); + } + return results; + } + + byte[] read(InputStream in) throws IOException { + try { + byte[] data = new byte[8192]; + int offset = 0; + int n; + while ((n = in.read(data, offset, data.length - offset)) >= 0) { + offset += n; + if (offset == data.length) + data = Arrays.copyOf(data, 2 * data.length); + } + return data; + } finally { + in.close(); + } + } + + File createJar(String name, Map<String, byte[]> entries) throws IOException { + File jar = new File(name); + OutputStream out = new FileOutputStream(jar); + try { + JarOutputStream jos = new JarOutputStream(out); + for (Map.Entry<String,byte[]> e: entries.entrySet()) { + jos.putNextEntry(new ZipEntry(e.getKey())); + jos.write(e.getValue()); + } + jos.close(); + } finally { + out.close(); + } + return jar; + } + + void skip(String testName, String reason) { + System.err.println(testName + " skipped: " + reason); + } + private int errors; + + File javaHome; + boolean modularJDK; + + static File file(File dir, String... path) { + File f = dir; + for (String p: path) + f = new File(f, p); + return f; + } } class A { }
--- a/test/tools/javac/6508981/p/A.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/6508981/p/A.java Tue May 07 17:14:17 2013 -0700 @@ -21,4 +21,4 @@ * questions. */ package p; -class A { } +public class A { }
--- a/test/tools/javac/6734819/T6734819a.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/6734819/T6734819a.java Tue May 07 17:14:17 2013 -0700 @@ -27,7 +27,7 @@ * @summary Javac performs flows analysis on already translated classes * @author Maurizio Cimadamore * - * @compile/ref=T6734819a.out -XDrawDiagnostics -Xlint:all -XDverboseCompilePolicy T6734819a.java + * @compile/ref=T6734819a.out -XDrawDiagnostics -Xlint:all,-path -XDverboseCompilePolicy T6734819a.java */ class Y extends W {} class W extends Z {}
--- a/test/tools/javac/6734819/T6734819b.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/6734819/T6734819b.java Tue May 07 17:14:17 2013 -0700 @@ -27,7 +27,7 @@ * @summary Javac performs flows analysis on already translated classes * @author Maurizio Cimadamore * - * @compile/ref=T6734819b.out -XDrawDiagnostics -Xlint:all -XDverboseCompilePolicy T6734819b.java + * @compile/ref=T6734819b.out -XDrawDiagnostics -Xlint:all,-path -XDverboseCompilePolicy T6734819b.java */ class A extends B {} class B {
--- a/test/tools/javac/6734819/T6734819c.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/6734819/T6734819c.java Tue May 07 17:14:17 2013 -0700 @@ -4,7 +4,7 @@ * @summary Javac performs flows analysis on already translated classes * @author Maurizio Cimadamore * - * @compile/fail/ref=T6734819c.out -XDrawDiagnostics -Xlint:all -XDverboseCompilePolicy T6734819c.java + * @compile/fail/ref=T6734819c.out -XDrawDiagnostics -Xlint:all,-path -XDverboseCompilePolicy T6734819c.java */ class Y extends W {} class W extends Z {}
--- a/test/tools/javac/OverrideChecks/6199153/T6199153.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/OverrideChecks/6199153/T6199153.java Tue May 07 17:14:17 2013 -0700 @@ -3,7 +3,7 @@ * @bug 6199153 * @summary Generic throws and overriding * @author mcimadamore - * @compile/fail/ref=T6199153.out -Xlint -Werror -XDrawDiagnostics T6199153.java + * @compile/fail/ref=T6199153.out -Xlint:all,-path -Werror -XDrawDiagnostics T6199153.java */ import java.io.IOException;
--- a/test/tools/javac/Paths/MineField.sh Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/Paths/MineField.sh Tue May 07 17:14:17 2013 -0700 @@ -51,6 +51,18 @@ # previous -Xbootclasspath/p: or -Xbootclasspath/a: command line flags. #---------------------------------------------------------------- +#---------------------------------------------------------------- +# +# JDK 7: Modules: java.endorsed.dirs java.ext.dirs -endorseddirs -extdirs +# +# Endorsed directories and extension directories are currently not supported +# by javac or by java. +# Bootclasspath options are supported by javac, and by java in legacy mode. +# Endorsed and extension directories are internally similar to -Xbootclasspath/p: +# and -Xbootclasspath/a: and could be treated the same way if necessary. +# +#---------------------------------------------------------------- + . ${TESTSRC-.}/Util.sh set -u
--- a/test/tools/javac/T6232928.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/T6232928.java Tue May 07 17:14:17 2013 -0700 @@ -27,7 +27,7 @@ * @summary Interface package-info should be marked abstract and synthetic * @author Wei Tao * @compile T6232928.java - * @compile T6232928/package-info.java + * @compile -doe T6232928/package-info.java * @run main T6232928 */
--- a/test/tools/javac/T6558476.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/T6558476.java Tue May 07 17:14:17 2013 -0700 @@ -37,6 +37,19 @@ import com.sun.tools.javac.Main; public class T6558476 { + public static void main(String[] args) throws IOException { + File javaHome = new File(System.getProperty("java.home")); + if (javaHome.getName().equals("jre")) + javaHome = javaHome.getParentFile(); + if (file(javaHome, "lib", "modules", "%jigsaw-library").exists() + && !file(javaHome, "lib", "ext", "dnsns.jar").exists()) { + System.err.println("PASS BY DEFAULT: modular JDK found with no dnsns.jar"); + return; + } + + main2(args); + } + private static File copyFileTo(File file, File directory) throws IOException { File newFile = new File(directory, file.getName()); FileInputStream fis = null; @@ -70,7 +83,7 @@ return sb.toString(); } - public static void main(String[] args) throws IOException { + public static void main2(String[] args) throws IOException { File javaHomeDir = new File(System.getProperty("java.home")); File outputDir = new File("outputDir" + new Random().nextInt(65536)); outputDir.mkdir(); @@ -99,4 +112,11 @@ throw new Error("Error deleting file \"" + tmpJar.getPath() + "\""); } } + + static File file(File dir, String... path) { + File f = dir; + for (String p: path) + f = new File(f, p); + return f; + } }
--- a/test/tools/javac/T6654037.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/T6654037.java Tue May 07 17:14:17 2013 -0700 @@ -52,7 +52,7 @@ JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, Arrays.asList("-bootclasspath", bootPath, "-Xjcov"), null, Arrays.asList(new MyFileObject(code))); CompilationUnitTree cut = ct.parse().iterator().next(); - ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(1); MethodTree method = (MethodTree) clazz.getMembers().get(0); VariableTree condSt = (VariableTree) method.getBody().getStatements().get(1); BinaryTree cond = (BinaryTree) condSt.getInitializer();
--- a/test/tools/javac/T6725036.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/T6725036.java Tue May 07 17:14:17 2013 -0700 @@ -43,6 +43,15 @@ public class T6725036 { public static void main(String... args) throws Exception { + File javaHome = new File(System.getProperty("java.home")); + if (javaHome.getName().equals("jre")) + javaHome = javaHome.getParentFile(); + if (file(javaHome, "lib", "modules", "%jigsaw-library").exists() + && !file(javaHome, "jre", "lib", "rt.jar").exists()) { + System.err.println("PASS BY DEFAULT: modular JDK found with no rt.jar"); + return; + } + new T6725036().run(); } @@ -92,4 +101,11 @@ } int errors; + + static File file(File dir, String... path) { + File f = dir; + for (String p: path) + f = new File(f, p); + return f; + } }
--- a/test/tools/javac/T6873845.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/T6873845.java Tue May 07 17:14:17 2013 -0700 @@ -11,6 +11,15 @@ public class T6873845 { public static void main(String... args) throws Exception { + File javaHome = new File(System.getProperty("java.home")); + if (javaHome.getName().equals("jre")) + javaHome = javaHome.getParentFile(); + if (file(javaHome, "lib", "modules", "%jigsaw-library").exists() + && !file(javaHome, "lib", "ct.sym").exists()) { + System.err.println("PASS BY DEFAULT: modular JDK found with no ct.sym"); + return; + } + new T6873845().run(); } @@ -19,8 +28,8 @@ if (out.contains("sunapi")) throw new Exception("unexpected output for -X"); - String warn1 = "T6873845.java:73:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline; - String warn2 = "T6873845.java:78:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline; + String warn1 = "T6873845.java:81:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline; + String warn2 = "T6873845.java:86:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline; String note1 = "- compiler.note.sunapi.filename: T6873845.java" + newline; String note2 = "- compiler.note.sunapi.recompile" + newline; @@ -81,5 +90,13 @@ private File testSrc = new File(System.getProperty("test.src", ".")); private File testClasses = new File(System.getProperty("test.classes", ".")); private String newline = System.getProperty("line.separator"); + + + static File file(File dir, String... path) { + File f = dir; + for (String p: path) + f = new File(f, p); + return f; + } }
--- a/test/tools/javac/api/6411310/Test.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/api/6411310/Test.java Tue May 07 17:14:17 2013 -0700 @@ -48,7 +48,12 @@ Set<String> foundJars = new TreeSet<String>(); void run() throws Exception { - File rt_jar = findRtJar(); + File javaHome = new File(System.getProperty("java.home")); + if (javaHome.getName().equals("jre")) + javaHome = javaHome.getParentFile(); + boolean modularJDK = file(javaHome, "lib", "modules", "%jigsaw-library").exists(); + + File rt_jar = modularJDK ? null : findRtJar(); // names for entries to be created in directories and jar files String[] entries = { "p/A.java", "p/A.class", "p/resources/A-1.html" }; @@ -63,8 +68,10 @@ test(createFileManager(useOptimizedZip), createJar("jar", entries), "p", entries); test(createFileManager(useOptimizedZip), createJar("jar jar", entries), "p", entries); - for (boolean useSymbolFile: new boolean[] { false, true }) { - test(createFileManager(useOptimizedZip, useSymbolFile), rt_jar, "java.lang.ref", null); + if (!modularJDK) { + for (boolean useSymbolFile: new boolean[] { false, true }) { + test(createFileManager(useOptimizedZip, useSymbolFile), rt_jar, "java.lang.ref", null); + } } } @@ -72,12 +79,17 @@ throw new Exception(errors + " errors found"); // Verify that we hit all the impl classes we intended - checkCoverage("classes", foundClasses, - "RegularFileObject", "SymbolFileObject", "ZipFileIndexFileObject", "ZipFileObject"); + Set<String> expectClasses = new HashSet<String>(Arrays.asList( + "RegularFileObject", "ZipFileIndexFileObject", "ZipFileObject")); + if (!modularJDK) + expectClasses.add("SymbolFileObject"); + checkCoverage("classes", foundClasses, expectClasses); // Verify that we hit the jar files we intended, specifically ct.sym as well as rt.jar - checkCoverage("jar files", foundJars, - "ct.sym", "jar", "jar jar", "rt.jar"); + Set<String> expectJars = new HashSet<String>(Arrays.asList("jar", "jar jar")); + if (!modularJDK) + expectJars.addAll(Arrays.asList("ct.sym", "rt.jar")); + checkCoverage("jar files", foundJars, expectJars); } // use a new file manager for each test @@ -133,11 +145,10 @@ } } - void checkCoverage(String label, Set<String> found, String... expect) throws Exception { - Set<String> e = new TreeSet<String>(Arrays.asList(expect)); - if (!found.equals(e)) { - e.removeAll(found); - throw new Exception("expected " + label + " not used: " + e); + void checkCoverage(String label, Set<String> found, Set<String> expect) throws Exception { + if (!found.equals(expect)) { + expect.removeAll(found); + throw new Exception("expected " + label + " not used: " + expect); } } @@ -229,4 +240,11 @@ } int errors; + + static File file(File dir, String... path) { + File f = dir; + for (String p: path) + f = new File(f, p); + return f; + } }
--- a/test/tools/javac/api/T6877206.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/api/T6877206.java Tue May 07 17:14:17 2013 -0700 @@ -52,7 +52,12 @@ Set<String> foundJars = new TreeSet<String>(); void run() throws Exception { - File rt_jar = findRtJar(); + javaHome = new File(System.getProperty("java.home")); + if (javaHome.getName().equals("jre")) + javaHome = javaHome.getParentFile(); + boolean modularJDK = file(javaHome, "lib", "modules", "%jigsaw-library").exists(); + + File rt_jar = modularJDK ? null : findRtJar(); // names for entries to be created in directories and jar files String[] entries = { "p/A.class", "p/resources/A-1.jpg" }; @@ -67,18 +72,25 @@ test(createFileManager(useOptimizedZip), createJar("jar", entries), "p", entries.length); test(createFileManager(useOptimizedZip), createJar("jar jar", entries), "p", entries.length); - for (boolean useSymbolFile: new boolean[] { false, true }) { - test(createFileManager(useOptimizedZip, useSymbolFile), rt_jar, "java.lang.ref", -1); + if (!modularJDK) { + for (boolean useSymbolFile: new boolean[] { false, true }) { + test(createFileManager(useOptimizedZip, useSymbolFile), rt_jar, "java.lang.ref", -1); + } } } // Verify that we hit all the impl classes we intended - checkCoverage("classes", foundClasses, - "RegularFileObject", "SymbolFileObject", "ZipFileIndexFileObject", "ZipFileObject"); + Set<String> expectClasses = new HashSet<String>(Arrays.asList( + "RegularFileObject", "ZipFileIndexFileObject", "ZipFileObject")); + if (!modularJDK) + expectClasses.add("SymbolFileObject"); + checkCoverage("classes", foundClasses, expectClasses); // Verify that we hit the jar files we intended, specifically ct.sym as well as rt.jar - checkCoverage("jar files", foundJars, - "ct.sym", "jar", "jar jar", "rt.jar"); + Set<String> expectJars = new HashSet<String>(Arrays.asList("jar", "jar jar")); + if (!modularJDK) + expectJars.addAll(Arrays.asList("ct.sym", "rt.jar")); + checkCoverage("jar files", foundJars, expectJars); } // use a new file manager for each test @@ -149,11 +161,10 @@ } } - void checkCoverage(String label, Set<String> found, String... expect) throws Exception { - Set<String> e = new TreeSet<String>(Arrays.asList(expect)); - if (!found.equals(e)) { - e.removeAll(found); - throw new Exception("expected " + label + " not used: " + e); + void checkCoverage(String label, Set<String> found, Set<String> expect) throws Exception { + if (!found.equals(expect)) { + expect.removeAll(found); + throw new Exception("expected " + label + " not used: " + expect); } } @@ -202,10 +213,7 @@ } File findRtJar() throws Exception { - File java_home = new File(System.getProperty("java.home")); - if (java_home.getName().equals("jre")) - java_home = java_home.getParentFile(); - File rt_jar = new File(new File(new File(java_home, "jre"), "lib"), "rt.jar"); + File rt_jar = file(javaHome, "jre", "lib", "rt.jar"); if (!rt_jar.exists()) throw new Exception("can't find rt.jar"); return rt_jar; @@ -236,4 +244,13 @@ out.close(); } } + + File javaHome; + + static File file(File dir, String... path) { + File f = dir; + for (String p: path) + f = new File(f, p); + return f; + } }
--- a/test/tools/javac/diags/CheckResourceKeys.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/diags/CheckResourceKeys.java Tue May 07 17:14:17 2013 -0700 @@ -276,7 +276,9 @@ "compiler.misc.", "count.", "illegal.", + "java.", "javac.", + "javac.debug.modules", "verbose." ));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/modules/ClassReaderTest01.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests for reading module-info.class files + * @build DirectiveTest + * @run main ClassReaderTest01 + */ + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.tools.JavaFileObject; +import javax.tools.StandardLocation; + +public class ClassReaderTest01 extends DirectiveTest { + public static void main(String... args) throws Exception { + new ClassReaderTest01().run(); + } + + @Test + void basicTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { exports p; }")); + files.add(createFile("M1/p/C1.java", + "package p; public class C1 { }")); + files.add(createFile("M2/module-info.java", + "module M2 { requires public M1; }")); + fm.setLocation(StandardLocation.MODULE_PATH, Arrays.asList(classesDir)); + compile(files); + + srcDir = new File(srcDir.getParentFile(), "src2"); + srcDir.mkdirs(); + fm.setLocation(StandardLocation.SOURCE_PATH, Arrays.asList(srcDir)); + + List<JavaFileObject> files2 = new ArrayList<JavaFileObject>(); + files2.add(createFile("M3/module-info.java", + "module M3 { requires M2; }")); + files2.add(createFile("M3/q/C2.java", + "package q; public class C2 { void m() { new p.C1(); } }")); + compile(files2); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/modules/DirectiveTest.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.tools.Diagnostic; +import javax.tools.DiagnosticListener; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; + +import com.sun.source.util.JavacTask; +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.ModuleProvides_attribute; +import com.sun.tools.classfile.ModuleProvides_attribute.View; +import com.sun.tools.javac.api.ClientCodeWrapper; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.util.JCDiagnostic; +import com.sun.tools.javap.JavapTask; + +/* Utilities for module directives tests. */ +abstract class DirectiveTest { + + protected DirectiveTest() { + javac = JavacTool.create(); + fm = javac.getStandardFileManager(null, null, null); + } + + @Retention(RetentionPolicy.RUNTIME) + @interface Test { } + + void run() throws Exception { + for (Method m: getClass().getDeclaredMethods()) { + Annotation a = m.getAnnotation(Test.class); + if (a != null) { + init(m.getName()); + try { + m.invoke(this, new Object[] { }); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + throw (cause instanceof Exception) ? ((Exception) cause) : e; + } + System.err.println(); + } + } + System.err.println(testCount + " tests" + ((errorCount == 0) ? "" : ", " + errorCount + " errors")); + if (errorCount > 0) + throw new Exception(errorCount + " errors found"); + } + + void init(String name) throws IOException { + System.err.println("Test " + name); + testCount++; + + srcDir = new File(name, "src"); + srcDir.mkdirs(); + classesDir = new File(name, "classes"); + classesDir.mkdirs(); + + fm.setLocation(StandardLocation.SOURCE_PATH, Arrays.asList(srcDir)); + fm.setLocation(StandardLocation.MODULE_PATH, Collections.<File>emptyList()); + fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(classesDir)); + } + + void compile(List<JavaFileObject> files) throws Exception { + JavacTask task = javac.getTask(null, fm, null, null, null, files); + if (!task.call()) + throw new Exception("compilation failed"); + } + + void compile(List<JavaFileObject> files, List<String> expectDiags) throws Exception { + class DiagListener implements DiagnosticListener<JavaFileObject> { + List<String> diags = new ArrayList<String>(); + @Override + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { + System.err.println(diagnostic); + JCDiagnostic d = ((ClientCodeWrapper.DiagnosticSourceUnwrapper) diagnostic).d; + diags.add(d.getKind() + ": " + d.getCode() + " " + Arrays.asList(d.getArgs())); + } + } + + DiagListener dl = new DiagListener(); + JavacTask task = javac.getTask(null, fm, dl, null, null, files); + boolean ok = task.call(); + System.err.println(ok ? "Compilation succeeded" : "Compilation failed"); + + List<String> foundDiags = dl.diags; + + checkEqual("diags", expectDiags, foundDiags); + } + + void javap(String path) { + List<String> opts = Arrays.asList("-v"); + List<String> files = Arrays.asList(new File(classesDir, path).getPath()); + JavapTask t = new JavapTask(null, fm, null, opts, files); + t.call(); + } + + View getView(ClassFile cf, String name) throws ConstantPoolException { + ConstantPool cp = cf.constant_pool; + ModuleProvides_attribute attr = (ModuleProvides_attribute) cf.getAttribute(Attribute.ModuleProvides); + Set<String> found = new HashSet<String>(); + for (View v: attr.view_table) { + if (v.view_name_index == 0 && name == null + || v.view_name_index != 0 && cp.getUTF8Value(v.view_name_index).equals(name)) { + return v; + } + } + return null; + } + + JavaFileObject createFile(String path, final String body) throws IOException { + File f = new File(srcDir, path); + f.getParentFile().mkdirs(); + try (FileWriter out = new FileWriter(f)) { + out.write(body); + } + return fm.getJavaFileObjects(f).iterator().next(); + } + + <T> Set<T> createSet(T... items) { + return new HashSet<T>(Arrays.asList(items)); + } + + <T> void checkEqual(String label, T expect, T found) { + if ((found == null) ? (expect == null) : found.equals(expect)) + return; + System.err.println("Error: mismatch"); + System.err.println(" expected: " + expect); + System.err.println(" found: " + found); + errorCount++; + } + + <T> void checkEqual(String label, Collection<T> expect, Collection<T> found) { + if ((found == null) ? (expect == null) : found.equals(expect)) + return; + System.err.println("Error: mismatch"); + System.err.println(" expected: " + expect); + System.err.println(" found: " + found); + errorCount++; + } + + JavacTool javac; + StandardJavaFileManager fm; + File srcDir; + File classesDir; + int testCount; + int errorCount; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/modules/EntrypointTest01.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests for "class class-name;" + * @build DirectiveTest + * @run main EntrypointTest01 + */ + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.tools.JavaFileObject; + +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.ModuleProvides_attribute.View; + +public class EntrypointTest01 extends DirectiveTest { + public static void main(String... args) throws Exception { + new EntrypointTest01().run(); + } + + @Test + void basicTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { class p.Main; }")); + files.add(createFile("M1/p/Main.java", + "package p; public class Main { public static void main(String... args) { } }")); + compile(files); + + Set<String> expect = createSet("p/Main"); + Set<String> found = getEntrypoints("M1/module-info.class", null); + checkEqual("entrypoint", expect, found); + } + + @Test + void duplTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { class p.Main; class p.Main2; }")); + files.add(createFile("M1/p/Main.java", + "package p; public class Main { public static void main(String... args) { } }")); + files.add(createFile("M1/p/Main2.java", + "package p; public class Main2 { public static void main(String... args) { } }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.dupl.entrypoint []"); + compile(files, expectDiags); + } + + @Test + void mainNotPublicTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { class p.Main; }")); + files.add(createFile("M1/p/Main.java", + "package p; public class Main { static void main(String... args) { } }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.no.psv.main [p.Main]"); + compile(files, expectDiags); + } + + @Test + void mainNotStaticTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { class p.Main; }")); + files.add(createFile("M1/p/Main.java", + "package p; public class Main { public void main(String... args) { } }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.no.psv.main [p.Main]"); + compile(files, expectDiags); + } + + @Test + void mainNotVoidTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { class p.Main; }")); + files.add(createFile("M1/p/Main.java", + "package p; public class Main { public static int main(String... args) { return 0; } }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.no.psv.main [p.Main]"); + compile(files, expectDiags); + } + + @Test + void mainNoArgsTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { class p.Main; }")); + files.add(createFile("M1/p/Main.java", + "package p; public class Main { public static void main() { } }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.no.psv.main [p.Main]"); + compile(files, expectDiags); + } + + @Test + void mainArgsNotArray1Test() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { class p.Main; }")); + files.add(createFile("M1/p/Main.java", + "package p; public class Main { public static void main(String arg) { } }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.no.psv.main [p.Main]"); + compile(files, expectDiags); + } + + @Test + void mainArgsNotArray2Test() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { class p.Main; }")); + files.add(createFile("M1/p/Main.java", + "package p; public class Main { public static void main(int[] arg) { } }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.no.psv.main [p.Main]"); + compile(files, expectDiags); + } + + Set<String> getEntrypoints(String path, String viewName) throws IOException, ConstantPoolException { + javap(path); + Set<String> found = new HashSet<String>(); + ClassFile cf = ClassFile.read(new File(classesDir, path)); + ConstantPool cp = cf.constant_pool; + View v = getView(cf, viewName); + CONSTANT_Class_info info = cp.getClassInfo(v.entrypoint_index); + found.add(info.getName()); + return found; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/modules/ExportsTest01.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests for "exports package-name;" + * @build DirectiveTest + * @run main ExportsTest01 + */ + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.tools.JavaFileObject; + +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.ModuleProvides_attribute.View; + +public class ExportsTest01 extends DirectiveTest { + public static void main(String... args) throws Exception { + new ExportsTest01().run(); + } + + @Test + void basicTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { exports p; }")); + files.add(createFile("M1/p/C.java", + "package p; public class C { }")); + compile(files); + + Set<String> expect = createSet("p"); + Set<String> found = getExports("M1/module-info.class", null); + checkEqual("exports", expect, found); + } + + @Test + void viewTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { exports p; view V { exports q; } }")); + files.add(createFile("M1/p/C.java", + "package p; public class C { }")); + files.add(createFile("M1/q/C.java", + "package q; public class C { }")); + compile(files); + + Set<String> expectDefault = createSet("p"); + Set<String> foundDefault = getExports("M1/module-info.class", null); + checkEqual("exports", expectDefault, foundDefault); + + Set<String> expectV = createSet("p", "q"); + Set<String> foundV = getExports("M1/module-info.class", "V"); + checkEqual("exports", expectV, foundV); + } + + @Test + void duplTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { exports p; exports p; }")); + files.add(createFile("M1/p/C.java", + "package p; public class C { }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.dupl.exports [p]"); + compile(files, expectDiags); + } + + Set<String> getExports(String path, String viewName) throws IOException, ConstantPoolException { + javap(path); + Set<String> found = new HashSet<String>(); + ClassFile cf = ClassFile.read(new File(classesDir, path)); + ConstantPool cp = cf.constant_pool; + View v = getView(cf, viewName); + for (int e: v.export_table) { + CONSTANT_Utf8_info info = cp.getUTF8Info(e); + found.add(info.value); + } + return found; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/modules/ModuleDataTest01.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,86 @@ + +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests for module data + * @build DirectiveTest + * @run main ModuleDataTest01 + */ + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.tools.JavaFileObject; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.ModuleData_attribute; + +public class ModuleDataTest01 extends DirectiveTest { + public static void main(String... args) throws Exception { + new ModuleDataTest01().run(); + } + + @Override + void run() throws Exception { + String[] tests = { /*"", */" ", "\n", "\nthis is module data\n" }; + for (String s: tests) { + test(s); + } + + if (errorCount > 0) + throw new Exception(errorCount + " errors found"); + } + + void test(String s) throws Exception { + String testName = "test_" + + s.toLowerCase() + .replace("\n", "N") + .replace(" ", "S") + .replace("\t", "T"); + init(testName); + + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { }" + s)); + compile(files); + + String expect = s.replaceAll("^[ \n\t]*", ""); + if (expect.isEmpty()) expect = null; + String found = getModuleData("M1/module-info.class"); + checkEqual("module data", expect, found); + } + + String getModuleData(String path) throws IOException, ConstantPoolException { + javap(path); + ClassFile cf = ClassFile.read(new File(classesDir, path)); + ConstantPool cp = cf.constant_pool; + ModuleData_attribute attr = (ModuleData_attribute) cf.getAttribute(Attribute.ModuleData); + return (attr == null) ? null : attr.getData(cp); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/modules/PermitsTest01.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests for "permits module-name;" + * @build DirectiveTest + * @run main PermitsTest01 + */ + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.tools.JavaFileObject; + +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPool.CONSTANT_ModuleId_info; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.ModuleProvides_attribute.View; + +public class PermitsTest01 extends DirectiveTest { + public static void main(String... args) throws Exception { + new PermitsTest01().run(); + } + + @Test + void basicTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { permits M2; }")); + files.add(createFile("M2/module-info.java", + "module M2 { }")); + compile(files); + + Set<String> expect = createSet("M2"); + Set<String> found = getPermits("M1/module-info.class", null); + checkEqual("permits", expect, found); + } + + @Test + void duplTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { permits M2; permits M2; }")); + files.add(createFile("M2/module-info.java", + "module M2 { }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.dupl.permits [M2]"); + compile(files, expectDiags); + } + + Set<String> getPermits(String path, String viewName) throws IOException, ConstantPoolException { + javap(path); + Set<String> found = new HashSet<String>(); + ClassFile cf = ClassFile.read(new File(classesDir, path)); + ConstantPool cp = cf.constant_pool; + View v = getView(cf, viewName); + for (int i: v.permit_table) { + CONSTANT_ModuleId_info info = cp.getModuleIdInfo(i); + String s = info.getName(); + if (info.version_index != 0) + s += "@" + info.getVersion(); + found.add(s); + } + return found; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/modules/ProvidesModuleTest01.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests for "provides module-name;" + * @build DirectiveTest + * @run main ProvidesModuleTest01 + */ + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.tools.JavaFileObject; + +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPool.CONSTANT_ModuleId_info; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.ModuleProvides_attribute.View; + +public class ProvidesModuleTest01 extends DirectiveTest { + public static void main(String... args) throws Exception { + new ProvidesModuleTest01().run(); + } + + @Test + void basicTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { provides M1a; }")); + compile(files); + + Set<String> expect = createSet("M1a"); + Set<String> found = getAliases("M1/module-info.class", null); + checkEqual("aliases", expect, found); + } + + @Test + void duplTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { provides M1a; provides M1a; }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.dupl.provides [M1a]"); + compile(files, expectDiags); + } + + Set<String> getAliases(String path, String viewName) throws IOException, ConstantPoolException { + javap(path); + Set<String> found = new HashSet<String>(); + ClassFile cf = ClassFile.read(new File(classesDir, path)); + ConstantPool cp = cf.constant_pool; + View v = getView(cf, viewName); + for (int i: v.alias_table) { + CONSTANT_ModuleId_info info = cp.getModuleIdInfo(i); + String s = info.getName(); + if (info.version_index != 0) + s += "@" + info.getVersion(); + found.add(s); + } + return found; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/modules/ProvidesServiceTest01.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests for "provides service service-name with impl-name;" + * @build DirectiveTest + * @run main ProvidesServiceTest01 + */ + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.tools.JavaFileObject; + +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.ModuleProvides_attribute; +import com.sun.tools.classfile.ModuleProvides_attribute.View; + +public class ProvidesServiceTest01 extends DirectiveTest { + public static void main(String... args) throws Exception { + new ProvidesServiceTest01().run(); + } + + @Test + void basicTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { provides service p.S1 with p.S2; }")); + files.add(createFile("M1/p/S1.java", + "package p; public class S1 { }")); + files.add(createFile("M1/p/S2.java", + "package p; public class S2 extends S1 { }")); + compile(files); + + Set<String> expect = createSet("p/S1 p/S2"); + Set<String> found = getServices("M1/module-info.class", null); + checkEqual("services", expect, found); + } + + @Test + void duplTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { provides service p.S1 with p.S2; provides service p.S1 with p.S2; }")); + files.add(createFile("M1/p/S1.java", + "package p; public class S1 { }")); + files.add(createFile("M1/p/S2.java", + "package p; public class S2 extends S1 { }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.dupl.provides.service [p.S1, p.S2]"); + compile(files, expectDiags); + } + + @Test + void implIsAbstractTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { provides service p.S1 with p.S2; }")); + files.add(createFile("M1/p/S1.java", + "package p; public class S1 { }")); + files.add(createFile("M1/p/S2.java", + "package p; public abstract class S2 extends S1 { }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.service.impl.is.abstract [p.S2]"); + compile(files, expectDiags); + } + + @Test + void implNotPublicTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { provides service p.S1 with p.S2; }")); + files.add(createFile("M1/p/S1.java", + "package p; public class S1 { }")); + files.add(createFile("M1/p/S2.java", + "package p; class S2 extends S1 { }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.not.def.public.cant.access [p.S2, p]"); + compile(files, expectDiags); + } + + @Test + void implConstrNotPublicTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { provides service p.S1 with p.S2; }")); + files.add(createFile("M1/p/S1.java", + "package p; public class S1 { }")); + files.add(createFile("M1/p/S2.java", + "package p; public class S2 extends S1 { private S2() { } }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.service.impl.no.default.constr [p.S2]"); + compile(files, expectDiags); + } + + @Test + void implConstrHasArgsTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { provides service p.S1 with p.S2; }")); + files.add(createFile("M1/p/S1.java", + "package p; public class S1 { }")); + files.add(createFile("M1/p/S2.java", + "package p; public class S2 extends S1 { public S2(int i) { } }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.service.impl.no.default.constr [p.S2]"); + compile(files, expectDiags); + } + + @Test + void implIsInnerTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { provides service p.S1 with p.S2.Inner; }")); + files.add(createFile("M1/p/S1.java", + "package p; public class S1 { }")); + files.add(createFile("M1/p/S2.java", + "package p; public class S2 extends S1 { public class Inner { } }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.service.impl.is.inner [p.S2.Inner]"); + compile(files, expectDiags); + } + + Set<String> getServices(String path, String viewName) throws IOException, ConstantPoolException { + javap(path); + Set<String> found = new HashSet<String>(); + ClassFile cf = ClassFile.read(new File(classesDir, path)); + ConstantPool cp = cf.constant_pool; + View v = getView(cf, viewName); + for (ModuleProvides_attribute.Service e: v.service_table) { + CONSTANT_Class_info serviceInfo = cp.getClassInfo(e.service_index); + CONSTANT_Class_info implInfo = cp.getClassInfo(e.impl_index); + found.add(serviceInfo.getName() + " " + implInfo.getName()); + } + return found; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/modules/RequiresModuleTest01.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests for "requires module-name;" + * @build DirectiveTest + * @run main ProvidesModuleTest01 + */ + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.tools.JavaFileObject; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPool.CONSTANT_ModuleQuery_info; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.ModuleRequires_attribute; + +import com.sun.tools.javac.jvm.Target; + +public class RequiresModuleTest01 extends DirectiveTest { + public static void main(String... args) throws Exception { + new RequiresModuleTest01().run(); + } + + @Test + void basicTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { requires M2; }")); + files.add(createFile("M2/module-info.java", + "module M2 { }")); + compile(files); + + Set<String> expect = createSet("M2", "java/base@>=" + version); + Set<String> found = getRequires("M1/module-info.class"); + checkEqual("required modules", expect, found); + } + + @Test + void duplTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { requires M2; requires M2; }")); + files.add(createFile("M2/module-info.java", + "module M2 { }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.dupl.requires [M2]"); + compile(files, expectDiags); + } + + @Test + void viewTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { view V { requires M1; } }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.requires.not.allowed.in.view []"); + compile(files, expectDiags); + } + + Set<String> getRequires(String path) throws IOException, ConstantPoolException { + javap(path); + ClassFile cf = ClassFile.read(new File(classesDir, path)); + ConstantPool cp = cf.constant_pool; + ModuleRequires_attribute attr = (ModuleRequires_attribute) cf.getAttribute(Attribute.ModuleRequires); + Set<String> found = new HashSet<String>(); + for (ModuleRequires_attribute.Entry e: attr.module_table) { + CONSTANT_ModuleQuery_info info = cp.getModuleQueryInfo(e.index); + String s = info.getName(); + if (info.version_index != 0) + s += "@" + info.getVersion(); + found.add(s); + } + return found; + } + + Target target = Target.DEFAULT; + String version = target.name.replace("1.", ""); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/modules/RequiresModuleTest02.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests for requires finding modules in different locations + * @run main RequiresModuleTest02 + */ + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class RequiresModuleTest02 { + static PrintStream out = System.out; + + public static void main(String... args) throws Exception { + new RequiresModuleTest02().run(); + } + + enum PathKind { + SOURCEPATH, + MODULEPATH, + MODULELIB + } + + enum RequireKind { + MODULE, + ALIAS, + VIEW + } + + void run() throws Exception { + setup(); + for (PathKind pk: PathKind.values()) { + for (RequireKind rk: RequireKind.values()) { + test(pk, rk); + } + } + + out.println(testCount + " tests" + ((errorCount == 0) ? "" : ", " + errorCount + " errors")); + if (errorCount > 0) + throw new Exception(errorCount + " errors found"); + } + + void setup() throws Exception { + srcDir = new File("src"); + classesDir = new File("classes"); + classesDir.mkdirs(); + moduleLib = new File("mlib"); + + List<File> files = Arrays.asList( + // module M1 + createFile(srcDir, "M1/module-info.java", + "module M1@1.0 {\n" + + " provides A1;\n" + + " view V1 { }\n" + + "}") + ); + + List<String> args = new ArrayList<String>(); + args.add("-d"); + args.add(classesDir.getPath()); + args.add("-modulepath"); + args.add(classesDir.getPath()); + for (File f: files) + args.add(f.getPath()); + compile(args); + + jmod(Arrays.asList("create", "-L", moduleLib.getPath())); + jmod(Arrays.asList("install", "-L", moduleLib.getPath(), + classesDir.getPath(), "M1")); + } + + void test(PathKind pk, RequireKind rk) throws Exception { + out.println("Test pk:" + pk + " rk:" + rk); + if (rk == RequireKind.ALIAS) { + out.println(".... skipped until Jigsaw supports aliases"); + return; + } + testCount++; + + File testDir = new File(pk + "-" + rk ); + File testSrcDir = new File(testDir, "src"); + File testClassesDir = new File(testDir, "classes"); + testClassesDir.mkdirs(); + + String requires; + switch (rk) { + case MODULE: requires = "M1"; break; + case ALIAS: requires = "A1"; break; + case VIEW: requires = "V1"; break; + default: throw new IllegalArgumentException(); + } + List<File> files = Arrays.asList( + createFile(testSrcDir, "MT/module-info.java", + "module MT@1.0 {\n" + + " requires " + requires + ";\n" + + "}") + ); + + List<String> args = new ArrayList<String>(); + args.add("-d"); + args.add(testClassesDir.getPath()); + switch (pk) { + case SOURCEPATH: + args.add("-modulepath"); + args.add(testClassesDir.getPath()); + args.add("-sourcepath"); + args.add(srcDir.getPath()); + break; + case MODULEPATH: + args.add("-modulepath"); + args.add(classesDir.getPath() + + File.pathSeparator + + testClassesDir.getPath()); + break; + case MODULELIB: + args.add("-modulepath"); + args.add(testClassesDir.getPath()); + args.add("-L"); + args.add(moduleLib.getPath()); + break; + default: throw new IllegalArgumentException(); + } + for (File f: files) + args.add(f.getPath()); + + compile(args, 0); + } + + File createFile(File srcDir, String path, final String body) throws IOException { + File f = new File(srcDir, path); + f.getParentFile().mkdirs(); + try (FileWriter out = new FileWriter(f)) { + out.write(body); + } + return f; + } + + void compile(List<String> args) throws Exception { + int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()])); + if (rc != 0) + throw new Exception("compilation failed"); + } + + void compile(List<String> args, int expect_rc) throws Exception { + int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()])); + if (rc == expect_rc) { + out.println("compilation " + (rc == 0 ? "succeeded" : "failed") + " as expected"); + } else { + error("compilation " + (rc == 0 ? "succeeded" : "failed") + " unexpectedly"); + } + } + + void jmod(List<String> args) throws Exception { + // for now, use jmod via CLI; eventually should use API + File javaHome = new File(System.getProperty("java.home")); + File jmod = new File(new File(javaHome, "bin"), "jmod"); + List<String> cmdArgs = new ArrayList<String>(); + cmdArgs.add(jmod.getPath()); + cmdArgs.addAll(args); + Process p = new ProcessBuilder() + .command(cmdArgs) + .redirectErrorStream(true) + .start(); + try (BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()))) { + String line; + while ((line = r.readLine()) != null) + out.println(line); + int rc = p.waitFor(); + if (rc != 0) + throw new Exception("jmod failed: rc=" + rc); + } + } + + void error(String msg) { + out.println("ERROR: " + msg); + errorCount++; + } + + File srcDir; + File classesDir; + File moduleLib; + + int testCount; + int errorCount; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/modules/RequiresServiceTest01.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests for "requires service service-name;" + * @build DirectiveTest + * @run main RequiresServiceTest01 + */ + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.tools.JavaFileObject; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.ModuleRequires_attribute; + +import com.sun.tools.javac.jvm.Target; + +public class RequiresServiceTest01 extends DirectiveTest { + public static void main(String... args) throws Exception { + new RequiresServiceTest01().run(); + } + + @Test + void basicTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { requires service p.S1; }")); + provideService(files, "M2", "p.S1", "p.S2"); + compile(files); + + Set<String> expect = createSet("p/S1"); + Set<String> found = getRequires("M1/module-info.class"); + checkEqual("required services", expect, found); + } + + @Test + void duplTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { requires service p.S1; requires service p.S1; }")); + provideService(files, "M2", "p.S1", "p.S2"); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.dupl.requires.service [p.S1]"); + compile(files, expectDiags); + } + + @Test + void viewTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { view V { requires service p.S1; } }")); + provideService(files, "M2", "p.S1", "p.S2"); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.requires.not.allowed.in.view []"); + compile(files, expectDiags); + } + + void provideService(List<JavaFileObject> files, String module, String service, String impl) + throws IOException { + files.add(createFile(module + "/module-info.java", + "module " + module + " { provides service " + service + " with " + impl + "; }")); + String servicePkg = service.substring(0, service.lastIndexOf(".")); + String serviceCls = service.substring(service.lastIndexOf(".") + 1); + files.add(createFile(module + "/" + service.replace(".", "/") + ".java", + "package " + servicePkg + "; public class " + serviceCls + " { }")); + String implPkg = impl.substring(0, impl.lastIndexOf(".")); + String implCls = impl.substring(impl.lastIndexOf(".") + 1); + files.add(createFile(module + "/" + impl.replace(".", "/") + ".java", + "package " + implPkg + "; public class " + implCls + " extends " + service + " { }")); + } + + Set<String> getRequires(String path) throws IOException, ConstantPoolException { + javap(path); + Set<String> found = new HashSet<String>(); + ClassFile cf = ClassFile.read(new File(classesDir, path)); + ConstantPool cp = cf.constant_pool; + ModuleRequires_attribute attr = (ModuleRequires_attribute) cf.getAttribute(Attribute.ModuleRequires); + for (ModuleRequires_attribute.Entry e: attr.service_table) { + CONSTANT_Class_info info = cp.getClassInfo(e.index); + found.add(info.getName()); + } + return found; + } + + Target target = Target.DEFAULT; + String version = target.name.replace("1.", ""); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/modules/ViewTest01.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Tests for "view { ... };" + * @build DirectiveTest + * @run main ViewTest01 + */ + +import com.sun.tools.classfile.Attribute; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.tools.JavaFileObject; + +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.ModuleProvides_attribute; +import com.sun.tools.classfile.ModuleProvides_attribute.View; + +public class ViewTest01 extends DirectiveTest { + public static void main(String... args) throws Exception { + new ViewTest01().run(); + } + + @Test + void emptyTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { }")); + compile(files); + + Set<String> expect = null; + Set<String> found = getViews("M1/module-info.class"); + checkEqual("views", expect, found); + } + + @Test + void basicTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { view V { } }")); + compile(files); + + Set<String> expect = createSet("V"); + Set<String> found = getViews("M1/module-info.class"); + checkEqual("views", expect, found); + } + + @Test + void duplTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { view V { } view V { } }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.dupl.view [V]"); + compile(files, expectDiags); + } + + @Test + void inheritDuplTest() throws Exception { + List<JavaFileObject> files = new ArrayList<JavaFileObject>(); + files.add(createFile("M1/module-info.java", + "module M1 { view M1 { } }")); + + List<String> expectDiags = Arrays.asList("ERROR: compiler.err.dupl.view [M1]"); + compile(files, expectDiags); + } + + Set<String> getViews(String path) throws IOException, ConstantPoolException { + javap(path); + ClassFile cf = ClassFile.read(new File(classesDir, path)); + ConstantPool cp = cf.constant_pool; + ModuleProvides_attribute attr = (ModuleProvides_attribute) cf.getAttribute(Attribute.ModuleProvides); + if (attr == null) + return null; + Set<String> found = new HashSet<String>(); + for (View v: attr.view_table) { + found.add(v.view_name_index == 0 ? null : cp.getUTF8Value(v.view_name_index)); + } + return found; + } +}
--- a/test/tools/javac/nio/compileTest/CompileTest.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/nio/compileTest/CompileTest.java Tue May 07 17:14:17 2013 -0700 @@ -41,16 +41,32 @@ public class CompileTest { + static File javaHome; + + static File file(File dir, String... path) { + File f = dir; + for (String p: path) + f = new File(f, p); + return f; + } + public static void main(String[] args) throws Exception { + javaHome = new File(System.getProperty("java.home")); + if (javaHome.getName().equals("jre")) + javaHome = javaHome.getParentFile(); + + if (file(javaHome, "lib", "modules", "%jigsaw-library").exists() + && !file(javaHome, "jre", "lib", "rt.jar").exists()) { + System.err.println("PASS BY DEFAULT: modular JDK found with no rt.jar"); + return; + } + new CompileTest().run(); } public void run() throws Exception { File rtDir = new File("rt.dir"); - File javaHome = new File(System.getProperty("java.home")); - if (javaHome.getName().equals("jre")) - javaHome = javaHome.getParentFile(); - File rtJar = new File(new File(new File(javaHome, "jre"), "lib"), "rt.jar"); + File rtJar = file(javaHome, "jre", "lib", "rt.jar"); expand(rtJar, rtDir); String[] rtDir_opts = {
--- a/test/tools/javac/processing/6348193/T6348193.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/processing/6348193/T6348193.java Tue May 07 17:14:17 2013 -0700 @@ -80,6 +80,7 @@ args.add(System.getProperty("java.class.path")); args.add("-d"); args.add("."); + args.add("-XDnomodules"); JavacTool t = JavacTool.create(); // avoid using class loader @@ -169,7 +170,7 @@ static class NoLoaderSecurityManager extends SecurityManager { public void checkCreateClassLoader() { - throw new SecurityException("Not today, thanks you!"); + throw new SecurityException("Not today, thank you!"); } public void checkPropertyAccess(String key) { /*OK*/ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/proprietary/Test.java Tue May 07 17:14:17 2013 -0700 @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.*; +import java.util.*; + +/** + * Test runner to check if ct.sym exists and then to execute a series + * of simple jtreg-like compile commands. + * If this is a modular JDK image (as determined by the presence of a + * jigsaw module library), and if ct.sym does not exist, the test will + * pass by default. If this is not a modular JDK image and ct.sym + * does not exist, the test will fail. + * + * The equivalent of @compile and @compile/fail are supported, with + * the leading "@" removed. Filenames are assumed to be in the test.src + * directory. + */ + +public class Test { + public static void main(String... args) throws Exception { + + File javaHome = new File(System.getProperty("java.home")); + if (javaHome.getName().equals("jre")) + javaHome = javaHome.getParentFile(); + if (file(javaHome, "lib", "modules", "%jigsaw-library").exists() + && !file(javaHome, "lib", "ct.sym").exists()) { + System.err.println("PASS BY DEFAULT: modular JDK found with no ct.sym"); + return; + } + + new Test().run(args); + } + + void run(String... args) throws Exception { + List<String> compileArgs = new ArrayList<String>(); + boolean expectFail = false; + + for (String arg: args) { + if (arg.equals("compile")) { + if (compileArgs.size() > 0) + compile(compileArgs, expectFail); + compileArgs.clear(); + expectFail = false; + } else if (arg.equals("compile/fail")) { + if (compileArgs.size() > 0) + compile(compileArgs, expectFail); + compileArgs.clear(); + expectFail = true; + } else { + compileArgs.add(arg); + } + } + + if (compileArgs.size() > 0) + compile(compileArgs, expectFail); + + if (errors > 0) + throw new Exception(errors + " errors found"); + } + + void compile(List<String> args, boolean expectFail) { + System.err.println("javac: " + args); + + File testSrc = new File(System.getProperty("test.src")); + for (int i = 0; i < args.size(); i++) { + String arg = args.get(i); + if (arg.endsWith(".java")) + args.set(i, new File(testSrc, arg).getPath()); + } + + args.add("-d"); + args.add(System.getProperty("test.classes")); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw); + String out = sw.toString(); + System.err.println(out); + if (expectFail && rc == 0) + error("compilation succeeded unexpectedly"); + else if (!expectFail && rc != 0) + error("compilation failed unexpectedly, rc=" + rc); + } + + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int errors; + + static File file(File dir, String... path) { + File f = dir; + for (String p: path) + f = new File(f, p); + return f; + } +}
--- a/test/tools/javac/proprietary/WarnClass.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/proprietary/WarnClass.java Tue May 07 17:14:17 2013 -0700 @@ -26,11 +26,12 @@ * @bug 6380059 * @summary Emit warnings for proprietary packages in the boot class path * @author Peter von der Ah\u00e9 - * @compile WarnClass.java - * @compile/fail -Werror WarnClass.java - * @compile/fail -Werror -source 1.4 -nowarn WarnClass.java - * @compile/fail -Werror -nowarn WarnClass.java - * @compile/fail -Werror -Xlint:none WarnClass.java + * @run main Test + * compile WarnClass.java + * compile/fail -Werror WarnClass.java + * compile/fail -Werror -source 1.4 -nowarn WarnClass.java + * compile/fail -Werror -nowarn WarnClass.java + * compile/fail -Werror -Xlint:none WarnClass.java */ public class WarnClass extends sun.misc.Lock {}
--- a/test/tools/javac/proprietary/WarnImport.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/proprietary/WarnImport.java Tue May 07 17:14:17 2013 -0700 @@ -26,11 +26,12 @@ * @bug 6380059 * @summary Emit warnings for proprietary packages in the boot class path * @author Peter von der Ah\u00e9 - * @compile WarnImport.java - * @compile/fail -Werror WarnImport.java - * @compile/fail -Werror -source 1.4 -nowarn WarnImport.java - * @compile/fail -Werror -nowarn WarnImport.java - * @compile/fail -Werror -Xlint:none WarnImport.java + * @run main Test + * compile WarnImport.java + * compile/fail -Werror WarnImport.java + * compile/fail -Werror -source 1.4 -nowarn WarnImport.java + * compile/fail -Werror -nowarn WarnImport.java + * compile/fail -Werror -Xlint:none WarnImport.java */ import sun.misc.VM;
--- a/test/tools/javac/proprietary/WarnMethod.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/proprietary/WarnMethod.java Tue May 07 17:14:17 2013 -0700 @@ -26,11 +26,12 @@ * @bug 6380059 * @summary Emit warnings for proprietary packages in the boot class path * @author Peter von der Ah\u00e9 - * @compile WarnMethod.java - * @compile/fail -Werror WarnMethod.java - * @compile/fail -Werror -source 1.4 -nowarn WarnMethod.java - * @compile/fail -Werror -nowarn WarnMethod.java - * @compile/fail -Werror -Xlint:none WarnMethod.java + * @run main Test + * compile WarnMethod.java + * compile/fail -Werror WarnMethod.java + * compile/fail -Werror -source 1.4 -nowarn WarnMethod.java + * compile/fail -Werror -nowarn WarnMethod.java + * compile/fail -Werror -Xlint:none WarnMethod.java */ public class WarnMethod {
--- a/test/tools/javac/proprietary/WarnStaticImport.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/proprietary/WarnStaticImport.java Tue May 07 17:14:17 2013 -0700 @@ -26,11 +26,12 @@ * @bug 6380059 * @summary Emit warnings for proprietary packages in the boot class path * @author Peter von der Ah\u00e9 - * @compile WarnStaticImport.java - * @compile/fail -Werror WarnStaticImport.java - * @compile/fail -Werror -source 1.4 -nowarn WarnStaticImport.java - * @compile/fail -Werror -nowarn WarnStaticImport.java - * @compile/fail -Werror -Xlint:none WarnStaticImport.java + * @run main Test + * compile WarnStaticImport.java + * compile/fail -Werror WarnStaticImport.java + * compile/fail -Werror -source 1.4 -nowarn WarnStaticImport.java + * compile/fail -Werror -nowarn WarnStaticImport.java + * compile/fail -Werror -Xlint:none WarnStaticImport.java */ import static sun.misc.VM.getFinalRefCount;
--- a/test/tools/javac/proprietary/WarnVariable.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/proprietary/WarnVariable.java Tue May 07 17:14:17 2013 -0700 @@ -26,11 +26,12 @@ * @bug 6380059 * @summary Emit warnings for proprietary packages in the boot class path * @author Peter von der Ah\u00e9 - * @compile WarnVariable.java - * @compile/fail -Werror WarnVariable.java - * @compile/fail -Werror -source 1.4 -nowarn WarnVariable.java - * @compile/fail -Werror -nowarn WarnVariable.java - * @compile/fail -Werror -Xlint:none WarnVariable.java + * @run main Test + * compile WarnVariable.java + * compile/fail -Werror WarnVariable.java + * compile/fail -Werror -source 1.4 -nowarn WarnVariable.java + * compile/fail -Werror -nowarn WarnVariable.java + * compile/fail -Werror -Xlint:none WarnVariable.java */ public class WarnVariable {
--- a/test/tools/javac/proprietary/WarnWildcard.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/proprietary/WarnWildcard.java Tue May 07 17:14:17 2013 -0700 @@ -26,11 +26,12 @@ * @bug 6380059 * @summary Emit warnings for proprietary packages in the boot class path * @author Peter von der Ah\u00e9 - * @compile WarnWildcard.java - * @compile/fail -Werror WarnWildcard.java - * @compile/fail -Werror -source 1.4 -nowarn WarnWildcard.java - * @compile/fail -Werror -nowarn WarnWildcard.java - * @compile/fail -Werror -Xlint:none WarnWildcard.java + * @run main Test + * compile WarnWildcard.java + * compile/fail -Werror WarnWildcard.java + * compile/fail -Werror -source 1.4 -nowarn WarnWildcard.java + * compile/fail -Werror -nowarn WarnWildcard.java + * compile/fail -Werror -Xlint:none WarnWildcard.java */ public class WarnWildcard {
--- a/test/tools/javac/tree/TreeKindTest.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/tree/TreeKindTest.java Tue May 07 17:14:17 2013 -0700 @@ -113,6 +113,26 @@ ok = ok & verify(k, i, i == AnnotationTree.class); break; + case MODULE: + ok = ok & verify(k, i, i == ModuleTree.class); + break; + + case MODULE_CLASS: + ok = ok & verify(k, i, i == ModuleClassTree.class); + break; + + case MODULE_PERMITS: + ok = ok & verify(k, i, i == ModulePermitsTree.class); + break; + + case MODULE_REQUIRES: + ok = ok & verify(k, i, i == ModuleRequiresTree.class); + break; + + case PACKAGE: + ok = ok & verify(k, i, i == PackageTree.class); + break; + case OTHER: ok = ok & verify(k, i, i == null); break;
--- a/test/tools/javac/varargs/6730476/T6730476b.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javac/varargs/6730476/T6730476b.java Tue May 07 17:14:17 2013 -0700 @@ -27,7 +27,7 @@ * * @summary invalid "unchecked generic array" warning * @author mcimadamore - * @compile T6730476b.java -Xlint -Werror + * @compile T6730476b.java -Xlint:all,-path -Werror * */
--- a/test/tools/javap/T6729471.java Thu Apr 25 09:24:40 2013 -0700 +++ b/test/tools/javap/T6729471.java Tue May 07 17:14:17 2013 -0700 @@ -31,14 +31,16 @@ import java.io.*; import java.net.*; import java.util.*; +import java.util.jar.*; +import java.util.zip.*; public class T6729471 { - public static void main(String... args) { + public static void main(String... args) throws Exception { new T6729471().run(); } - void run() { + void run() throws Exception { File testClasses = new File(System.getProperty("test.classes")); // simple class @@ -57,16 +59,29 @@ verify(new File(testClasses, "T6729471.class").toURI().toString(), "public static void main(java.lang.String...)"); + // jar url: local jar + File my_jar = createJar("my.jar", getClasses(Map.class)); + try { + verify("jar:" + my_jar.toURL() + "!/java/util/Map.class", + "public abstract boolean containsKey(java.lang.Object)"); + } catch (MalformedURLException e) { + error(e.toString()); + } + // jar url: rt.jar File java_home = new File(System.getProperty("java.home")); if (java_home.getName().equals("jre")) java_home = java_home.getParentFile(); File rt_jar = new File(new File(new File(java_home, "jre"), "lib"), "rt.jar"); - try { - verify("jar:" + rt_jar.toURL() + "!/java/util/Map.class", - "public abstract boolean containsKey(java.lang.Object)"); - } catch (MalformedURLException e) { - error(e.toString()); + if (rt_jar.exists()) { + try { + verify("jar:" + rt_jar.toURL() + "!/java/util/Map.class", + "public abstract boolean containsKey(java.lang.Object)"); + } catch (MalformedURLException e) { + error(e.toString()); + } + } else { + System.err.println("warning: rt.jar not found; test skipped"); } // jar url: ct.sym, if it exists @@ -78,8 +93,9 @@ } catch (MalformedURLException e) { error(e.toString()); } - } else - System.err.println("warning: ct.sym not found"); + } else { + System.err.println("warning: ct.sym not found; test skipped"); + } if (errors > 0) throw new Error(errors + " found."); @@ -116,5 +132,48 @@ throw new Error("javap reported error."); return output; } + + Map<String,byte[]> getClasses(Class... classes) throws IOException { + ClassLoader cl = getClass().getClassLoader(); + Map<String,byte[]> results = new HashMap<String, byte[]>(); + for (Class c: classes) { + String name = c.getName().replace(".", "/") + ".class"; + byte[] data = read(cl.getResourceAsStream(name)); + results.put(name, data); + } + return results; + } + + byte[] read(InputStream in) throws IOException { + try { + byte[] data = new byte[8192]; + int offset = 0; + int n; + while ((n = in.read(data, offset, data.length - offset)) >= 0) { + offset += n; + if (offset == data.length) + data = Arrays.copyOf(data, 2 * data.length); + } + return data; + } finally { + in.close(); + } + } + + File createJar(String name, Map<String, byte[]> entries) throws IOException { + File jar = new File(name); + OutputStream out = new FileOutputStream(jar); + try { + JarOutputStream jos = new JarOutputStream(out); + for (Map.Entry<String,byte[]> e: entries.entrySet()) { + jos.putNextEntry(new ZipEntry(e.getKey())); + jos.write(e.getValue()); + } + jos.close(); + } finally { + out.close(); + } + return jar; + } }