nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PackagesHelper.java
changeset 38897 b92825d7708c
parent 34551 24317dc1c751
child 41426 aa60c8d89a92
equal deleted inserted replaced
38840:7693aa00e131 38897:b92825d7708c
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package jdk.nashorn.tools.jjs;
    26 package jdk.nashorn.tools.jjs;
    27 
    27 
       
    28 import java.lang.reflect.Modifier;
    28 import java.io.IOException;
    29 import java.io.IOException;
    29 import java.io.File;
    30 import java.io.File;
    30 import java.net.URI;
    31 import java.net.URI;
    31 import java.nio.file.DirectoryStream;
    32 import java.nio.file.DirectoryStream;
    32 import java.nio.file.Files;
    33 import java.nio.file.Files;
    47 import javax.tools.JavaFileManager.Location;
    48 import javax.tools.JavaFileManager.Location;
    48 import javax.tools.JavaFileObject;
    49 import javax.tools.JavaFileObject;
    49 import javax.tools.StandardJavaFileManager;
    50 import javax.tools.StandardJavaFileManager;
    50 import javax.tools.StandardLocation;
    51 import javax.tools.StandardLocation;
    51 import javax.tools.ToolProvider;
    52 import javax.tools.ToolProvider;
       
    53 import jdk.nashorn.internal.runtime.Context;
    52 
    54 
    53 /**
    55 /**
    54  * A helper class to compute properties of a Java package object. Properties of
    56  * A helper class to compute properties of a Java package object. Properties of
    55  * package object are (simple) top level class names in that java package and
    57  * package object are (simple) top level class names in that java package and
    56  * immediate subpackages of that package.
    58  * immediate subpackages of that package.
    70      */
    72      */
    71     private static boolean isJavacAvailable() {
    73     private static boolean isJavacAvailable() {
    72         return compiler != null;
    74         return compiler != null;
    73     }
    75     }
    74 
    76 
       
    77     private final Context context;
    75     private final StandardJavaFileManager fm;
    78     private final StandardJavaFileManager fm;
    76     private final Set<JavaFileObject.Kind> fileKinds;
    79     private final Set<JavaFileObject.Kind> fileKinds;
    77     private final FileSystem jrtfs;
    80     private final FileSystem jrtfs;
    78 
    81 
    79     /**
    82     /**
    80      * Construct a new PackagesHelper.
    83      * Construct a new PackagesHelper.
    81      *
    84      *
    82      * @param classPath Class path to compute properties of java package objects
    85      * @param context the current Nashorn Context
    83      */
    86      */
    84     PackagesHelper(final String classPath) throws IOException {
    87     PackagesHelper(final Context context) throws IOException {
       
    88         this.context = context;
       
    89         final String classPath = context.getEnv()._classpath;
    85         if (isJavacAvailable()) {
    90         if (isJavacAvailable()) {
    86             fm = compiler.getStandardFileManager(null, null, null);
    91             fm = compiler.getStandardFileManager(null, null, null);
    87             fileKinds = EnumSet.of(JavaFileObject.Kind.CLASS);
    92             fileKinds = EnumSet.of(JavaFileObject.Kind.CLASS);
    88 
    93 
    89             if (classPath != null && !classPath.isEmpty()) {
    94             if (classPath != null && !classPath.isEmpty()) {
   164                         try (DirectoryStream<Path> ds2 = Files.newDirectoryStream(pkgUnderMod)) {
   169                         try (DirectoryStream<Path> ds2 = Files.newDirectoryStream(pkgUnderMod)) {
   165                             for (Path p : ds2) {
   170                             for (Path p : ds2) {
   166                                 String str = p.getFileName().toString();
   171                                 String str = p.getFileName().toString();
   167                                 // get rid of ".class", if any
   172                                 // get rid of ".class", if any
   168                                 if (str.endsWith(".class")) {
   173                                 if (str.endsWith(".class")) {
   169                                     props.add(str.substring(0, str.length() - ".class".length()));
   174                                     final String clsName = str.substring(0, str.length() - ".class".length());
   170                                 } else {
   175                                     if (clsName.indexOf('$') == -1 && isClassAccessible(pkg + "." + clsName)) {
       
   176                                         props.add(str);
       
   177                                     }
       
   178                                 } else if (isPackageAccessible(pkg + "." + str)) {
   171                                     props.add(str);
   179                                     props.add(str);
   172                                 }
   180                                 }
   173                             }
   181                             }
   174                         }
   182                         }
   175                     }
   183                     }
   191             final int nextDot = binaryName.indexOf('.', pkg.length() + 1);
   199             final int nextDot = binaryName.indexOf('.', pkg.length() + 1);
   192             final int start = pkg.length() + 1;
   200             final int start = pkg.length() + 1;
   193 
   201 
   194             if (nextDot != -1) {
   202             if (nextDot != -1) {
   195                 // subpackage - eg. "regex" for "java.util"
   203                 // subpackage - eg. "regex" for "java.util"
   196                 props.add(binaryName.substring(start, nextDot));
   204                 final String pkgName = binaryName.substring(start, nextDot);
       
   205                 if (isPackageAccessible(binaryName.substring(0, nextDot))) {
       
   206                     props.add(binaryName.substring(start, nextDot));
       
   207                 }
   197             } else {
   208             } else {
   198                 // class - filter out nested, inner, anonymous, local classes.
   209                 // class - filter out nested, inner, anonymous, local classes.
   199                 // Dynalink supported public nested classes as properties of
   210                 // Dynalink supported public nested classes as properties of
   200                 // StaticClass object anyway. We don't want to expose those
   211                 // StaticClass object anyway. We don't want to expose those
   201                 // "$" internal names as properties of package object.
   212                 // "$" internal names as properties of package object.
   202 
   213 
   203                 final String clsName = binaryName.substring(start);
   214                 final String clsName = binaryName.substring(start);
   204                 if (clsName.indexOf('$') == -1) {
   215                 if (clsName.indexOf('$') == -1 && isClassAccessible(binaryName)) {
   205                     props.add(clsName);
   216                     props.add(clsName);
   206                 }
   217                 }
   207             }
   218             }
   208         }
   219         }
   209     }
   220     }
   212     private static List<File> getFiles(final String classPath) {
   223     private static List<File> getFiles(final String classPath) {
   213         return Stream.of(classPath.split(File.pathSeparator))
   224         return Stream.of(classPath.split(File.pathSeparator))
   214                     .map(File::new)
   225                     .map(File::new)
   215                     .collect(Collectors.toList());
   226                     .collect(Collectors.toList());
   216     }
   227     }
       
   228 
       
   229     private boolean isClassAccessible(final String className) {
       
   230         try {
       
   231             final Class<?> clz = context.findClass(className);
       
   232             return Modifier.isPublic(clz.getModifiers());
       
   233         } catch (final ClassNotFoundException cnfe) {
       
   234         }
       
   235         return false;
       
   236     }
       
   237 
       
   238     private boolean isPackageAccessible(final String pkgName) {
       
   239         try {
       
   240             Context.checkPackageAccess(pkgName);
       
   241             return true;
       
   242         } catch (final SecurityException se) {
       
   243             return false;
       
   244         }
       
   245     }
   217 }
   246 }