hillion 01/10/25 06:07:40 Added: sources/org/apache/batik/util ClassFileUtilities.java Log: Added a utility class with methods to compute the dependencies in a Java class file. Revision Changes Path 1.1 xml-batik/sources/org/apache/batik/util/ClassFileUtilities.java Index: ClassFileUtilities.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.batik.util; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * This class contains utility methods to manipulate Java classes. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> * @version $Id: ClassFileUtilities.java,v 1.1 2001/10/25 13:07:40 hillion Exp $ */ public class ClassFileUtilities { // Constant pool info tags public final static byte CONSTANT_UTF8_INFO = 1; public final static byte CONSTANT_INTEGER_INFO = 3; public final static byte CONSTANT_FLOAT_INFO = 4; public final static byte CONSTANT_LONG_INFO = 5; public final static byte CONSTANT_DOUBLE_INFO = 6; public final static byte CONSTANT_CLASS_INFO = 7; public final static byte CONSTANT_STRING_INFO = 8; public final static byte CONSTANT_FIELDREF_INFO = 9; public final static byte CONSTANT_METHODREF_INFO = 10; public final static byte CONSTANT_INTERFACEMETHODREF_INFO = 11; public final static byte CONSTANT_NAMEANDTYPE_INFO = 12; /** * This class does not need to be instantiated. */ protected ClassFileUtilities() { } /** * Returns the dependencies of the given class. * @param path The root class path. * @param classpath The set of directories (Strings) to scan. * @return a list of paths representing the used classes. */ public static Set getClassDependencies(String path, Set classpath) throws IOException { InputStream is = new FileInputStream(path); Set result = new HashSet(); Set done = new HashSet(); computeClassDependencies(is, classpath, done, result); return result; } private static void computeClassDependencies(InputStream is, Set classpath, Set done, Set result) throws IOException { Iterator it = getClassDependencies(is).iterator(); while (it.hasNext()) { String s = (String)it.next(); if (!done.contains(s)) { done.add(s); Iterator cpit = classpath.iterator(); while (cpit.hasNext()) { String root = (String)cpit.next(); StringBuffer sb = new StringBuffer(root); sb.append('/').append(s).append(".class"); String path = sb.toString(); File f = new File(path); if (f.isFile()) { result.add(path); computeClassDependencies(new FileInputStream(f), classpath, done, result); } } } } } /** * Returns the dependencies of the given class. * @return a list of strings representing the used classes. */ public static Set getClassDependencies(InputStream is) throws IOException { DataInputStream dis = new DataInputStream(is); if (dis.readInt() != 0xcafebabe) { throw new IOException("Invalid classfile"); } dis.readInt(); int len = dis.readShort(); String[] strs = new String[len]; Set classes = new HashSet(); Set desc = new HashSet(); for (int i = 1; i < len; i++) { switch (dis.readByte() & 0xff) { case CONSTANT_LONG_INFO: case CONSTANT_DOUBLE_INFO: dis.readLong(); i++; break; case CONSTANT_FIELDREF_INFO: case CONSTANT_METHODREF_INFO: case CONSTANT_INTERFACEMETHODREF_INFO: case CONSTANT_INTEGER_INFO: case CONSTANT_FLOAT_INFO: dis.readInt(); break; case CONSTANT_CLASS_INFO: classes.add(new Integer(dis.readShort() & 0xffff)); break; case CONSTANT_STRING_INFO: dis.readShort(); break; case CONSTANT_NAMEANDTYPE_INFO: dis.readShort(); desc.add(new Integer(dis.readShort() & 0xffff)); break; case CONSTANT_UTF8_INFO: strs[i] = dis.readUTF(); break; default: throw new RuntimeException(); } } Set result = new HashSet(); Iterator it = classes.iterator(); while (it.hasNext()) { result.add(strs[((Integer)it.next()).intValue()]); } it = desc.iterator(); while (it.hasNext()) { result.addAll(getDescriptorClasses(strs[((Integer)it.next()).intValue()])); } return result; } /** * Returns the classes contained in a field or method desciptor. */ protected static Set getDescriptorClasses(String desc) { Set result = new HashSet(); int i = 0; char c = desc.charAt(i); switch (c) { case '(': loop: for (;;) { c = desc.charAt(++i); switch (c) { case '[': do { c = desc.charAt(++i); } while (c == '['); if (c != 'L') { break; } case 'L': c = desc.charAt(++i); StringBuffer sb = new StringBuffer(); while (c != ';') { sb.append(c); c = desc.charAt(++i); } result.add(sb.toString()); break; default: break; case ')': break loop; } } c = desc.charAt(++i); switch (c) { case '[': do { c = desc.charAt(++i); } while (c == '['); if (c != 'L') { break; } case 'L': c = desc.charAt(++i); StringBuffer sb = new StringBuffer(); while (c != ';') { sb.append(c); c = desc.charAt(++i); } result.add(sb.toString()); break; default: case 'V': } break; case '[': do { c = desc.charAt(++i); } while (c == '['); if (c != 'L') { break; } case 'L': c = desc.charAt(++i); StringBuffer sb = new StringBuffer(); while (c != ';') { sb.append(c); c = desc.charAt(++i); } result.add(sb.toString()); break; default: } return result; } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]