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

Mon, 03 Jun 2013 17:09:26 -0700

author
jjg
date
Mon, 03 Jun 2013 17:09:26 -0700
changeset 1796
242bcad5be74
parent 1638
fd3fdaff0257
child 2139
defadd528513
permissions
-rw-r--r--

8006615: [doclint] move remaining messages into resource bundle
Reviewed-by: mcimadamore, vromero

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@1577 28 import java.util.ArrayList;
mchung@1577 29 import java.util.HashMap;
mchung@1577 30 import java.util.HashSet;
mchung@1577 31 import java.util.List;
mchung@1577 32 import java.util.Map;
mchung@1577 33 import java.util.Set;
mchung@1577 34 import java.util.SortedMap;
mchung@1577 35 import java.util.SortedSet;
mchung@1577 36 import java.util.TreeMap;
mchung@1577 37 import java.util.TreeSet;
mchung@1577 38
mchung@1577 39 /**
mchung@1577 40 * Dependency Analyzer.
mchung@1577 41 */
mchung@1577 42 public class Analyzer {
mchung@1577 43 /**
mchung@1577 44 * Type of the dependency analysis. Appropriate level of data
mchung@1577 45 * will be stored.
mchung@1577 46 */
mchung@1577 47 public enum Type {
mchung@1577 48 SUMMARY,
mchung@1577 49 PACKAGE,
mchung@1577 50 CLASS,
mchung@1577 51 VERBOSE
mchung@1577 52 };
mchung@1577 53
mchung@1577 54 private final Type type;
mchung@1577 55 private final List<ArchiveDeps> results = new ArrayList<ArchiveDeps>();
mchung@1577 56 private final Map<String, Archive> map = new HashMap<String, Archive>();
mchung@1577 57 private final Archive NOT_FOUND
mchung@1577 58 = new Archive(JdepsTask.getMessage("artifact.not.found"));
mchung@1577 59
mchung@1577 60 /**
mchung@1577 61 * Constructs an Analyzer instance.
mchung@1577 62 *
mchung@1577 63 * @param type Type of the dependency analysis
mchung@1577 64 */
mchung@1577 65 public Analyzer(Type type) {
mchung@1577 66 this.type = type;
mchung@1577 67 }
mchung@1577 68
mchung@1577 69 /**
mchung@1577 70 * Performs the dependency analysis on the given archives.
mchung@1577 71 */
mchung@1577 72 public void run(List<Archive> archives) {
mchung@1577 73 for (Archive archive : archives) {
mchung@1577 74 ArchiveDeps deps;
mchung@1577 75 if (type == Type.CLASS || type == Type.VERBOSE) {
mchung@1577 76 deps = new ClassVisitor(archive);
mchung@1577 77 } else {
mchung@1577 78 deps = new PackageVisitor(archive);
mchung@1577 79 }
mchung@1577 80 archive.visit(deps);
mchung@1577 81 results.add(deps);
mchung@1577 82 }
mchung@1577 83
mchung@1577 84 // set the required dependencies
mchung@1577 85 for (ArchiveDeps result: results) {
mchung@1577 86 for (Set<String> set : result.deps.values()) {
mchung@1577 87 for (String target : set) {
mchung@1577 88 Archive source = getArchive(target);
mchung@1577 89 if (result.archive != source) {
mchung@1577 90 if (!result.requiredArchives.contains(source)) {
mchung@1577 91 result.requiredArchives.add(source);
mchung@1577 92 }
mchung@1577 93 // either a profile name or the archive name
mchung@1638 94 String tname = result.getTargetProfile(target);
mchung@1638 95 if (tname.isEmpty()) {
mchung@1638 96 tname = PlatformClassPath.contains(source)
mchung@1638 97 ? "JDK internal API (" + source.getFileName() + ")"
mchung@1638 98 : source.toString();
mchung@1577 99 }
mchung@1577 100 if (!result.targetNames.contains(tname)) {
mchung@1577 101 result.targetNames.add(tname);
mchung@1577 102 }
mchung@1577 103 }
mchung@1577 104 }
mchung@1577 105 }
mchung@1577 106 }
mchung@1577 107 }
mchung@1577 108
mchung@1577 109 public interface Visitor {
mchung@1577 110 /**
mchung@1577 111 * Visits a recorded dependency from origin to target which can be
mchung@1577 112 * a fully-qualified classname, a package name, a profile or
mchung@1577 113 * archive name depending on the Analyzer's type.
mchung@1577 114 */
mchung@1638 115 void visit(String origin, String target, String profile);
mchung@1577 116 /**
mchung@1577 117 * Visits the source archive to its destination archive of
mchung@1577 118 * a recorded dependency.
mchung@1577 119 */
mchung@1577 120 void visit(Archive source, Archive dest);
mchung@1577 121 }
mchung@1577 122
mchung@1577 123 public void visitSummary(Visitor v) {
mchung@1577 124 for (ArchiveDeps r : results) {
mchung@1577 125 for (Archive a : r.requiredArchives) {
mchung@1577 126 v.visit(r.archive, a);
mchung@1577 127 }
mchung@1577 128 for (String name : r.targetNames) {
mchung@1638 129 v.visit(r.archive.getFileName(), name, name);
mchung@1577 130 }
mchung@1577 131 }
mchung@1577 132 }
mchung@1577 133
mchung@1577 134 public void visit(Visitor v) {
mchung@1577 135 for (ArchiveDeps r: results) {
mchung@1577 136 for (Archive a : r.requiredArchives) {
mchung@1577 137 v.visit(r.archive, a);
mchung@1577 138 }
mchung@1577 139 for (String origin : r.deps.keySet()) {
mchung@1577 140 for (String target : r.deps.get(origin)) {
mchung@1577 141 // filter intra-dependency unless in verbose mode
mchung@1577 142 if (type == Type.VERBOSE || getArchive(origin) != getArchive(target)) {
mchung@1638 143 v.visit(origin, target, r.getTargetProfile(target));
mchung@1577 144 }
mchung@1577 145 }
mchung@1577 146 }
mchung@1577 147 }
mchung@1577 148 }
mchung@1577 149
mchung@1577 150 public Archive getArchive(String name) {
mchung@1577 151 return map.containsKey(name) ? map.get(name) : NOT_FOUND;
mchung@1577 152 }
mchung@1577 153
mchung@1638 154 /**
mchung@1638 155 * Returns the file name of the archive for non-JRE class or
mchung@1638 156 * internal JRE classes. It returns empty string for SE API.
mchung@1638 157 */
mchung@1638 158 public String getArchiveName(String target, String profile) {
mchung@1638 159 Archive source = getArchive(target);
mchung@1638 160 String name = source.getFileName();
mchung@1638 161 if (PlatformClassPath.contains(source))
mchung@1638 162 return profile.isEmpty() ? "JDK internal API (" + name + ")" : "";
mchung@1638 163 return name;
mchung@1577 164 }
mchung@1577 165
mchung@1577 166 private abstract class ArchiveDeps implements Archive.Visitor {
mchung@1577 167 final Archive archive;
mchung@1577 168 final Set<Archive> requiredArchives;
mchung@1577 169 final SortedSet<String> targetNames;
mchung@1577 170 final SortedMap<String, SortedSet<String>> deps;
mchung@1577 171
mchung@1577 172 ArchiveDeps(Archive archive) {
mchung@1577 173 this.archive = archive;
mchung@1577 174 this.requiredArchives = new HashSet<Archive>();
mchung@1577 175 this.targetNames = new TreeSet<String>();
mchung@1577 176 this.deps = new TreeMap<String, SortedSet<String>>();
mchung@1577 177 }
mchung@1577 178
mchung@1577 179 void add(String loc) {
mchung@1577 180 Archive a = map.get(loc);
mchung@1577 181 if (a == null) {
mchung@1577 182 map.put(loc, archive);
mchung@1577 183 } else if (a != archive) {
mchung@1577 184 // duplicated class warning?
mchung@1577 185 }
mchung@1577 186 }
mchung@1577 187
mchung@1577 188 void add(String origin, String target) {
mchung@1577 189 SortedSet<String> set = deps.get(origin);
mchung@1577 190 if (set == null) {
mchung@1577 191 set = new TreeSet<String>();
mchung@1577 192 deps.put(origin, set);
mchung@1577 193 }
mchung@1577 194 if (!set.contains(target)) {
mchung@1577 195 set.add(target);
mchung@1577 196 }
mchung@1577 197 }
mchung@1577 198
mchung@1577 199 public abstract void visit(Location o, Location t);
mchung@1638 200 public abstract String getTargetProfile(String target);
mchung@1638 201
mchung@1577 202 }
mchung@1577 203
mchung@1577 204 private class ClassVisitor extends ArchiveDeps {
mchung@1577 205 ClassVisitor(Archive archive) {
mchung@1577 206 super(archive);
mchung@1577 207 }
mchung@1577 208 public void visit(Location l) {
mchung@1577 209 add(l.getClassName());
mchung@1577 210 }
mchung@1577 211 public void visit(Location o, Location t) {
mchung@1577 212 add(o.getClassName(), t.getClassName());
mchung@1577 213 }
mchung@1638 214 public String getTargetProfile(String target) {
mchung@1638 215 int i = target.lastIndexOf('.');
mchung@1638 216 return (i > 0) ? Profiles.getProfileName(target.substring(0, i)) : "";
mchung@1638 217 }
mchung@1577 218 }
mchung@1577 219
mchung@1577 220 private class PackageVisitor extends ArchiveDeps {
mchung@1577 221 PackageVisitor(Archive archive) {
mchung@1577 222 super(archive);
mchung@1577 223 }
mchung@1577 224 public void visit(Location o, Location t) {
mchung@1577 225 add(packageOf(o), packageOf(t));
mchung@1577 226 }
mchung@1577 227 public void visit(Location l) {
mchung@1577 228 add(packageOf(l));
mchung@1577 229 }
mchung@1577 230 private String packageOf(Location loc) {
mchung@1577 231 String pkg = loc.getPackageName();
mchung@1577 232 return pkg.isEmpty() ? "<unnamed>" : pkg;
mchung@1577 233 }
mchung@1638 234 public String getTargetProfile(String target) {
mchung@1638 235 return Profiles.getProfileName(target);
mchung@1638 236 }
mchung@1577 237 }
mchung@1577 238 }

mercurial