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

Thu, 12 Oct 2017 19:50:01 +0800

author
aoqi
date
Thu, 12 Oct 2017 19:50:01 +0800
changeset 2702
9ca8d8713094
parent 2626
9113c7c8d902
parent 2525
2eb010b6cb22
child 2893
ca5783d9a597
permissions
-rw-r--r--

merge

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

mercurial