1 /* 2 * Copyright (c) 1999, 2014, 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 26 package com.sun.tools.sjavac.comp; 27 28 import javax.lang.model.element.Element; 29 import java.util.Arrays; 30 import java.util.Comparator; 31 import java.util.HashMap; 32 import java.util.HashSet; 33 import java.util.Map; 34 import java.util.Set; 35 36 import com.sun.tools.javac.code.Symbol.ClassSymbol; 37 import com.sun.tools.javac.util.Assert; 38 import com.sun.tools.javac.util.Context; 39 import com.sun.tools.javac.util.Log; 40 import com.sun.tools.javac.util.Name; 41 42 /** Utility class containing dependency information between packages 43 * and the pubapi for a package. 44 * 45 * <p><b>This is NOT part of any supported API. 46 * If you write code that depends on this, you do so at your own risk. 47 * This code and its internal interfaces are subject to change or 48 * deletion without notice.</b> 49 */ 50 public class Dependencies { 51 protected static final Context.Key<Dependencies> dependenciesKey = new Context.Key<>(); 52 53 // The log to be used for error reporting. 54 protected Log log; 55 // Map from package name to packages that the package depends upon. 56 protected Map<Name,Set<Name>> deps; 57 // This is the set of all packages that are supplied 58 // through the java files at the command line. 59 protected Set<Name> explicitPackages; 60 61 // Map from a package name to its public api. 62 // Will the Name encode the module in the future? 63 // If not, this will have to change to map from Module+Name to public api. 64 protected Map<Name,StringBuffer> publicApiPerClass; 65 66 public static Dependencies instance(Context context) { 67 Dependencies instance = context.get(dependenciesKey); 68 if (instance == null) 69 instance = new Dependencies(context); 70 return instance; 71 } 72 73 private Dependencies(Context context) { 74 context.put(dependenciesKey, this); 75 log = Log.instance(context); 76 deps = new HashMap<>(); 77 explicitPackages = new HashSet<>(); 78 publicApiPerClass = new HashMap<>(); 79 } 80 81 /** 82 * Fetch the set of dependencies that are relevant to the compile 83 * that has just been performed. I.e. we are only interested in 84 * dependencies for classes that were explicitly compiled. 85 * @return 86 */ 87 public Map<String,Set<String>> getDependencies() { 88 Map<String,Set<String>> new_deps = new HashMap<>(); 89 if (explicitPackages == null) return new_deps; 90 for (Name pkg : explicitPackages) { 91 Set<Name> set = deps.get(pkg); 92 if (set != null) { 93 Set<String> new_set = new_deps.get(pkg.toString()); 94 if (new_set == null) { 95 new_set = new HashSet<>(); 96 // Modules beware.... 97 new_deps.put(":"+pkg.toString(), new_set); 98 } 99 for (Name d : set) { 100 new_set.add(":"+d.toString()); 101 } 102 } 103 } 104 return new_deps; 105 } 106 107 static class CompareNames implements Comparator<Name> { 108 public int compare(Name a, Name b) { 109 return a.toString().compareTo(b.toString()); 110 } 111 112 } 113 114 /** 115 * Convert the map from class names to their pubapi to a map 116 * from package names to their pubapi (which is the sorted concatenation 117 * of all the class pubapis) 118 */ 119 public Map<String,String> getPubapis() { 120 Map<String,String> publicApiPerPackage = new HashMap<>(); 121 if (publicApiPerClass == null) return publicApiPerPackage; 122 Name[] keys = publicApiPerClass.keySet().toArray(new Name[0]); 123 Arrays.sort(keys, new CompareNames()); 124 StringBuffer newPublicApi = new StringBuffer(); 125 int i=0; 126 String prevPkg = ""; 127 for (Name k : keys) { 128 String cn = k.toString(); 129 String pn = ""; 130 int dp = cn.lastIndexOf('.'); 131 if (dp != -1) { 132 pn = cn.substring(0,dp); 133 } 134 if (!pn.equals(prevPkg)) { 135 if (!prevPkg.equals("")) { 136 // Add default module name ":" 137 publicApiPerPackage.put(":"+prevPkg, newPublicApi.toString()); 138 } 139 newPublicApi = new StringBuffer(); 140 prevPkg = pn; 141 } 142 newPublicApi.append(publicApiPerClass.get(k)); 143 i++; 144 } 145 if (!prevPkg.equals("")) 146 publicApiPerPackage.put(":"+prevPkg, newPublicApi.toString()); 147 return publicApiPerPackage; 148 } 149 150 /** 151 * Visit the api of a class and construct a pubapi string and 152 * store it into the pubapi_perclass map. 153 */ 154 public void visitPubapi(Element e) { 155 Name n = ((ClassSymbol)e).fullname; 156 Name p = ((ClassSymbol)e).packge().fullname; 157 StringBuffer sb = publicApiPerClass.get(n); 158 Assert.check(sb == null); 159 sb = new StringBuffer(); 160 PubapiVisitor v = new PubapiVisitor(sb); 161 v.visit(e); 162 if (sb.length()>0) { 163 publicApiPerClass.put(n, sb); 164 } 165 explicitPackages.add(p); 166 } 167 168 /** 169 * Collect a dependency. curr_pkg is marked as depending on dep_pkg. 170 */ 171 public void collect(Name currPkg, Name depPkg) { 172 if (!currPkg.equals(depPkg)) { 173 Set<Name> theset = deps.get(currPkg); 174 if (theset==null) { 175 theset = new HashSet<>(); 176 deps.put(currPkg, theset); 177 } 178 theset.add(depPkg); 179 } 180 } 181 }