1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/jdeps/Profile.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,234 @@ 1.4 +/* 1.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 +package com.sun.tools.jdeps; 1.29 + 1.30 +import com.sun.tools.classfile.Annotation; 1.31 +import com.sun.tools.classfile.Annotation.*; 1.32 +import com.sun.tools.classfile.Attribute; 1.33 +import com.sun.tools.classfile.ClassFile; 1.34 +import com.sun.tools.classfile.ConstantPool.*; 1.35 +import com.sun.tools.classfile.ConstantPoolException; 1.36 +import com.sun.tools.classfile.RuntimeAnnotations_attribute; 1.37 +import java.io.FileReader; 1.38 +import java.io.IOException; 1.39 +import java.nio.file.Files; 1.40 +import java.nio.file.Path; 1.41 +import java.nio.file.Paths; 1.42 +import java.util.*; 1.43 +import java.util.jar.JarFile; 1.44 + 1.45 +/** 1.46 + * Build the profile information from ct.sym if exists. 1.47 + */ 1.48 +enum Profile { 1.49 + 1.50 + COMPACT1("compact1", 1), 1.51 + COMPACT2("compact2", 2), 1.52 + COMPACT3("compact3", 3), 1.53 + FULL_JRE("Full JRE", 4); 1.54 + 1.55 + final String name; 1.56 + final int profile; 1.57 + final Set<String> packages; 1.58 + final Set<String> proprietaryPkgs; 1.59 + 1.60 + Profile(String name, int profile) { 1.61 + this.name = name; 1.62 + this.profile = profile; 1.63 + this.packages = new HashSet<>(); 1.64 + this.proprietaryPkgs = new HashSet<>(); 1.65 + } 1.66 + 1.67 + @Override 1.68 + public String toString() { 1.69 + return name; 1.70 + } 1.71 + 1.72 + public static int getProfileCount() { 1.73 + return PackageToProfile.map.values().size(); 1.74 + } 1.75 + 1.76 + /** 1.77 + * Returns the Profile for the given package name. It returns an empty 1.78 + * string if the given package is not in any profile. 1.79 + */ 1.80 + public static Profile getProfile(String pn) { 1.81 + Profile profile = PackageToProfile.map.get(pn); 1.82 + return (profile != null && profile.packages.contains(pn)) 1.83 + ? profile : null; 1.84 + } 1.85 + 1.86 + static class PackageToProfile { 1.87 + static String[] JAVAX_CRYPTO_PKGS = new String[] { 1.88 + "javax.crypto", 1.89 + "javax.crypto.interfaces", 1.90 + "javax.crypto.spec" 1.91 + }; 1.92 + static Map<String, Profile> map = initProfiles(); 1.93 + private static Map<String, Profile> initProfiles() { 1.94 + try { 1.95 + String profilesProps = System.getProperty("jdeps.profiles"); 1.96 + if (profilesProps != null) { 1.97 + // for testing for JDK development build where ct.sym doesn't exist 1.98 + initProfilesFromProperties(profilesProps); 1.99 + } else { 1.100 + Path home = Paths.get(System.getProperty("java.home")); 1.101 + if (home.endsWith("jre")) { 1.102 + home = home.getParent(); 1.103 + } 1.104 + Path ctsym = home.resolve("lib").resolve("ct.sym"); 1.105 + if (Files.exists(ctsym)) { 1.106 + // parse ct.sym and load information about profiles 1.107 + try (JarFile jf = new JarFile(ctsym.toFile())) { 1.108 + ClassFileReader reader = ClassFileReader.newInstance(ctsym, jf); 1.109 + for (ClassFile cf : reader.getClassFiles()) { 1.110 + findProfile(cf); 1.111 + } 1.112 + } 1.113 + // special case for javax.crypto.* classes that are not 1.114 + // included in ct.sym since they are in jce.jar 1.115 + Collections.addAll(Profile.COMPACT1.packages, JAVAX_CRYPTO_PKGS); 1.116 + } 1.117 + } 1.118 + } catch (IOException | ConstantPoolException e) { 1.119 + throw new Error(e); 1.120 + } 1.121 + HashMap<String,Profile> map = new HashMap<>(); 1.122 + for (Profile profile : Profile.values()) { 1.123 + for (String pn : profile.packages) { 1.124 + if (!map.containsKey(pn)) { 1.125 + // split packages in the JRE: use the smaller compact 1.126 + map.put(pn, profile); 1.127 + } 1.128 + } 1.129 + for (String pn : profile.proprietaryPkgs) { 1.130 + if (!map.containsKey(pn)) { 1.131 + map.put(pn, profile); 1.132 + } 1.133 + } 1.134 + } 1.135 + return map; 1.136 + } 1.137 + private static final String PROFILE_ANNOTATION = "Ljdk/Profile+Annotation;"; 1.138 + private static final String PROPRIETARY_ANNOTATION = "Lsun/Proprietary+Annotation;"; 1.139 + private static Profile findProfile(ClassFile cf) throws ConstantPoolException { 1.140 + RuntimeAnnotations_attribute attr = (RuntimeAnnotations_attribute) 1.141 + cf.attributes.get(Attribute.RuntimeInvisibleAnnotations); 1.142 + int index = 0; 1.143 + boolean proprietary = false; 1.144 + if (attr != null) { 1.145 + for (int i = 0; i < attr.annotations.length; i++) { 1.146 + Annotation ann = attr.annotations[i]; 1.147 + String annType = cf.constant_pool.getUTF8Value(ann.type_index); 1.148 + if (PROFILE_ANNOTATION.equals(annType)) { 1.149 + for (int j = 0; j < ann.num_element_value_pairs; j++) { 1.150 + Annotation.element_value_pair pair = ann.element_value_pairs[j]; 1.151 + Primitive_element_value ev = (Primitive_element_value) pair.value; 1.152 + CONSTANT_Integer_info info = (CONSTANT_Integer_info) 1.153 + cf.constant_pool.get(ev.const_value_index); 1.154 + index = info.value; 1.155 + break; 1.156 + } 1.157 + } else if (PROPRIETARY_ANNOTATION.equals(annType)) { 1.158 + proprietary = true; 1.159 + } 1.160 + } 1.161 + } 1.162 + 1.163 + Profile p = null; // default 1.164 + switch (index) { 1.165 + case 1: 1.166 + p = Profile.COMPACT1; break; 1.167 + case 2: 1.168 + p = Profile.COMPACT2; break; 1.169 + case 3: 1.170 + p = Profile.COMPACT3; break; 1.171 + case 4: 1.172 + p = Profile.FULL_JRE; break; 1.173 + default: 1.174 + // skip classes with profile=0 1.175 + // Inner classes are not annotated with the profile annotation 1.176 + return null; 1.177 + } 1.178 + 1.179 + String name = cf.getName(); 1.180 + int i = name.lastIndexOf('/'); 1.181 + name = (i > 0) ? name.substring(0, i).replace('/', '.') : ""; 1.182 + if (proprietary) { 1.183 + p.proprietaryPkgs.add(name); 1.184 + } else { 1.185 + p.packages.add(name); 1.186 + } 1.187 + return p; 1.188 + } 1.189 + 1.190 + private static void initProfilesFromProperties(String path) throws IOException { 1.191 + Properties props = new Properties(); 1.192 + try (FileReader reader = new FileReader(path)) { 1.193 + props.load(reader); 1.194 + } 1.195 + for (Profile prof : Profile.values()) { 1.196 + int i = prof.profile; 1.197 + String key = props.getProperty("profile." + i + ".name"); 1.198 + if (key == null) { 1.199 + throw new RuntimeException(key + " missing in " + path); 1.200 + } 1.201 + String n = props.getProperty("profile." + i + ".packages"); 1.202 + String[] pkgs = n.split("\\s+"); 1.203 + for (String p : pkgs) { 1.204 + if (p.isEmpty()) continue; 1.205 + prof.packages.add(p); 1.206 + } 1.207 + } 1.208 + } 1.209 + } 1.210 + 1.211 + // for debugging 1.212 + public static void main(String[] args) { 1.213 + if (args.length == 0) { 1.214 + if (Profile.getProfileCount() == 0) { 1.215 + System.err.println("No profile is present in this JDK"); 1.216 + } 1.217 + for (Profile p : Profile.values()) { 1.218 + String profileName = p.name; 1.219 + SortedSet<String> set = new TreeSet<>(p.packages); 1.220 + for (String s : set) { 1.221 + // filter out the inner classes that are not annotated with 1.222 + // the profile annotation 1.223 + if (PackageToProfile.map.get(s) == p) { 1.224 + System.out.format("%2d: %-10s %s%n", p.profile, profileName, s); 1.225 + profileName = ""; 1.226 + } else { 1.227 + System.err.format("Split package: %s in %s and %s %n", 1.228 + s, PackageToProfile.map.get(s).name, p.name); 1.229 + } 1.230 + } 1.231 + } 1.232 + } 1.233 + for (String pn : args) { 1.234 + System.out.format("%s in %s%n", pn, getProfile(pn)); 1.235 + } 1.236 + } 1.237 +}