src/share/classes/com/sun/tools/jdeps/PlatformClassPath.java

Sat, 07 Nov 2020 10:30:02 +0800

author
aoqi
date
Sat, 07 Nov 2020 10:30:02 +0800
changeset 3938
93012e2a5d1d
parent 2893
ca5783d9a597
permissions
-rw-r--r--

Added tag mips-jdk8u275-b01 for changeset eb6ee6a5f2fe

     1 /*
     2  * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 package com.sun.tools.jdeps;
    27 import com.sun.tools.classfile.Annotation;
    28 import com.sun.tools.classfile.ClassFile;
    29 import com.sun.tools.classfile.ConstantPool;
    30 import com.sun.tools.classfile.ConstantPoolException;
    31 import com.sun.tools.classfile.RuntimeAnnotations_attribute;
    32 import com.sun.tools.classfile.Dependencies.ClassFileError;
    33 import java.io.IOException;
    34 import java.nio.file.FileVisitResult;
    35 import java.nio.file.Files;
    36 import java.nio.file.Path;
    37 import java.nio.file.Paths;
    38 import java.nio.file.SimpleFileVisitor;
    39 import java.nio.file.attribute.BasicFileAttributes;
    40 import java.util.*;
    42 import static com.sun.tools.classfile.Attribute.*;
    44 /**
    45  * ClassPath for Java SE and JDK
    46  */
    47 class PlatformClassPath {
    48     private static final List<String> NON_PLATFORM_JARFILES =
    49         Arrays.asList("alt-rt.jar", "ant-javafx.jar", "javafx-mx.jar");
    50     private static final List<Archive> javaHomeArchives = init();
    52     static List<Archive> getArchives() {
    53         return javaHomeArchives;
    54     }
    56     private static List<Archive> init() {
    57         List<Archive> result = new ArrayList<>();
    58         Path home = Paths.get(System.getProperty("java.home"));
    59         try {
    60             if (home.endsWith("jre")) {
    61                 // jar files in <javahome>/jre/lib
    62                 result.addAll(addJarFiles(home.resolve("lib")));
    63                 if (home.getParent() != null) {
    64                     // add tools.jar and other JDK jar files
    65                     Path lib = home.getParent().resolve("lib");
    66                     if (Files.exists(lib)) {
    67                         result.addAll(addJarFiles(lib));
    68                     }
    69                 }
    70             } else if (Files.exists(home.resolve("lib"))) {
    71                 // either a JRE or a jdk build image
    72                 Path classes = home.resolve("classes");
    73                 if (Files.isDirectory(classes)) {
    74                     // jdk build outputdir
    75                     result.add(new JDKArchive(classes));
    76                 }
    77                 // add other JAR files
    78                 result.addAll(addJarFiles(home.resolve("lib")));
    79             } else {
    80                 throw new RuntimeException("\"" + home + "\" not a JDK home");
    81             }
    82             return result;
    83         } catch (IOException e) {
    84             throw new Error(e);
    85         }
    86     }
    88     private static List<Archive> addJarFiles(final Path root) throws IOException {
    89         final List<Archive> result = new ArrayList<>();
    90         final Path ext = root.resolve("ext");
    91         Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
    92             @Override
    93             public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
    94                 throws IOException
    95             {
    96                 if (dir.equals(root) || dir.equals(ext)) {
    97                     return FileVisitResult.CONTINUE;
    98                 } else {
    99                     // skip other cobundled JAR files
   100                     return FileVisitResult.SKIP_SUBTREE;
   101                 }
   102             }
   103             @Override
   104             public FileVisitResult visitFile(Path p, BasicFileAttributes attrs)
   105                 throws IOException
   106             {
   107                 String fn = p.getFileName().toString();
   108                 if (fn.endsWith(".jar")) {
   109                     // JDK may cobundle with JavaFX that doesn't belong to any profile
   110                     // Treat jfxrt.jar as regular Archive
   111                     result.add(NON_PLATFORM_JARFILES.contains(fn)
   112                                    ? Archive.getInstance(p)
   113                                    : new JDKArchive(p));
   114                 }
   115                 return FileVisitResult.CONTINUE;
   116             }
   117         });
   118         return result;
   119     }
   121     /**
   122      * A JDK archive is part of the JDK containing the Java SE API
   123      * or implementation classes (i.e. JDK internal API)
   124      */
   125     static class JDKArchive extends Archive {
   126         private static List<String> PROFILE_JARS = Arrays.asList("rt.jar", "jce.jar");
   127         // Workaround: The following packages are not annotated as jdk.Exported
   128         private static List<String> EXPORTED_PACKAGES = Arrays.asList(
   129                 "javax.jnlp",
   130                 "org.w3c.dom.css",
   131                 "org.w3c.dom.html",
   132                 "org.w3c.dom.stylesheets",
   133                 "org.w3c.dom.xpath"
   134         );
   135         public static boolean isProfileArchive(Archive archive) {
   136             if (archive instanceof JDKArchive) {
   137                 return PROFILE_JARS.contains(archive.getName());
   138             }
   139             return false;
   140         }
   142         private final Map<String,Boolean> exportedPackages = new HashMap<>();
   143         private final Map<String,Boolean> exportedTypes = new HashMap<>();
   144         JDKArchive(Path p) throws IOException {
   145             super(p, ClassFileReader.newInstance(p));
   146         }
   148         /**
   149          * Tests if a given fully-qualified name is an exported type.
   150          */
   151         public boolean isExported(String cn) {
   152             int i = cn.lastIndexOf('.');
   153             String pn = i > 0 ? cn.substring(0, i) : "";
   155             boolean isJdkExported = isExportedPackage(pn);
   156             if (exportedTypes.containsKey(cn)) {
   157                 return exportedTypes.get(cn);
   158             }
   159             return isJdkExported;
   160         }
   162         /**
   163          * Tests if a given package name is exported.
   164          */
   165         public boolean isExportedPackage(String pn) {
   166             if (Profile.getProfile(pn) != null) {
   167                 return true;
   168             }
   169             // special case for JavaFX and APIs that are not annotated with @jdk.Exported)
   170             if (EXPORTED_PACKAGES.contains(pn) || pn.startsWith("javafx.")) {
   171                 return true;
   172             }
   173             return exportedPackages.containsKey(pn) ? exportedPackages.get(pn) : false;
   174         }
   176         private static final String JDK_EXPORTED_ANNOTATION = "Ljdk/Exported;";
   177         private Boolean isJdkExported(ClassFile cf) throws ConstantPoolException {
   178             RuntimeAnnotations_attribute attr = (RuntimeAnnotations_attribute)
   179                     cf.attributes.get(RuntimeVisibleAnnotations);
   180             if (attr != null) {
   181                 for (int i = 0; i < attr.annotations.length; i++) {
   182                     Annotation ann = attr.annotations[i];
   183                     String annType = cf.constant_pool.getUTF8Value(ann.type_index);
   184                     if (JDK_EXPORTED_ANNOTATION.equals(annType)) {
   185                         boolean isJdkExported = true;
   186                         for (int j = 0; j < ann.num_element_value_pairs; j++) {
   187                             Annotation.element_value_pair pair = ann.element_value_pairs[j];
   188                             Annotation.Primitive_element_value ev = (Annotation.Primitive_element_value) pair.value;
   189                             ConstantPool.CONSTANT_Integer_info info = (ConstantPool.CONSTANT_Integer_info)
   190                                     cf.constant_pool.get(ev.const_value_index);
   191                             isJdkExported = info.value != 0;
   192                         }
   193                         return Boolean.valueOf(isJdkExported);
   194                     }
   195                 }
   196             }
   197             return null;
   198         }
   200         void processJdkExported(ClassFile cf) throws IOException {
   201             try {
   202                 String cn = cf.getName();
   203                 String pn = cn.substring(0, cn.lastIndexOf('/')).replace('/', '.');
   205                 Boolean b = isJdkExported(cf);
   206                 if (b != null) {
   207                     exportedTypes.put(cn.replace('/', '.'), b);
   208                 }
   209                 if (!exportedPackages.containsKey(pn)) {
   210                     // check if package-info.class has @jdk.Exported
   211                     Boolean isJdkExported = null;
   212                     ClassFile pcf = reader().getClassFile(cn.substring(0, cn.lastIndexOf('/')+1) + "package-info");
   213                     if (pcf != null) {
   214                         isJdkExported = isJdkExported(pcf);
   215                     }
   216                     if (isJdkExported != null) {
   217                         exportedPackages.put(pn, isJdkExported);
   218                     }
   219                 }
   220             } catch (ConstantPoolException e) {
   221                 throw new ClassFileError(e);
   222             }
   223         }
   224     }
   225 }

mercurial