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

Thu, 17 Jul 2014 15:23:08 -0700

author
mchung
date
Thu, 17 Jul 2014 15:23:08 -0700
changeset 2538
1e39ae45d8ac
parent 2139
defadd528513
child 2626
9113c7c8d902
permissions
-rw-r--r--

8029548: (jdeps) use @jdk.Exported to determine supported vs JDK internal API
8031092: jdeps does not recognize --help option.
8048063: (jdeps) Add filtering capability
Reviewed-by: alanb, dfuchs

mchung@1472 1 /*
mchung@2538 2 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
mchung@1472 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mchung@1472 4 *
mchung@1472 5 * This code is free software; you can redistribute it and/or modify it
mchung@1472 6 * under the terms of the GNU General Public License version 2 only, as
mchung@1472 7 * published by the Free Software Foundation. Oracle designates this
mchung@1472 8 * particular file as subject to the "Classpath" exception as provided
mchung@1472 9 * by Oracle in the LICENSE file that accompanied this code.
mchung@1472 10 *
mchung@1472 11 * This code is distributed in the hope that it will be useful, but WITHOUT
mchung@1472 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mchung@1472 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mchung@1472 14 * version 2 for more details (a copy is included in the LICENSE file that
mchung@1472 15 * accompanied this code).
mchung@1472 16 *
mchung@1472 17 * You should have received a copy of the GNU General Public License version
mchung@1472 18 * 2 along with this work; if not, write to the Free Software Foundation,
mchung@1472 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mchung@1472 20 *
mchung@1472 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mchung@1472 22 * or visit www.oracle.com if you need additional information or have any
mchung@1472 23 * questions.
mchung@1472 24 */
mchung@1472 25 package com.sun.tools.jdeps;
mchung@1472 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;
mchung@1472 33 import java.io.IOException;
mchung@1472 34 import java.nio.file.FileVisitResult;
mchung@1472 35 import java.nio.file.Files;
mchung@1472 36 import java.nio.file.Path;
mchung@2139 37 import java.nio.file.Paths;
mchung@1472 38 import java.nio.file.SimpleFileVisitor;
mchung@1472 39 import java.nio.file.attribute.BasicFileAttributes;
mchung@1472 40 import java.util.*;
mchung@1472 41
mchung@2538 42 import static com.sun.tools.classfile.Attribute.*;
mchung@2538 43
mchung@1472 44 /**
mchung@1472 45 * ClassPath for Java SE and JDK
mchung@1472 46 */
mchung@1472 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();
mchung@2139 51
mchung@1472 52 static List<Archive> getArchives() {
mchung@1472 53 return javaHomeArchives;
mchung@1472 54 }
mchung@1472 55
mchung@2139 56 private static List<Archive> init() {
mchung@2139 57 List<Archive> result = new ArrayList<>();
mchung@2139 58 Path home = Paths.get(System.getProperty("java.home"));
mchung@2139 59 try {
mchung@2139 60 if (home.endsWith("jre")) {
mchung@2139 61 // jar files in <javahome>/jre/lib
mchung@2139 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 }
mchung@2139 70 } else if (Files.exists(home.resolve("lib"))) {
mchung@2139 71 // either a JRE or a jdk build image
mchung@2139 72 Path classes = home.resolve("classes");
mchung@2139 73 if (Files.isDirectory(classes)) {
mchung@2139 74 // jdk build outputdir
mchung@2538 75 result.add(new JDKArchive(classes));
mchung@2139 76 }
mchung@2139 77 // add other JAR files
mchung@2139 78 result.addAll(addJarFiles(home.resolve("lib")));
mchung@2139 79 } else {
mchung@2139 80 throw new RuntimeException("\"" + home + "\" not a JDK home");
mchung@2139 81 }
mchung@2139 82 return result;
mchung@2139 83 } catch (IOException e) {
mchung@2139 84 throw new Error(e);
mchung@2139 85 }
mchung@1472 86 }
mchung@1472 87
mchung@2139 88 private static List<Archive> addJarFiles(final Path root) throws IOException {
mchung@2139 89 final List<Archive> result = new ArrayList<>();
mchung@1472 90 final Path ext = root.resolve("ext");
mchung@1472 91 Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
mchung@1472 92 @Override
mchung@1472 93 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
mchung@1472 94 throws IOException
mchung@1472 95 {
mchung@1472 96 if (dir.equals(root) || dir.equals(ext)) {
mchung@1472 97 return FileVisitResult.CONTINUE;
mchung@1472 98 } else {
mchung@1472 99 // skip other cobundled JAR files
mchung@1472 100 return FileVisitResult.SKIP_SUBTREE;
mchung@1472 101 }
mchung@1472 102 }
mchung@1472 103 @Override
mchung@2139 104 public FileVisitResult visitFile(Path p, BasicFileAttributes attrs)
mchung@1472 105 throws IOException
mchung@1472 106 {
mchung@2139 107 String fn = p.getFileName().toString();
mchung@2139 108 if (fn.endsWith(".jar")) {
mchung@2139 109 // JDK may cobundle with JavaFX that doesn't belong to any profile
mchung@2139 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));
mchung@1472 114 }
mchung@1472 115 return FileVisitResult.CONTINUE;
mchung@1472 116 }
mchung@1472 117 });
mchung@1472 118 return result;
mchung@1472 119 }
mchung@2139 120
mchung@2139 121 /**
mchung@2139 122 * A JDK archive is part of the JDK containing the Java SE API
mchung@2139 123 * or implementation classes (i.e. JDK internal API)
mchung@2139 124 */
mchung@2139 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@2538 158 if (Profile.getProfile(pn) != null) {
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 }
mchung@2139 211 }
mchung@2139 212 }
mchung@1472 213 }

mercurial