Thu, 25 Aug 2011 17:18:25 -0700
Added tag jdk8-b02 for changeset b3c059de2a61
1 /*
2 * Copyright (c) 2009, 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 */
26 import java.io.*;
27 import java.util.*;
28 import java.util.regex.Pattern;
29 import javax.tools.*;
31 import com.sun.tools.classfile.*;
32 import com.sun.tools.classfile.Dependencies.*;
33 import com.sun.tools.classfile.Dependency.Location;
34 import com.sun.tools.javac.file.JavacFileManager;
35 import com.sun.tools.javac.util.Context;
37 /**
38 * Demo utility for using the classfile dependency analysis API framework.
39 *
40 * Usage:
41 * getdeps [options] classes
42 * where options include:
43 * -classpath path where to find classes to analyze
44 * -p package-name restrict analysis to classes in this package
45 * (may be given multiple times)
46 * -r regex restrict analysis to packages matching pattern
47 * (-p and -r are exclusive)
48 * -rev invert the dependencies in the output
49 * -t transitive closure of dependencies
50 */
51 public class GetDeps {
52 public static void main(String... args) throws Exception {
53 new GetDeps().run(args);
54 }
56 void run(String... args) throws IOException, ClassFileNotFoundException {
57 PrintWriter pw = new PrintWriter(System.out);
58 try {
59 run(pw, args);
60 } finally {
61 pw.flush();
62 }
63 }
65 void run(PrintWriter out, String... args) throws IOException, ClassFileNotFoundException {
66 decodeArgs(args);
68 final StandardJavaFileManager fm = new JavacFileManager(new Context(), false, null);
69 if (classpath != null)
70 fm.setLocation(StandardLocation.CLASS_PATH, classpath);
72 ClassFileReader reader = new ClassFileReader(fm);
74 Dependencies d = new Dependencies();
76 if (regex != null)
77 d.setFilter(Dependencies.getRegexFilter(Pattern.compile(regex)));
79 if (packageNames.size() > 0)
80 d.setFilter(Dependencies.getPackageFilter(packageNames, false));
82 SortedRecorder r = new SortedRecorder(reverse);
84 d.findAllDependencies(reader, rootClassNames, transitiveClosure, r);
86 SortedMap<Location,SortedSet<Dependency>> deps = r.getMap();
87 for (Map.Entry<Location, SortedSet<Dependency>> e: deps.entrySet()) {
88 out.println(e.getKey());
89 for (Dependency dep: e.getValue()) {
90 out.println(" " + dep.getTarget());
91 }
92 }
93 }
95 void decodeArgs(String... args) {
96 rootClassNames = new TreeSet<String>();
97 packageNames = new TreeSet<String>();
99 for (int i = 0; i < args.length; i++) {
100 String arg = args[i];
101 if (arg.equals("-classpath") && (i + 1 < args.length))
102 classpath = getPathFiles(args[++i]);
103 else if (arg.equals("-p") && (i + 1 < args.length))
104 packageNames.add(args[++i]);
105 else if (arg.equals("-r") && (i + 1 < args.length))
106 regex = args[++i];
107 else if (arg.equals("-rev"))
108 reverse = true;
109 else if (arg.equals("-t"))
110 transitiveClosure = true;
111 else if (arg.startsWith("-"))
112 throw new Error(arg);
113 else {
114 for ( ; i < args.length; i++)
115 rootClassNames.add(args[i]);
116 }
117 }
118 }
120 List<File> getPathFiles(String path) {
121 List<File> files = new ArrayList<File>();
122 for (String p: path.split(File.pathSeparator)) {
123 if (p.length() > 0)
124 files.add(new File(p));
125 }
126 return files;
127 }
129 boolean transitiveClosure;
130 List<File> classpath;
131 Set<String> rootClassNames;
132 Set<String> packageNames;
133 String regex;
134 boolean reverse;
137 static class ClassFileReader implements Dependencies.ClassFileReader {
138 private JavaFileManager fm;
140 ClassFileReader(JavaFileManager fm) {
141 this.fm = fm;
142 }
144 @Override
145 public ClassFile getClassFile(String className) throws ClassFileNotFoundException {
146 try {
147 JavaFileObject fo = fm.getJavaFileForInput(
148 StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);
149 if (fo == null)
150 fo = fm.getJavaFileForInput(
151 StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
152 if (fo == null)
153 throw new ClassFileNotFoundException(className);
154 InputStream in = fo.openInputStream();
155 try {
156 return ClassFile.read(in);
157 } finally {
158 in.close();
159 }
160 } catch (ConstantPoolException e) {
161 throw new ClassFileNotFoundException(className, e);
162 } catch (IOException e) {
163 throw new ClassFileNotFoundException(className, e);
164 }
165 }
166 };
168 static class SortedRecorder implements Recorder {
169 public SortedRecorder(boolean reverse) {
170 this.reverse = reverse;
171 }
173 public void addDependency(Dependency d) {
174 Location o = (reverse ? d.getTarget() : d.getOrigin());
175 SortedSet<Dependency> odeps = map.get(o);
176 if (odeps == null) {
177 Comparator<Dependency> c = (reverse ? originComparator : targetComparator);
178 map.put(o, odeps = new TreeSet<Dependency>(c));
179 }
180 odeps.add(d);
181 }
183 public SortedMap<Location, SortedSet<Dependency>> getMap() {
184 return map;
185 }
187 private Comparator<Dependency> originComparator = new Comparator<Dependency>() {
188 public int compare(Dependency o1, Dependency o2) {
189 return o1.getOrigin().toString().compareTo(o2.getOrigin().toString());
190 }
191 };
193 private Comparator<Dependency> targetComparator = new Comparator<Dependency>() {
194 public int compare(Dependency o1, Dependency o2) {
195 return o1.getTarget().toString().compareTo(o2.getTarget().toString());
196 }
197 };
199 private Comparator<Location> locationComparator = new Comparator<Location>() {
200 public int compare(Location o1, Location o2) {
201 return o1.toString().compareTo(o2.toString());
202 }
203 };
205 private final SortedMap<Location, SortedSet<Dependency>> map =
206 new TreeMap<Location, SortedSet<Dependency>>(locationComparator);
208 boolean reverse;
209 }
211 }