001: /*
002: * Closure.java
003: *
004: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
005: *
006: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
007: *
008: * The contents of this file are subject to the terms of either the GNU
009: * General Public License Version 2 only ("GPL") or the Common
010: * Development and Distribution License("CDDL") (collectively, the
011: * "License"). You may not use this file except in compliance with the
012: * License. You can obtain a copy of the License at
013: * http://www.netbeans.org/cddl-gplv2.html
014: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
015: * specific language governing permissions and limitations under the
016: * License. When distributing the software, include this License Header
017: * Notice in each file and include the License file at
018: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
019: * particular file as subject to the "Classpath" exception as provided
020: * by Sun in the GPL Version 2 section of the License file that
021: * accompanied this code. If applicable, add the following below the
022: * License Header, with the fields enclosed by brackets [] replaced by
023: * your own identifying information:
024: * "Portions Copyrighted [year] [name of copyright owner]"
025: *
026: * Contributor(s):
027: *
028: * The Original Software is NetBeans. The Initial Developer of the Original
029: * Software is Sun Microsystems, Inc. Portions Copyright 2000-2001 Sun
030: * Microsystems, Inc. All Rights Reserved.
031: *
032: * If you wish your version of this file to be governed by only the CDDL
033: * or only the GPL Version 2, indicate your decision by adding
034: * "[Contributor] elects to include this software in this distribution
035: * under the [CDDL or GPL Version 2] license." If you do not indicate a
036: * single choice of license, a recipient has the option to distribute
037: * your version of this file under either the CDDL, the GPL Version 2 or
038: * to extend the choice of license to its licensees as provided above.
039: * However, if you add GPL Version 2 code and therefore, elected the GPL
040: * Version 2 license, then the option applies only if the new code is
041: * made subject to such option by the copyright holder.
042: *
043: * Contributor(s): Thomas Ball
044: *
045: * Version: $Revision$
046: */
047:
048: import org.netbeans.modules.classfile.*;
049: import java.io.*;
050: import java.util.*;
051:
052: /**
053: * Closure: report all classes which this file references in one
054: * way or another. Note: this utility won't find classes which are
055: * dynamically loaded.
056: *
057: * @author Thomas Ball
058: */
059: public class Closure {
060: String this Class;
061: Set closure;
062:
063: Closure(String spec) {
064: this Class = spec;
065: }
066:
067: void buildClosure(boolean includeJDK) throws IOException {
068: if (closure != null)
069: return;
070: closure = new HashSet();
071: Set visited = new HashSet();
072: Stack stk = new Stack();
073: ClassName this CN = ClassName.getClassName(this Class.replace(
074: '.', '/'));
075: stk.push(this CN);
076: visited.add(this CN.getExternalName());
077:
078: while (!stk.empty()) {
079: // Add class to closure.
080: ClassName cn = (ClassName) stk.pop();
081: InputStream is = findClassStream(cn.getType());
082: if (is == null) {
083: System.err.println("couldn't find class: "
084: + cn.getExternalName());
085: continue;
086: }
087: ClassFile cfile = new ClassFile(is);
088: closure.add(cfile.getName().getExternalName());
089:
090: ConstantPool pool = cfile.getConstantPool();
091: Iterator refs = pool.getAllClassNames().iterator();
092: while (refs.hasNext()) {
093: ClassName cnRef = (ClassName) refs.next();
094: String cname = cnRef.getExternalName();
095: if (cname.indexOf('[') != -1) {
096: // skip arrays
097: } else if (!includeJDK
098: && (cname.startsWith("java.")
099: || cname.startsWith("javax.")
100: || cname.startsWith("sun.")
101: || cname.startsWith("com.sun.corba")
102: || cname.startsWith("com.sun.image")
103: || cname
104: .startsWith("com.sun.java.swing")
105: || cname.startsWith("com.sun.naming") || cname
106: .startsWith("com.sun.security"))) {
107: // if directed, skip JDK references
108: } else {
109: boolean isNew = visited.add(cname);
110: if (isNew)
111: stk.push(cnRef);
112: }
113: }
114: }
115: }
116:
117: void dumpClosure(PrintStream out) {
118: Iterator iter = new TreeSet(closure).iterator();
119: while (iter.hasNext())
120: out.println((String) iter.next());
121: }
122:
123: Iterator dependencies() {
124: return closure.iterator();
125: }
126:
127: private InputStream findClassStream(String className) {
128: InputStream is = ClassLoader.getSystemClassLoader()
129: .getResourceAsStream(className + ".class");
130: return is;
131: }
132:
133: /**
134: * An error routine which displays the command line usage
135: * before exiting.
136: */
137: public static void usage() {
138: System.err
139: .println("usage: java Closure [-includejdk] <class> [ <class> ...]");
140: System.exit(1);
141: }
142:
143: public static void main(String[] args) {
144: if (args.length == 0)
145: usage();
146:
147: boolean includeJDK = false;
148: for (int i = 0; i < args.length; i++) {
149: if (args[i].equals("-includejdk"))
150: includeJDK = true;
151: else if (args[i].charAt(0) == '-')
152: usage();
153: else {
154: try {
155: Closure c = new Closure(args[i]);
156: c.buildClosure(includeJDK);
157: c.dumpClosure(System.out);
158: } catch (IOException e) {
159: System.err.println("error accessing \"" + args[i]
160: + "\": " + e.toString());
161: }
162: }
163: }
164: }
165: }
|