1 /* 2 * Copyright (c) 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 package com.sun.tools.sjavac.comp.dependencies; 26 27 import java.util.Collection; 28 import java.util.HashMap; 29 import java.util.Map; 30 import java.util.Set; 31 import java.util.stream.Collectors; 32 33 import javax.tools.JavaFileManager.Location; 34 import javax.tools.JavaFileObject; 35 import javax.tools.StandardLocation; 36 37 import com.sun.source.util.TaskEvent; 38 import com.sun.source.util.TaskListener; 39 import com.sun.tools.javac.code.Symbol; 40 import com.sun.tools.javac.code.Symbol.ClassSymbol; 41 import com.sun.tools.javac.code.Symbol.PackageSymbol; 42 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 43 import com.sun.tools.javac.util.Context; 44 import com.sun.tools.javac.util.DefinedBy; 45 import com.sun.tools.javac.util.DefinedBy.Api; 46 import com.sun.tools.sjavac.Log; 47 import com.sun.tools.sjavac.comp.Dependencies; 48 import com.sun.tools.sjavac.comp.JavaFileObjectWithLocation; 49 50 public class DependencyCollector implements TaskListener { 51 52 private Context context; 53 54 // Compilation unit -> fully qualified name -> class symbol 55 public final Map<JCCompilationUnit, Map<String, Set<ClassSymbol>>> collectedDependencies = new HashMap<>(); 56 57 public DependencyCollector(Context context) { 58 this.context = context; 59 } 60 61 @Override 62 @DefinedBy(Api.COMPILER_TREE) 63 public void finished(TaskEvent e) { 64 if (e.getKind() == TaskEvent.Kind.ANALYZE) { 65 JCCompilationUnit cu = (JCCompilationUnit) e.getCompilationUnit(); 66 //com.sun.tools.sjavac.Log.info("Finished compilation unit: " + cu.sourcefile); 67 PackageSymbol thisPkg = cu.packge; 68 if (thisPkg == null) { 69 // Compilation unit in default package. See JDK-8048144. 70 return; 71 } 72 DependencyScanner ds = new DependencyScanner(context); 73 cu.accept(ds); 74 75 collectedDependencies.put(cu, ds.dependencies); 76 } 77 78 if (e.getKind() == TaskEvent.Kind.COMPILATION) { 79 Dependencies deps = Dependencies.instance(context); 80 81 // Collect dependencies 82 for (JCCompilationUnit fromCu : collectedDependencies.keySet()) { 83 84 // fqName -> set of type deps 85 Map<String, Set<ClassSymbol>> map = collectedDependencies.get(fromCu); 86 for (String fromFqName : map.keySet()) { 87 Set<ClassSymbol> toSymbols = map.get(fromFqName); 88 Set<ClassSymbol> toOutermostSymbols = collectOutermostClassSymbols(toSymbols); 89 90 for (ClassSymbol toTypeSymbol : toOutermostSymbols) { 91 92 // Ignore self-dependencies 93 if (fromFqName.equals(toTypeSymbol.flatname.toString())) 94 continue; 95 Location loc = getLocationOf(toTypeSymbol); 96 if (loc != StandardLocation.PLATFORM_CLASS_PATH) 97 deps.collect(loc, fromCu, fromFqName, toTypeSymbol); 98 } 99 } 100 } 101 102 // Collect pubapi of dependencies 103 Collection<Map<String, Set<ClassSymbol>>> allDepMaps = collectedDependencies.values(); 104 for (Map<String, Set<ClassSymbol>> depMap : allDepMaps) { 105 for (String fromFqName : depMap.keySet()) { 106 Set<ClassSymbol> toSymbols = depMap.get(fromFqName); 107 Set<ClassSymbol> toOutermostSymbols = collectOutermostClassSymbols(toSymbols); 108 for (ClassSymbol ts : toOutermostSymbols) { 109 // Ignore self-dependencies 110 if (fromFqName.equals(ts.flatname.toString())) 111 continue; 112 if (getLocationOf(ts) != StandardLocation.PLATFORM_CLASS_PATH) 113 deps.visitPubapi(ts); 114 } 115 } 116 } 117 118 } 119 } 120 121 private Location getLocationOf(ClassSymbol cs) { 122 JavaFileObject jfo = cs.outermostClass().classfile; 123 if (jfo != null) 124 return ((JavaFileObjectWithLocation<?>) jfo).getLocation(); 125 Log.warn("Could not determine location of " + cs.flatName()); 126 return null; 127 } 128 129 private Set<ClassSymbol> collectOutermostClassSymbols(Set<ClassSymbol> cs) { 130 return cs.stream() 131 .map(Symbol::outermostClass) 132 .collect(Collectors.toSet()); 133 } 134 }