src/share/classes/com/sun/tools/jdeps/Analyzer.java

Thu, 17 Oct 2013 13:19:48 -0700

author
mchung
date
Thu, 17 Oct 2013 13:19:48 -0700
changeset 2139
defadd528513
parent 1638
fd3fdaff0257
child 2172
aa91bc6e8480
permissions
-rw-r--r--

8015912: jdeps support to output in dot file format
8026255: Switch jdeps to follow traditional Java option style
Reviewed-by: alanb

mchung@1577 1 /*
mchung@1577 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
mchung@1577 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mchung@1577 4 *
mchung@1577 5 * This code is free software; you can redistribute it and/or modify it
mchung@1577 6 * under the terms of the GNU General Public License version 2 only, as
mchung@1577 7 * published by the Free Software Foundation. Oracle designates this
mchung@1577 8 * particular file as subject to the "Classpath" exception as provided
mchung@1577 9 * by Oracle in the LICENSE file that accompanied this code.
mchung@1577 10 *
mchung@1577 11 * This code is distributed in the hope that it will be useful, but WITHOUT
mchung@1577 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mchung@1577 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mchung@1577 14 * version 2 for more details (a copy is included in the LICENSE file that
mchung@1577 15 * accompanied this code).
mchung@1577 16 *
mchung@1577 17 * You should have received a copy of the GNU General Public License version
mchung@1577 18 * 2 along with this work; if not, write to the Free Software Foundation,
mchung@1577 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mchung@1577 20 *
mchung@1577 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mchung@1577 22 * or visit www.oracle.com if you need additional information or have any
mchung@1577 23 * questions.
mchung@1577 24 */
mchung@1577 25 package com.sun.tools.jdeps;
mchung@1577 26
mchung@1577 27 import com.sun.tools.classfile.Dependency.Location;
mchung@2139 28 import com.sun.tools.jdeps.PlatformClassPath.JDKArchive;
mchung@1577 29 import java.util.HashMap;
mchung@1577 30 import java.util.List;
mchung@1577 31 import java.util.Map;
mchung@1577 32 import java.util.Set;
mchung@1577 33 import java.util.SortedMap;
mchung@1577 34 import java.util.SortedSet;
mchung@1577 35 import java.util.TreeMap;
mchung@1577 36 import java.util.TreeSet;
mchung@1577 37
mchung@1577 38 /**
mchung@1577 39 * Dependency Analyzer.
mchung@1577 40 */
mchung@1577 41 public class Analyzer {
mchung@1577 42 /**
mchung@1577 43 * Type of the dependency analysis. Appropriate level of data
mchung@1577 44 * will be stored.
mchung@1577 45 */
mchung@1577 46 public enum Type {
mchung@1577 47 SUMMARY,
mchung@1577 48 PACKAGE,
mchung@1577 49 CLASS,
mchung@1577 50 VERBOSE
mchung@1577 51 };
mchung@1577 52
mchung@1577 53 private final Type type;
mchung@2139 54 private final Map<Archive, ArchiveDeps> results = new HashMap<>();
mchung@2139 55 private final Map<String, Archive> map = new HashMap<>();
mchung@1577 56 private final Archive NOT_FOUND
mchung@1577 57 = new Archive(JdepsTask.getMessage("artifact.not.found"));
mchung@1577 58
mchung@1577 59 /**
mchung@1577 60 * Constructs an Analyzer instance.
mchung@1577 61 *
mchung@1577 62 * @param type Type of the dependency analysis
mchung@1577 63 */
mchung@1577 64 public Analyzer(Type type) {
mchung@1577 65 this.type = type;
mchung@1577 66 }
mchung@1577 67
mchung@1577 68 /**
mchung@1577 69 * Performs the dependency analysis on the given archives.
mchung@1577 70 */
mchung@1577 71 public void run(List<Archive> archives) {
mchung@1577 72 for (Archive archive : archives) {
mchung@1577 73 ArchiveDeps deps;
mchung@1577 74 if (type == Type.CLASS || type == Type.VERBOSE) {
mchung@1577 75 deps = new ClassVisitor(archive);
mchung@1577 76 } else {
mchung@1577 77 deps = new PackageVisitor(archive);
mchung@1577 78 }
mchung@1577 79 archive.visit(deps);
mchung@2139 80 results.put(archive, deps);
mchung@1577 81 }
mchung@1577 82
mchung@1577 83 // set the required dependencies
mchung@2139 84 for (ArchiveDeps result: results.values()) {
mchung@1577 85 for (Set<String> set : result.deps.values()) {
mchung@1577 86 for (String target : set) {
mchung@1577 87 Archive source = getArchive(target);
mchung@1577 88 if (result.archive != source) {
mchung@2139 89 String profile = "";
mchung@2139 90 if (source instanceof JDKArchive) {
mchung@2139 91 profile = result.profile != null ? result.profile.toString() : "";
mchung@2139 92 if (result.getTargetProfile(target) == null) {
mchung@2139 93 profile += ", JDK internal API";
mchung@2139 94 // override the value if it accesses any JDK internal
mchung@2139 95 result.requireArchives.put(source, profile);
mchung@2139 96 continue;
mchung@2139 97 }
mchung@1577 98 }
mchung@2139 99 if (!result.requireArchives.containsKey(source)) {
mchung@2139 100 result.requireArchives.put(source, profile);
mchung@1577 101 }
mchung@1577 102 }
mchung@1577 103 }
mchung@1577 104 }
mchung@1577 105 }
mchung@1577 106 }
mchung@1577 107
mchung@2139 108 public boolean hasDependences(Archive archive) {
mchung@2139 109 if (results.containsKey(archive)) {
mchung@2139 110 return results.get(archive).deps.size() > 0;
mchung@2139 111 }
mchung@2139 112 return false;
mchung@2139 113 }
mchung@2139 114
mchung@1577 115 public interface Visitor {
mchung@1577 116 /**
mchung@2139 117 * Visits the source archive to its destination archive of
mchung@2139 118 * a recorded dependency.
mchung@2139 119 */
mchung@2139 120 void visitArchiveDependence(Archive origin, Archive target, String profile);
mchung@2139 121 /**
mchung@1577 122 * Visits a recorded dependency from origin to target which can be
mchung@1577 123 * a fully-qualified classname, a package name, a profile or
mchung@1577 124 * archive name depending on the Analyzer's type.
mchung@1577 125 */
mchung@2139 126 void visitDependence(String origin, Archive source, String target, Archive archive, String profile);
mchung@1577 127 }
mchung@1577 128
mchung@2139 129 public void visitArchiveDependences(Archive source, Visitor v) {
mchung@2139 130 ArchiveDeps r = results.get(source);
mchung@2139 131 for (Map.Entry<Archive,String> e : r.requireArchives.entrySet()) {
mchung@2139 132 v.visitArchiveDependence(r.archive, e.getKey(), e.getValue());
mchung@1577 133 }
mchung@1577 134 }
mchung@1577 135
mchung@2139 136 public void visitDependences(Archive source, Visitor v) {
mchung@2139 137 ArchiveDeps r = results.get(source);
mchung@2139 138 for (String origin : r.deps.keySet()) {
mchung@2139 139 for (String target : r.deps.get(origin)) {
mchung@2139 140 Archive archive = getArchive(target);
mchung@2139 141 assert source == getArchive(origin);
mchung@2139 142 Profile profile = r.getTargetProfile(target);
mchung@2139 143
mchung@2139 144 // filter intra-dependency unless in verbose mode
mchung@2139 145 if (type == Type.VERBOSE || archive != source) {
mchung@2139 146 v.visitDependence(origin, source, target, archive,
mchung@2139 147 profile != null ? profile.toString() : "");
mchung@1577 148 }
mchung@1577 149 }
mchung@1577 150 }
mchung@1577 151 }
mchung@1577 152
mchung@1577 153 public Archive getArchive(String name) {
mchung@1577 154 return map.containsKey(name) ? map.get(name) : NOT_FOUND;
mchung@1577 155 }
mchung@1577 156
mchung@1577 157 private abstract class ArchiveDeps implements Archive.Visitor {
mchung@1577 158 final Archive archive;
mchung@2139 159 final Map<Archive,String> requireArchives;
mchung@1577 160 final SortedMap<String, SortedSet<String>> deps;
mchung@2139 161 Profile profile = null;
mchung@1577 162 ArchiveDeps(Archive archive) {
mchung@1577 163 this.archive = archive;
mchung@2139 164 this.requireArchives = new HashMap<>();
mchung@2139 165 this.deps = new TreeMap<>();
mchung@1577 166 }
mchung@1577 167
mchung@1577 168 void add(String loc) {
mchung@1577 169 Archive a = map.get(loc);
mchung@1577 170 if (a == null) {
mchung@1577 171 map.put(loc, archive);
mchung@1577 172 } else if (a != archive) {
mchung@1577 173 // duplicated class warning?
mchung@1577 174 }
mchung@1577 175 }
mchung@1577 176
mchung@1577 177 void add(String origin, String target) {
mchung@1577 178 SortedSet<String> set = deps.get(origin);
mchung@1577 179 if (set == null) {
mchung@2139 180 deps.put(origin, set = new TreeSet<>());
mchung@1577 181 }
mchung@1577 182 if (!set.contains(target)) {
mchung@1577 183 set.add(target);
mchung@2139 184 // find the corresponding profile
mchung@2139 185 Profile p = getTargetProfile(target);
mchung@2139 186 if (profile == null || (p != null && profile.profile < p.profile)) {
mchung@2139 187 profile = p;
mchung@2139 188 }
mchung@1577 189 }
mchung@1577 190 }
mchung@1577 191 public abstract void visit(Location o, Location t);
mchung@2139 192 public abstract Profile getTargetProfile(String target);
mchung@1577 193 }
mchung@1577 194
mchung@1577 195 private class ClassVisitor extends ArchiveDeps {
mchung@1577 196 ClassVisitor(Archive archive) {
mchung@1577 197 super(archive);
mchung@1577 198 }
mchung@1577 199 public void visit(Location l) {
mchung@1577 200 add(l.getClassName());
mchung@1577 201 }
mchung@1577 202 public void visit(Location o, Location t) {
mchung@1577 203 add(o.getClassName(), t.getClassName());
mchung@1577 204 }
mchung@2139 205 public Profile getTargetProfile(String target) {
mchung@1638 206 int i = target.lastIndexOf('.');
mchung@2139 207 return (i > 0) ? Profile.getProfile(target.substring(0, i)) : null;
mchung@1638 208 }
mchung@1577 209 }
mchung@1577 210
mchung@1577 211 private class PackageVisitor extends ArchiveDeps {
mchung@1577 212 PackageVisitor(Archive archive) {
mchung@1577 213 super(archive);
mchung@1577 214 }
mchung@1577 215 public void visit(Location o, Location t) {
mchung@1577 216 add(packageOf(o), packageOf(t));
mchung@1577 217 }
mchung@1577 218 public void visit(Location l) {
mchung@1577 219 add(packageOf(l));
mchung@1577 220 }
mchung@1577 221 private String packageOf(Location loc) {
mchung@1577 222 String pkg = loc.getPackageName();
mchung@1577 223 return pkg.isEmpty() ? "<unnamed>" : pkg;
mchung@1577 224 }
mchung@2139 225 public Profile getTargetProfile(String target) {
mchung@2139 226 return Profile.getProfile(target);
mchung@1638 227 }
mchung@1577 228 }
mchung@1577 229 }

mercurial