# HG changeset patch # User mchung # Date 1367972057 25200 # Node ID f9e6d666883e557b24e8d0f50a6c78ae2aee735d # Parent a1e10f3adc47c8602a72e43a41403a642e73e0b1# Parent 2985b07bd28816d5cf7bb01fa80e1c18a4c56321 Merge diff -r a1e10f3adc47 -r f9e6d666883e .hgtags --- 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 diff -r a1e10f3adc47 -r f9e6d666883e .jcheck/conf --- 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 diff -r a1e10f3adc47 -r f9e6d666883e make/build.properties --- 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 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 diff -r a1e10f3adc47 -r f9e6d666883e make/build.xml --- 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 @@ + + @@ -154,15 +156,36 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + filepath="${import.jdk}/src/share/classes" file="java/lang/module/ModuleInfo.java"/> + classpath="${import.jdk}/jre/lib/rt.jar" classname="java.lang.module.ModuleInfo"/> - - - - - - - - - - - - - - - - - - - + @@ -213,6 +211,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -222,6 +264,16 @@ + + + + + + @@ -513,9 +565,12 @@ **** javac targets. --> + + + + - + depends="build-bootstrap-classes-javac,build-bootstrap-module-langtools,-def-build-bootstrap-jar,-def-build-bootstrap-tool"> @@ -524,7 +579,7 @@ - + @@ -543,13 +598,42 @@ + + + + + + + + + + + + + + + + + - + + + + @@ -559,7 +643,7 @@ - + @@ -584,8 +668,13 @@ **** doclets targets. --> - + + + + + + @@ -617,22 +706,27 @@ **** javah targets. --> - + - - - - - + + + + + + + + @@ -650,11 +744,15 @@ **** javap targets. --> - + + + + + jarclasspath="javac.jar"/> @@ -662,14 +760,14 @@ - + - + @@ -770,6 +868,69 @@ **** Targets for Ant macro and task definitions. --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -817,7 +978,7 @@ - + @@ -827,6 +988,7 @@ + @@ -863,7 +1025,7 @@ debuglevel="${javac.debuglevel}"> - + @@ -878,6 +1040,11 @@ + + + + + @@ -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 @@ + + + + + + opts = new ArrayList(); + 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 opts) throws IOException, InterruptedException { + if (fork) { + List cmd = new ArrayList(); + 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 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; + +} diff -r a1e10f3adc47 -r f9e6d666883e make/tools/Jigsaw/JmodTask.java --- /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 opts = new ArrayList(); + 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 files = new ArrayList(); + + 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 opts = new ArrayList(); + 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 opts) throws IOException, InterruptedException { + if (fork) { + List cmd = new ArrayList(); + 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 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 args = new ArrayList(); +} diff -r a1e10f3adc47 -r f9e6d666883e make/tools/genstubs/GenStubs.java --- 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 defs = new ListBuffer(); 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 diff -r a1e10f3adc47 -r f9e6d666883e makefiles/BuildLangtools.gmk --- 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)) diff -r a1e10f3adc47 -r f9e6d666883e src/share/bin/launcher.sh-template --- 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} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/EntrypointDirectiveTree.java --- /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(); +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/ExportDirectiveTree.java --- /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(); +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/ModuleDirectiveTree.java --- /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 { } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/ModuleIdTree.java --- /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(); +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/ModuleQueryTree.java --- /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(); +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/ModuleTree.java --- /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 getDirectives(); + CharSequence getExtendedMetadata(); +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/PackageTree.java --- /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 getAnnotations(); + Tree getPackageId(); +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/PermitsDirectiveTree.java --- /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(); +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/ProvidesModuleDirectiveTree.java --- /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(); +} + diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/ProvidesServiceDirectiveTree.java --- /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(); +} + + diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/RequiresFlag.java --- /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 +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/RequiresModuleDirectiveTree.java --- /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 getFlags(); + ModuleQueryTree getModuleQuery(); +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/RequiresServiceDirectiveTree.java --- /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 getFlags(); + ExpressionTree getServiceName(); +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/Tree.java --- 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. */ diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/TreeVisitor.java --- 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); diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/tree/ViewDeclarationTree.java --- /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 getDirectives(); +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/util/SimpleTreeVisitor.java --- 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 implements TreeVisitor { +public class SimpleTreeVisitor implements TreeVisitor { 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); } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/source/util/TreeScanner.java --- 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; } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/classfile/AccessFlags.java --- 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 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 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 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 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; } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/classfile/Attribute.java --- 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); } } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/classfile/ClassTranslator.java --- 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 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 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 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 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 translations) { CONSTANT_MethodHandle_info info2 = (CONSTANT_MethodHandle_info) translations.get(info); if (info2 == null) { diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/classfile/ClassWriter.java --- 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) { diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/classfile/ConstantPool.java --- 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 accept(Visitor 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 accept(Visitor 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 accept(Visitor 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 accept(Visitor visitor, D data) { + return visitor.visitNameAndType(this, data); + } + public final int name_index; public final int type_index; } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/classfile/Dependencies.java --- 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); diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/classfile/ModuleData_attribute.java --- /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. + * + *

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. + */ +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 accept(Visitor visitor, D data) { + return visitor.visitModuleData(this, data); + } + + public final int data_index; +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/classfile/ModuleProvides_attribute.java --- /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. + * + *

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. + */ +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 accept(Visitor 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; + } + } +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/classfile/ModuleRequires_attribute.java --- /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. + * + *

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. + */ +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 accept(Visitor 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; + } +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/classfile/Module_attribute.java --- /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. + * + *

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. + */ +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 accept(Visitor visitor, D data) { + return visitor.visitModule(this, data); + } + + public final int module_id_index; + +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java --- 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 DiagnosticListener wrap(DiagnosticListener dl) { - if (isTrusted(dl)) + if (dl == null || isTrusted(dl)) return dl; return new WrappedDiagnosticListener(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 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 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); } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/code/Directive.java --- /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. + * + *

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. + */ +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 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 accept(Visitor visitor, P data); + + static List filter(List directives, Kind kind, Class clazz) { + ListBuffer 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 flags; + + public RequiresModuleDirective(ModuleQuery moduleQuery) { + this(moduleQuery, EnumSet.noneOf(RequiresFlag.class)); + } + + public RequiresModuleDirective(ModuleQuery moduleQuery, Set 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 accept(Visitor 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 flags; + + public RequiresServiceDirective(ClassSymbol sym, Set 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 accept(Visitor 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 accept(Visitor 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 accept(Visitor 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 accept(Visitor 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 accept(Visitor 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 accept(Visitor 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 directives; + + public ViewDeclaration(Name name, List directives) { + this.name = name; + this.directives = directives; + } + + public ViewDeclaration(List 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 list = + filter(directives, Kind.ENTRYPOINT, EntrypointDirective.class); + return list.isEmpty() ? null : list.head.sym; + } + + public List getAliases() { + return filter(directives, Kind.PROVIDES_MODULE, ProvidesModuleDirective.class); + } + + public List getServices() { + return filter(directives, Kind.PROVIDES_SERVICE, ProvidesServiceDirective.class); + } + + public List getExports() { + return filter(directives, Kind.EXPORTS, ExportsDirective.class); + } + + public List 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 accept(Visitor visitor, P data) { + return visitor.visitView(this, data); + } + } + + public static interface Visitor { + 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 implements Visitor { + 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 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 implements Visitor { + + + /** 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 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); + } + + } +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/code/Flags.java --- 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; } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/code/Kinds.java --- 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; diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/code/ModuleId.java --- /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]} + * + *

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. + */ +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"; + } + +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/code/ModuleQuery.java --- /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} + * + *

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. + */ +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"; + } + +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/code/Printer.java --- 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") diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/code/Scope.java --- 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) { diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/code/Source.java --- 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; } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/code/Symbol.java --- 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 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 getRequiredModules() { + return Directive.filter(directives, Directive.Kind.REQUIRES_MODULE, + RequiresModuleDirective.class); + } + + public List 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 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 getViews() { + ListBuffer 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 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 getExports(final ViewDeclaration viewDecl) { + final Set exports = new LinkedHashSet(); + Directive.Scanner s = new Directive.Scanner() { + @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) ? "" + : (fullname.isEmpty()) ? "" + : 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 accept(ElementVisitor 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 diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/code/Symtab.java --- 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 operatorNames = new HashSet(); + /** 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 packages = new HashMap(); + /** A hashtable containing the encountered modules. + * the table should be updated from outside to reflect modules + * found in the host environment. + */ + public Map allModules = new LinkedHashMap(); + 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 accept(ElementVisitor 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); } } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/code/Type.java --- 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 accept(Type.Visitor 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 accept(TypeVisitor 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); diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java --- 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 s) { + // Error? + return t; + } + + @Override public Type visitType(Type t, List s) { return new AnnotatedType(s, t); } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/code/TypeTag.java --- 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, diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/code/Types.java --- 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); } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/comp/Attr.java --- 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 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 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 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 merge(ListBuffer primary, List secondary) { + Set set = new LinkedHashSet(); + set.addAll(primary); + for (Directive d: secondary) { + if (d.getKind() != Directive.Kind.VIEW) + set.add(d); + } + ListBuffer results = new ListBuffer(); + 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 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 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 diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/comp/AttrContext.java --- 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; diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/comp/Check.java --- 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 || diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/comp/Enter.java --- 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 moduleEnv(JCModuleDecl tree, Env env) { + assert tree.sym != null; + Env 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 topEnv = topLevelEnv(tree); + + Env treeEnv = topLevelEnv(tree); // Save environment of package-info.java file. - if (isPkgInfo) { + if (isPackageInfo) { + addEnv = (pd != null) && pd.annots.nonEmpty(); + Env 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 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 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 prevUncompleted = uncompleted; - if (memberEnter.completionEnabled) uncompleted = new ListBuffer(); + if (memberEnter.completionEnabled) + uncompleted = new ListBuffer(); 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 topEnv = topLevelEnv(tree); - memberEnter.memberEnter(tree, topEnv); + Env treeEnv = topLevelEnv(tree); + memberEnter.memberEnter(tree, treeEnv); log.useSource(prev); } } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/comp/Flow.java --- 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 { diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/comp/Lower.java --- 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.nil(), - null, List.nil(), List.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.nil(), tree.sym.module_info); + } + + private void createInfoClass(List annots, ClassSymbol c) { + long flags = Flags.ABSTRACT | Flags.INTERFACE; + JCClassDecl infoClass = + make.ClassDef(make.Modifiers(flags, annots), + c.name, List.nil(), + null, List.nil(), List.nil()); + infoClass.sym = c; + translated.append(infoClass); + } + public void visitClassDef(JCClassDecl tree) { ClassSymbol currentClassPrev = currentClass; MethodSymbol currentMethodSymPrev = currentMethodSym; diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/comp/MemberEnter.java --- 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 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); diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/comp/ModuleContext.java --- /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. + * + *

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. + */ +public class ModuleContext { + + ModuleContext() { + requiresBaseModule = true; + directives = new ListBuffer(); + directiveForTree = new HashMap(); + directiveIndex = new HashMap>(); + } + + ModuleContext dup() { + return new ModuleContext(); + } + + void addDirective(Directive d, JCModuleDirective tree, Name name) { + directives.add(d); + directiveForTree.put(tree, d); + Set set = directiveIndex.get(name); + if (set == null) + directiveIndex.put(name, (set = new LinkedHashSet())); + set.add(d); + } + + Collection getDirectives(Name name) { + Set set = directiveIndex.get(name); + return (set != null) ? set : Collections.emptySet(); + } + + Collection getDirectives(Directive.Kind kind, Name name) { + List list = null; + Set set = directiveIndex.get(name); + if (set != null) { + for (Directive d: set) { + if (d.getKind() == kind) { + if (list == null) + list = new ArrayList(); + list.add(d); + } + } + } + return (list == null) ? Collections.emptySet() : list; + } + + + + final ListBuffer directives; + final Map directiveForTree; + final Map> directiveIndex; + + boolean requiresBaseModule; + boolean isPlatformModule; + boolean hasEntrypoint; +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/comp/Modules.java --- /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.*; + +/** + *

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. + */ +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 rootLocns = new LinkedHashSet(); + + final Map allModules; + + /** The symbol currently being analyzed. */ + ModuleSymbol currSym; + + Env env; + Map> moduleEnvs = new HashMap>(); + + /** 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; + } + + void acceptAll(List trees) { + for (List l = trees; l.nonEmpty(); l = l.tail) + l.head.accept(this); + } + + public ModuleContext getModuleContext(JCModuleDecl decl) { + Env 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 menv = env.dup(tree, new ModuleContext()); + moduleEnvs.put(sym, menv); + Env 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(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 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 viewDirectives; + Env 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 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 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 namedModules = new ListBuffer(); + 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 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 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 locns = new ListBuffer(); + 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 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 loader = ServiceLoader.load(ModuleResolver.class); +// // for now, use the first available, if any +// for (Iterator 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 c = + Class.forName(jigsawModuleResolver).asSubclass(ModuleResolver.class); + Constructor 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 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 trees) { + if (result != null) + return; + + for (List l = trees; l.nonEmpty(); l = l.tail) { + l.head.accept(this); + if (result != null) + return; + } + } + + 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 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 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 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 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 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 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 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 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 String toString(Iterable 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 resolve( + Iterable roots, + Iterable modules); + + boolean isPackageVisible(ModuleSymbol msym, PackageSymbol psym); + } + + class ZeroMod implements ModuleResolver { + private ErrorHandler errorHandler; + + ZeroMod(ErrorHandler e) { + errorHandler = e; + } + + public Iterable resolve( + Iterable roots, + Iterable modules) + { + DEBUG("ZeroMod: roots: " + Modules.toString(roots)); + DEBUG("ZeroMod: modules: " + Modules.toString(modules)); + roots.getClass(); + modules.getClass(); + + moduleTable = buildModuleTable(modules); + List rootNodes = getNodes(roots); + tarjan(rootNodes); + + DEBUG("ZeroMod.NODE MAP {"); + for (Node n: nodeMap.values()) + DEBUG(" Node " + n + " " + n.scc); + DEBUG("}"); + + ListBuffer results = new ListBuffer(); + 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 results) { + for (Node n: scc.nodes) + results.add(n.sym); + for (SCC child: scc.getChildren()) + getVisibleModules(child, results); + } + + private Map> buildModuleTable( + Iterable modules) { + Map> table = new HashMap>(); + // 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 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()); + 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> table, + ModuleSymbol sym, ModuleId mid) { + Map versions = table.get(mid.name); + if (versions == null) + table.put(mid.name, versions = new HashMap()); + 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 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> 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 getNodes(Iterable syms) { + ListBuffer lb = new ListBuffer(); + 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 nodeMap= new HashMap(); + + private class Node implements Comparable { + final ModuleSymbol sym; + SCC scc; + int index = -1; + int lowlink; + boolean active; + + Node(ModuleSymbol sym) { + this.sym = sym; + } + + Iterable getDependencies() { + DEBUG("ZeroMod.Node.getDependencies: " + sym + " " + sym.getRequiredModules()); + ListBuffer nodes = new ListBuffer(); + 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 getChildren() { + if (children == null) { + children = new LinkedHashSet(); + 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 nodes = new TreeSet(); + private Set children; + } + + // Tarjan's algorithm to determine strongly connected components of a + // directed graph in linear time. + + void tarjan(Iterable 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 stack = new ArrayList(); + } +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/comp/Resolve.java --- 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 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 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 diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/file/BaseFileObject.java --- 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. */ -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 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; } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/file/CompositeLocation.java --- /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 locations; + final String name; + private static int count; // FIXME, move count/name to creator, or move CompositeLocation to Locations + + CompositeLocation(Iterable locations, JavaFileManager fileManager) { + this.locations = locations; + this.fileManager = fileManager; + ListBuffer names = new ListBuffer(); + for (Location l: locations) + names.add(l.getName()); + name = "multiLocation#" + (count++) + names.toString(); + } + + @Override // javax.tools.ExtendedLocation + public Iterable list(String packageName, Set kinds, boolean recurse) throws IOException { + ListBuffer results = new ListBuffer(); + for (Location l: locations) { + Iterable 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 getLocation() { + if (!(fileManager instanceof StandardJavaFileManager)) + throw new IllegalStateException(); + StandardJavaFileManager fm = (StandardJavaFileManager) fileManager; + ListBuffer files = new ListBuffer(); + for (Location l: locations) { + Iterable 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(); + } +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/file/JavacFileManager.java --- 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. */ -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 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 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> moduleLocations = + new LinkedHashMap>(); + + @Override // javax.tools.ModuleFileManager + public Iterable getModuleLocations(Location locn) { + //System.err.println("JavacFileManager.getModuleLocations " + getModuleMode() + " " + locn); + + Iterable result = moduleLocations.get(locn); + if (result == null) { + Iterable files = locations.getLocation(locn); + if (files == null) + result = List.nil(); + else { + Set locns = new LinkedHashSet(); + 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 locationCache = new HashMap(); + + @Override // javax.tools.ModuleFileManager + public Location join(Iterable 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 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 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 results = new ListBuffer(); + 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 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 path = getLocation(location); @@ -604,6 +792,7 @@ return getClassLoader(lb.toArray(new URL[lb.size()])); } + @Override // javax.tools.JavaFileManager public Iterable list(Location location, String packageName, Set kinds, @@ -611,23 +800,35 @@ throws IOException { // validatePackageName(packageName); + nullCheck(location); nullCheck(packageName); nullCheck(kinds); - Iterable path = getLocation(location); - if (path == null) + if (location instanceof ExtendedLocation) { + return ((ExtendedLocation) location).list(packageName, kinds, recurse); + } + + Iterable files = locations.getLocation(location); + if (files == null) return List.nil(); RelativeDirectory subdirectory = RelativeDirectory.forPackage(packageName); ListBuffer results = new ListBuffer(); - 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 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 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 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 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 getJavaFileObjectsFromFiles( Iterable files) { @@ -782,23 +1015,32 @@ else result = new ArrayList(); 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 getJavaFileObjects(File... files) { return getJavaFileObjectsFromFiles(Arrays.asList(nullCheck(files))); } + @Override // javax.tools.StandardJavaFileManager public void setLocation(Location location, Iterable path) throws IOException { nullCheck(location); locations.setLocation(location, path); + locationCache.clear(); } - public Iterable getLocation(Location location) { + @Override // javax.tools.StandardJavaFileManager + public Iterable getLocation(Location location) { + return locations.getLocation(location); + } + + @Deprecated // remove uses of this method + Iterable getEntriesForLocation(Location location) { nullCheck(location); return locations.getLocation(location); } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/file/Locations.java --- 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} form). + * Collection form). * *

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 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 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 { + class Path extends LinkedHashSet { private static final long serialVersionUID = 0; private boolean expandJarClassPaths = false; - private Set canonicalValues = new HashSet(); 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 entries) { + for (PathEntry e: entries) + add(e); + } + + Collection toFiles() { + ListBuffer files = new ListBuffer(); + 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 getLocation(); - /** @see StandardJavaFileManager#setLocation */ + /** @see StandardJavaFileManager#setLocation. */ abstract void setLocation(Iterable 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 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 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(); diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/file/RegularFileObject.java --- 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 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(); diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/file/SymbolArchive.java --- 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(); diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/file/ZipArchive.java --- 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; /** *

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>(); 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 diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java --- 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()); + } } } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/jigsaw/JavacCatalog.java --- /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> moduleMap = + new HashMap>(); + 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 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 map = moduleMap.get(n); + if (map == null) + moduleMap.put(n, map = new HashMap()); + if (v != null) + map.put(v, msym); + else + map.put(nullVersion, msym); + } + + @Override + protected void gatherLocalModuleIds(String moduleName, Set mids) throws IOException { + DEBUG("JavacCatalog.gatherLocalModuleIds: " + moduleName); + if (moduleName != null) { + Map 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 mids) throws IOException { + DEBUG("JavacCatalog.gatherLocalDeclaringModuleIds"); + for (Map 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 map, + String mn, Set 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 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 requiresModules; + Map views; + + JavacModuleInfo(ModuleSymbol msym) { + msym.getClass(); // null check + DEBUG("JavacModuleInfo: msym: " + msym); + + this.msym = msym; + this.views = new HashMap(); + + 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 permits = new LinkedHashSet(); + for (PermitsDirective d : v.getPermits()) { + permits.add(d.moduleId.name.toString()); // FIXME: validate name? + } + + Set exports = new LinkedHashSet(); + + Set provides = new LinkedHashSet(); + for (ProvidesModuleDirective d : v.getAliases()) { + provides.add(getModuleId(d.moduleId)); + } + + Map> services = new LinkedHashMap>(); + for (ProvidesServiceDirective s : v.getServices()) { + String sn = new String(ClassFile.externalize(s.service.flatname)); + String pn = new String(ClassFile.externalize(s.impl.flatname)); + Set providers = services.get(sn); + if (providers == null) { + providers = new LinkedHashSet(); + 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.emptySet(), + Collections.emptySet(), + Collections.emptySet(), + Collections.>emptyMap())); + } + + requiresModules = new LinkedHashSet(); + for (RequiresModuleDirective r: msym.getRequiredModules()) { + DEBUG("JavacModuleInfo: require " + r); + ModuleIdQuery q = getModuleQuery(r.moduleQuery); + EnumSet 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 requiresModules() { + return requiresModules; + } + + public Set requiresServices() { + return Collections.emptySet(); + } + + public ModuleView defaultView() { + return views.get(id); + } + + public Set views() { + return Collections.unmodifiableSet(new HashSet(views.values())); + } + } + + class JavacModuleView + implements ModuleView + { + private final ModuleInfo mi; + private final ModuleId id; + private final Set exports; + private final Set aliases; + private final Map> services; + private final Set permits; + private final String mainClass; + + JavacModuleView(ModuleInfo mi, + ModuleId id, + String mainClass, + Set aliases, + Set exports, + Set permits, + Map> 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 aliases() { + return Collections.unmodifiableSet(aliases); + } + + public Set exports() { + return Collections.unmodifiableSet(exports); + } + + public Set permits() { + return Collections.unmodifiableSet(permits); + } + + public Map> 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 + + " }"; + } + } +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/jigsaw/JigsawLibraryLocation.java --- /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 list(String packageName, Set kinds, boolean recurse) + throws IOException { + // only Kind.CLASS supported + if (!kinds.contains(Kind.CLASS)) + return Collections.emptySet(); + ListBuffer results = new ListBuffer(); + packageName = normalize(packageName); + String subpackagePrefix = packageName + "."; + for (Library l = library; l != null; l = l.parent()) { + List 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(); + } + } +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/jigsaw/JigsawModuleResolver.java --- /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 config; + ClassReader reader; + Names names; + Symtab syms; + Debug debug; + Log log; + + Map 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 resolve( + Iterable roots, + Iterable modules) { + if (debug.isEnabled()) + debug.println("JigsawModuleResolver starting"); + + catalog.init(modules); + Collection jigsawRootQueries = new LinkedHashSet(); + 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 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 rootContexts = new ListBuffer(); + for (java.lang.module.ModuleId mid: config.roots()) { + PathContext pcx = config.getContextForModuleName(mid.name()); + rootContexts.add(pcx); + } + + Tarjan t = new Tarjan(rootContexts) { + @Override + protected Iterable getDependencies(PathContext pcx) { + return pcx.remoteContexts(); + } + }; + + ListBuffer results = new ListBuffer(); + views = new HashMap(); + // 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 getDirectives(ModuleInfo minfo) { + ListBuffer lb = new ListBuffer(); + for (ViewDependence vd: minfo.requiresModules()) { + Set 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 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 vl = new ListBuffer(); + 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 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> 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 set = visiblePackages.get(msym); + if (set == null) { + set = new HashSet(); + for (Directive.RequiresModuleDirective d: msym.getRequiredModules()) { + addExportsForView(set, d.moduleQuery.name.toString()); + } + visiblePackages.put(msym, set); + } + return set.contains(psym); + } + + private void addExportsForView(Set 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> visiblePackages = + new HashMap>(); + + 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 { + protected Tarjan(Iterable 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 list() { + List rootNodes = getNodes(roots); + for (Node node: rootNodes) { + if (node.index == -1) + tarjan(node); + } + LinkedHashSet results = new LinkedHashSet(); + 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 getDependencies(T t); + + protected String toString(T t) { + return t.toString(); + } + + private void list(SCC scc, LinkedHashSet results) { + for (Node n: scc.nodes) + results.add(n.t); + for (SCC child: scc.getChildren()) + list(child, results); + } + + private List getNodes(Iterable elems) { + ListBuffer lb = new ListBuffer(); + 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 nodeMap= new HashMap(); + + + // 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 roots; + private int index = 0; + private ArrayList stack = new ArrayList(); + + private class Node implements Comparable { + final T t; + SCC scc; + int index = -1; + int lowlink; + boolean active; + + Node(T t) { + this.t = t; + } + + Iterable getDependencies() { + ListBuffer nodes = new ListBuffer(); + 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 getChildren() { + if (children == null) { + children = new LinkedHashSet(); + 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 nodes = new TreeSet(); + private Set children; + } + } + +} diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/jvm/ClassFile.java --- 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; diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/jvm/ClassReader.java --- 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 packages; + /** A hashtable giving the module for each module location. + * + */ + private Map 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(); classes = new HashMap(); + allModules = new HashMap(); } 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); } + // /************************************************************************ * Error Diagnoses ***********************************************************************/ @@ -349,7 +378,9 @@ currentClassFile, diagFactory.fragment(key, args)); } - + // + + // /************************************************************************ * Buffer Access ***********************************************************************/ @@ -429,6 +460,9 @@ throw new AssertionError(e); } } + // + + // /************************************************************************ * 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 readRequiresFlags(int flags) { + Set 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)); + } + // + + // + /************************************************************************ * Reading Types ***********************************************************************/ @@ -905,6 +994,9 @@ throw badClassFile("undecl.type.var", name); } } + // + + // /************************************************************************ * 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 directives = + (viewName == null) ? msym.directives : List.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 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 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; } + // + + // /************************************************************************ * Reading Java-language annotations @@ -1908,6 +2102,7 @@ } } } + // class TypeAnnotationCompleter extends AnnotationCompleter { @@ -1942,6 +2137,7 @@ } } + // /************************************************************************ * 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); } + // + + // /************************************************************************ * Adjusting flags @@ -2297,6 +2505,9 @@ long adjustClassFlags(long flags) { return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded } + // + + // /************************************************************************ * 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; } + // + + // /************************************************************************ * 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 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 kinds = getPackageFileKinds(); + Set classKinds = EnumSet.copyOf(kinds); classKinds.remove(JavaFileObject.Kind.SOURCE); boolean wantClassFiles = !classKinds.isEmpty(); @@ -2769,17 +3014,16 @@ Location location, Iterable 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 @@ } } } + // + + // + +/************************************************************************ + * 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.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; + } + + // /** Output for "-checkclassfile" option. * @param key The key to look up the correct internationalized string. @@ -2802,6 +3104,8 @@ throws CompletionFailure; } + // + /** * 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(); } } + // } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java --- 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 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 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 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 aliases = v.getAliases(); + databuf.appendChar(aliases.size()); + for (ProvidesModuleDirective a: aliases) + databuf.appendChar(pool.put(a.moduleId)); + // services + List 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 exports = sym.getExports(v); + databuf.appendChar(exports.size()); + for (PackageSymbol e: exports) { + databuf.appendChar(pool.put(names.fromUtf(externalize(e.flatName())))); + } + // permits + List 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); diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/jvm/Pool.java --- 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. * *

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); diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/jvm/Target.java --- 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; + } } diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/main/JavaCompiler.java --- 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. */ -public class JavaCompiler implements ClassReader.SourceCompleter { +public class JavaCompiler { /** The context key for the compiler. */ protected static final Context.Key compilerKey = new Context.Key(); @@ -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.nil(), - null, List.nil()); + JCCompilationUnit tree = make.TopLevel(List.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.nil(), null, List.nil()); + JCCompilationUnit toplevel = make.TopLevel(List.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.nil(), null, List.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.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; diff -r a1e10f3adc47 -r f9e6d666883e src/share/classes/com/sun/tools/javac/main/Main.java --- 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