/* * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.tools.javac.sym; import java.io.BufferedInputStream; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import com.sun.tools.javac.util.Assert; /** * Provide details about profile contents. * * <p><b>This is NOT part of any supported API. * If you write code that depends on this, you do so at your own * risk. This code and its internal interfaces are subject to change * or deletion without notice.</b></p> */ public abstract class Profiles { // for debugging public static void main(String[] args) throws IOException { Profiles p = Profiles.read(new File(args[0])); if (args.length >= 2) { Map<Integer,Set<String>> lists = new TreeMap<Integer,Set<String>>(); for (int i = 1; i <= 4; i++) lists.put(i, new TreeSet<String>()); File rt_jar_lst = new File(args[1]); for (String line: Files.readAllLines(rt_jar_lst.toPath(), Charset.defaultCharset())) { if (line.endsWith(".class")) { String type = line.substring(0, line.length() - 6); int profile = p.getProfile(type); for (int i = profile; i <= 4; i++) lists.get(i).add(type); } } for (int i = 1; i <= 4; i++) { BufferedWriter out = new BufferedWriter(new FileWriter(i + ".txt")); try { for (String type: lists.get(i)) { out.write(type); out.newLine(); } } finally { out.close(); } } } } public static Profiles read(File file) throws IOException { BufferedInputStream in = new BufferedInputStream(new FileInputStream(file)); try { Properties p = new Properties(); p.load(in); if (p.containsKey("java/lang/Object")) return new SimpleProfiles(p); else return new MakefileProfiles(p); } finally { in.close(); } } public abstract int getProfileCount(); public abstract int getProfile(String typeName); public abstract Set<String> getPackages(int profile); private static class MakefileProfiles extends Profiles { static class Package { final Package parent; final String name; Map<String, Package> subpackages = new TreeMap<String, Package>(); int profile; Map<String, Integer> includedTypes = new TreeMap<String,Integer>(); Map<String, Integer> excludedTypes = new TreeMap<String,Integer>(); Package(Package parent, String name) { this.parent = parent; this.name = name; } int getProfile() { return (parent == null) ? profile : Math.max(parent.getProfile(), profile); } int getProfile(String simpleTypeName) { Integer i; if ((i = includedTypes.get(simpleTypeName)) != null) return i; if ((i = includedTypes.get("*")) != null) return i; if ((i = excludedTypes.get(simpleTypeName)) != null) return i + 1; if ((i = excludedTypes.get("*")) != null) return i + 1; return getProfile(); } String getName() { return (parent == null) ? name : (parent.getName() + "/" + name); } void getPackages(int profile, Set<String> results) { int prf = getProfile(); if (prf != 0 && profile >= prf) results.add(getName()); for (Package pkg: subpackages.values()) pkg.getPackages(profile, results); } } final Map<String, Package> packages = new TreeMap<String, Package>(); final int maxProfile = 4; // Three compact profiles plus full JRE MakefileProfiles(Properties p) { // consider crypto, only if java/lang package exists boolean foundJavaLang = false; for (int profile = 1; profile <= maxProfile; profile++) { String prefix = (profile < maxProfile ? "PROFILE_" + profile : "FULL_JRE"); String inclPackages = p.getProperty(prefix + "_RTJAR_INCLUDE_PACKAGES"); if (inclPackages == null) break; for (String pkg: inclPackages.substring(1).trim().split("\\s+")) { if (pkg.endsWith("/")) pkg = pkg.substring(0, pkg.length() - 1); if (foundJavaLang == false && pkg.equals("java/lang")) foundJavaLang = true; includePackage(profile, pkg); } String inclTypes = p.getProperty(prefix + "_RTJAR_INCLUDE_TYPES"); if (inclTypes != null) { for (String type: inclTypes.replace("$$", "$").split("\\s+")) { if (type.endsWith(".class")) includeType(profile, type.substring(0, type.length() - 6)); } } String exclTypes = p.getProperty(prefix + "_RTJAR_EXCLUDE_TYPES"); if (exclTypes != null) { for (String type: exclTypes.replace("$$", "$").split("\\s+")) { if (type.endsWith(".class")) excludeType(profile, type.substring(0, type.length() - 6)); } } } /* * A hack to force javax/crypto package into the compact1 profile, * because this package exists in jce.jar, and therefore not in * ct.sym. Note javax/crypto should exist in a profile along with * javax/net/ssl package. Thus, this package is added to compact1, * implying that it should exist in all three profiles. */ if (foundJavaLang) includePackage(1, "javax/crypto"); } @Override public int getProfileCount() { return maxProfile; } @Override public int getProfile(String typeName) { int sep = typeName.lastIndexOf("/"); String packageName = typeName.substring(0, sep); String simpleName = typeName.substring(sep + 1); Package p = getPackage(packageName); return p.getProfile(simpleName); } @Override public Set<String> getPackages(int profile) { Set<String> results = new TreeSet<String>(); for (Package p: packages.values()) p.getPackages(profile, results); return results; } private void includePackage(int profile, String packageName) { // System.err.println("include package " + packageName); Package p = getPackage(packageName); Assert.check(p.profile == 0); p.profile = profile; } private void includeType(int profile, String typeName) { // System.err.println("include type " + typeName); int sep = typeName.lastIndexOf("/"); String packageName = typeName.substring(0, sep); String simpleName = typeName.substring(sep + 1); Package p = getPackage(packageName); Assert.check(!p.includedTypes.containsKey(simpleName)); p.includedTypes.put(simpleName, profile); } private void excludeType(int profile, String typeName) { // System.err.println("exclude type " + typeName); int sep = typeName.lastIndexOf("/"); String packageName = typeName.substring(0, sep); String simpleName = typeName.substring(sep + 1); Package p = getPackage(packageName); Assert.check(!p.excludedTypes.containsKey(simpleName)); p.excludedTypes.put(simpleName, profile); } private Package getPackage(String packageName) { int sep = packageName.lastIndexOf("/"); Package parent; Map<String, Package> parentSubpackages; String simpleName; if (sep == -1) { parent = null; parentSubpackages = packages; simpleName = packageName; } else { parent = getPackage(packageName.substring(0, sep)); parentSubpackages = parent.subpackages; simpleName = packageName.substring(sep + 1); } Package p = parentSubpackages.get(simpleName); if (p == null) { parentSubpackages.put(simpleName, p = new Package(parent, simpleName)); } return p; } } private static class SimpleProfiles extends Profiles { private final Map<String, Integer> map; private final int profileCount; SimpleProfiles(Properties p) { int max = 0; map = new HashMap<String, Integer>(); for (Map.Entry<Object,Object> e: p.entrySet()) { String typeName = (String) e.getKey(); int profile = Integer.valueOf((String) e.getValue()); map.put(typeName, profile); max = Math.max(max, profile); } profileCount = max; } @Override public int getProfileCount() { return profileCount; } @Override public int getProfile(String typeName) { return map.get(typeName); } @Override public Set<String> getPackages(int profile) { Set<String> results = new TreeSet<String>(); for (Map.Entry<String,Integer> e: map.entrySet()) { String tn = e.getKey(); int prf = e.getValue(); int sep = tn.lastIndexOf("/"); if (sep > 0 && profile >= prf) results.add(tn); } return results; } } }