1 /* 2 * Copyright (c) 2012, 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; 26 27 import java.io.File; 28 import java.io.IOException; 29 import java.nio.file.FileVisitResult; 30 import java.nio.file.Files; 31 import java.nio.file.Path; 32 import java.nio.file.SimpleFileVisitor; 33 import java.nio.file.attribute.BasicFileAttributes; 34 import java.util.*; 35 36 /** 37 * ClassPath for Java SE and JDK 38 */ 39 class PlatformClassPath { 40 /* 41 * Profiles for Java SE 42 * 43 * This is a temporary workaround until a common API is defined for langtools 44 * to determine which profile a given classname belongs to. The list of 45 * packages and profile names are hardcoded in jdk.properties and 46 * split packages are not supported. 47 */ 48 static class Profile { 49 final String name; 50 final Set<String> packages; 51 52 Profile(String name) { 53 this.name = name; 54 this.packages = new HashSet<>(); 55 } 56 } 57 58 private final static String JAVAFX = "javafx"; 59 private final static Map<String,Profile> map = getProfilePackages(); 60 static String getProfileName(String packageName) { 61 Profile profile = map.get(packageName); 62 if (packageName.startsWith(JAVAFX + ".")) { 63 profile = map.get(JAVAFX); 64 } 65 return profile != null ? profile.name : ""; 66 } 67 68 private final static List<Archive> javaHomeArchives = init(); 69 static List<Archive> getArchives() { 70 return javaHomeArchives; 71 } 72 73 static boolean contains(Archive archive) { 74 return javaHomeArchives.contains(archive); 75 } 76 77 private static List<Archive> init() { 78 List<Archive> result = new ArrayList<>(); 79 String javaHome = System.getProperty("java.home"); 80 List<File> files = new ArrayList<>(); 81 File jre = new File(javaHome, "jre"); 82 File lib = new File(javaHome, "lib"); 83 84 try { 85 if (jre.exists() && jre.isDirectory()) { 86 result.addAll(addJarFiles(new File(jre, "lib"))); 87 result.addAll(addJarFiles(lib)); 88 } else if (lib.exists() && lib.isDirectory()) { 89 // either a JRE or a jdk build image 90 File classes = new File(javaHome, "classes"); 91 if (classes.exists() && classes.isDirectory()) { 92 // jdk build outputdir 93 ClassFileReader reader = ClassFileReader.newInstance(classes); 94 Archive archive = new Archive(classes, reader); 95 result.add(archive); 96 } 97 // add other JAR files 98 result.addAll(addJarFiles(lib)); 99 } else { 100 throw new RuntimeException("\"" + javaHome + "\" not a JDK home"); 101 } 102 } catch (IOException e) { 103 throw new RuntimeException(e); 104 } 105 106 // add a JavaFX profile if there is jfxrt.jar 107 for (Archive archive : result) { 108 if (archive.getFileName().equals("jfxrt.jar")) { 109 map.put(JAVAFX, new Profile("jfxrt.jar")); 110 } 111 } 112 return result; 113 } 114 115 private static List<Archive> addJarFiles(File f) throws IOException { 116 final List<Archive> result = new ArrayList<>(); 117 final Path root = f.toPath(); 118 final Path ext = root.resolve("ext"); 119 Files.walkFileTree(root, new SimpleFileVisitor<Path>() { 120 @Override 121 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) 122 throws IOException 123 { 124 if (dir.equals(root) || dir.equals(ext)) { 125 return FileVisitResult.CONTINUE; 126 } else { 127 // skip other cobundled JAR files 128 return FileVisitResult.SKIP_SUBTREE; 129 } 130 } 131 @Override 132 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 133 throws IOException 134 { 135 String fn = file.toFile().getName(); 136 if (fn.endsWith(".jar") && !fn.equals("alt-rt.jar")) { 137 File f = file.toFile(); 138 ClassFileReader reader = ClassFileReader.newInstance(f); 139 Archive archive = new Archive(f, reader); 140 result.add(archive); 141 } 142 return FileVisitResult.CONTINUE; 143 } 144 }); 145 return result; 146 } 147 148 private static Map<String,Profile> getProfilePackages() { 149 Map<String,Profile> map = new HashMap<>(); 150 151 // read the properties as a ResourceBundle as the build compiles 152 // the properties file into Java class. Another alternative is 153 // to load it as Properties and fix the build to exclude this file. 154 ResourceBundle profileBundle 155 = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.jdk"); 156 157 int i=1; 158 String key; 159 while (profileBundle.containsKey((key = "profile." + i + ".name"))) { 160 Profile profile = new Profile(profileBundle.getString(key)); 161 String n = profileBundle.getString("profile." + i + ".packages"); 162 String[] pkgs = n.split("\\s+"); 163 for (String p : pkgs) { 164 if (p.isEmpty()) continue; 165 assert(map.containsKey(p) == false); 166 profile.packages.add(p); 167 map.put(p, profile); 168 } 169 i++; 170 } 171 return map; 172 } 173 }