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