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]

Reply via email to