All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xapi.bytecode.ClassPoolTail Maven / Gradle / Ivy

Go to download

Everything needed to run a comprehensive dev environment. Just type X_ and pick a service from autocomplete; new dev modules will be added as they are built. The only dev service not included in the uber jar is xapi-dev-maven, as it includes all runtime dependencies of maven, adding ~4 seconds to build time, and 6 megabytes to the final output jar size (without xapi-dev-maven, it's ~1MB).

The newest version!
/*
 * Javassist, a Java-bytecode translator toolkit.
 * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License.  Alternatively, the contents of this file may be used under
 * the terms of the GNU Lesser General Public License Version 2.1 or later,
 * or the Apache License Version 2.0.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * MODIFIED BY James Nelson of We The Internet, 2013.
 * Repackaged to avoid conflicts with different versions of Javassist,
 * and modified Javassist APIs to make them more accessible to outside code.
 */
package xapi.bytecode;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Hashtable;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

final class ClassPathList {
    ClassPathList next;
    ClassPath path;

    ClassPathList(ClassPath p, ClassPathList n) {
        next = n;
        path = p;
    }
}

final class DirClassPath implements ClassPath {
    String directory;

    DirClassPath(String dirName) {
        directory = dirName;
    }

    @Override
    public InputStream openClassfile(String classname) {
        try {
            char sep = File.separatorChar;
            String filename = directory + sep
                + classname.replace('.', sep) + ".class";
            return new FileInputStream(filename.toString());
        }
        catch (FileNotFoundException e) {}
        catch (SecurityException e) {}
        return null;
    }

    @Override
    public URL find(String classname) {
        char sep = File.separatorChar;
        String filename = directory + sep
            + classname.replace('.', sep) + ".class";
        File f = new File(filename);
        if (f.exists()) {
          try {
              return f.getCanonicalFile().toURI().toURL();
          }
          catch (MalformedURLException e) {}
          catch (IOException e) {}
        }

        return null;
    }

    @Override
    public void close() {}

    @Override
    public String toString() {
        return directory;
    }
}

final class JarDirClassPath implements ClassPath {
    JarClassPath[] jars;

    JarDirClassPath(String dirName) throws NotFoundException {
        File[] files = new File(dirName).listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                name = name.toLowerCase();
                return name.endsWith(".jar") || name.endsWith(".zip");
            }
        });

        if (files != null) {
            jars = new JarClassPath[files.length];
            for (int i = 0; i < files.length; i++) {
              jars[i] = new JarClassPath(files[i].getPath());
            }
        }
    }

    @Override
    public InputStream openClassfile(String classname) throws NotFoundException {
        if (jars != null) {
          for (int i = 0; i < jars.length; i++) {
              InputStream is = jars[i].openClassfile(classname);
              if (is != null) {
                return is;
              }
          }
        }

        return null;    // not found
    }

    @Override
    public URL find(String classname) {
        if (jars != null) {
          for (int i = 0; i < jars.length; i++) {
              URL url = jars[i].find(classname);
              if (url != null) {
                return url;
              }
          }
        }

        return null;    // not found
    }

    @Override
    public void close() {
        if (jars != null) {
          for (int i = 0; i < jars.length; i++) {
            jars[i].close();
          }
        }
    }
}

final class JarClassPath implements ClassPath {
    JarFile jarfile;
    String jarfileURL;

    JarClassPath(String pathname) throws NotFoundException {
        try {
            jarfile = new JarFile(pathname);
            jarfileURL = new File(pathname).getCanonicalFile()
                                           .toURI().toURL().toString();
            return;
        }
        catch (IOException e) {}
        throw new NotFoundException(pathname);
    }

    @Override
    public InputStream openClassfile(String classname)
        throws NotFoundException
    {
        try {
            String jarname = classname.replace('.', '/') + ".class";
            JarEntry je = jarfile.getJarEntry(jarname);
            if (je != null) {
              return jarfile.getInputStream(je);
            }
            else {
              return null;    // not found
            }
        }
        catch (IOException e) {}
        throw new NotFoundException("broken jar file?: "
                                    + jarfile.getName());
    }

    @Override
    public URL find(String classname) {
        String jarname = classname.replace('.', '/') + ".class";
        JarEntry je = jarfile.getJarEntry(jarname);
        if (je != null) {
          try {
              return new URL("jar:" + jarfileURL + "!/" + jarname);
          }
          catch (MalformedURLException e) {}
        }

        return null;            // not found
    }

    @Override
    public void close() {
        try {
            jarfile.close();
            jarfile = null;
        }
        catch (IOException e) {}
    }

    @Override
    public String toString() {
        return jarfile == null ? "" : jarfile.toString();
    }
}

final class ClassPoolTail {
    protected ClassPathList pathList;
    private Hashtable packages;         // should be synchronized.

    public ClassPoolTail() {
        pathList = null;
        packages = new Hashtable();
    }

    @Override
    public String toString() {
        StringBuffer buf = new StringBuffer();
        buf.append("[class path: ");
        ClassPathList list = pathList;
        while (list != null) {
            buf.append(list.path.toString());
            buf.append(File.pathSeparatorChar);
            list = list.next;
        }

        buf.append(']');
        return buf.toString();
    }

    public synchronized ClassPath insertClassPath(ClassPath cp) {
        pathList = new ClassPathList(cp, pathList);
        return cp;
    }

    public synchronized ClassPath appendClassPath(ClassPath cp) {
        ClassPathList tail = new ClassPathList(cp, null);
        ClassPathList list = pathList;
        if (list == null) {
          pathList = tail;
        } else {
            while (list.next != null) {
              list = list.next;
            }

            list.next = tail;
        }

        return cp;
    }

    public synchronized void removeClassPath(ClassPath cp) {
        ClassPathList list = pathList;
        if (list != null) {
          if (list.path == cp) {
            pathList = list.next;
          } else {
              while (list.next != null) {
                if (list.next.path == cp) {
                  list.next = list.next.next;
                } else {
                  list = list.next;
                }
              }
          }
        }

        cp.close();
    }

    public ClassPath appendSystemPath() {
        return appendClassPath(new ClassClassPath());
    }

    public ClassPath insertClassPath(String pathname)
        throws NotFoundException
    {
        return insertClassPath(makePathObject(pathname));
    }

    public ClassPath appendClassPath(String pathname)
        throws NotFoundException
    {
        return appendClassPath(makePathObject(pathname));
    }

    private static ClassPath makePathObject(String pathname)
        throws NotFoundException
    {
        String lower = pathname.toLowerCase();
        if (lower.endsWith(".jar") || lower.endsWith(".zip")) {
          return new JarClassPath(pathname);
        }

        int len = pathname.length();
        if (len > 2 && pathname.charAt(len - 1) == '*'
            && (pathname.charAt(len - 2) == '/'
                || pathname.charAt(len - 2) == File.separatorChar)) {
            String dir = pathname.substring(0, len - 2);
            return new JarDirClassPath(dir);
        }

        return new DirClassPath(pathname);
    }

    /**
     * You can record "System" so that java.lang.System can be quickly
     * found although "System" is not a package name.
     */
    public void recordInvalidClassName(String name) {
        packages.put(name, name);
    }

    /**
     * This method does not close the output stream.
     */
    void writeClassfile(String classname, OutputStream out)
        throws NotFoundException, IOException
    {
        InputStream fin = openClassfile(classname);
        if (fin == null) {
          throw new NotFoundException(classname);
        }

        try {
            copyStream(fin, out);
        }
        finally {
            fin.close();
        }
    }

    /*
    -- faster version --
    void checkClassName(String classname) throws NotFoundException {
        if (find(classname) == null)
            throw new NotFoundException(classname);
    }

    -- slower version --

    void checkClassName(String classname) throws NotFoundException {
        InputStream fin = openClassfile(classname);
        try {
            fin.close();
        }
        catch (IOException e) {}
    }
    */


    /**
     * Opens the class file for the class specified by
     * classname.
     *
     * @param classname             a fully-qualified class name
     * @return null                 if the file has not been found.
     * @throws NotFoundException    if any error is reported by ClassPath.
     */
    InputStream openClassfile(String classname)
        throws NotFoundException
    {
        if (packages.get(classname) != null)
         {
          return null;    // not found
        }

        ClassPathList list = pathList;
        InputStream ins = null;
        NotFoundException error = null;
        while (list != null) {
            try {
                ins = list.path.openClassfile(classname);
            }
            catch (NotFoundException e) {
                if (error == null) {
                  error = e;
                }
            }

            if (ins == null) {
              list = list.next;
            } else {
              return ins;
            }
        }

        if (error != null) {
          throw error;
        }
        else {
          return null;    // not found
        }
    }

    /**
     * Searches the class path to obtain the URL of the class file
     * specified by classname.  It is also used to determine whether
     * the class file exists.
     *
     * @param classname     a fully-qualified class name.
     * @return null if the class file could not be found.
     */
    public URL find(String classname) {
        if (packages.get(classname) != null) {
          return null;
        }

        ClassPathList list = pathList;
        URL url = null;
        while (list != null) {
            url = list.path.find(classname);
            if (url == null) {
              list = list.next;
            } else {
              return url;
            }
        }

        return null;
    }

    /**
     * Reads from an input stream until it reaches the end.
     *
     * @return          the contents of that input stream
     */
    public static byte[] readStream(InputStream fin) throws IOException {
        byte[][] bufs = new byte[10][];
        int bufsize = 4096;

        for (int i = 0; i < 10; ++i) {
            bufs[i] = new byte[bufsize];
            int size = 0;
            int len = 0;
            do {
                len = fin.read(bufs[i], size, bufsize - size);
                if (len >= 0) {
                  size += len;
                } else {
                    byte[] result = new byte[bufsize - 4096 + size];
                    int s = 0;
                    for (int j = 0; j < i; ++j) {
                        System.arraycopy(bufs[j], 0, result, s, s + 4096);
                        s = s + s + 4096;
                    }

                    System.arraycopy(bufs[i], 0, result, s, size);
                    return result;
                }
            } while (size < bufsize);
            bufsize *= 2;
        }

        throw new IOException("too much data");
    }

    /**
     * Reads from an input stream and write to an output stream
     * until it reaches the end.  This method does not close the
     * streams.
     */
    public static void copyStream(InputStream fin, OutputStream fout)
        throws IOException
    {
        int bufsize = 4096;
        for (int i = 0; i < 8; ++i) {
            byte[] buf = new byte[bufsize];
            int size = 0;
            int len = 0;
            do {
                len = fin.read(buf, size, bufsize - size);
                if (len >= 0) {
                  size += len;
                } else {
                    fout.write(buf, 0, size);
                    return;
                }
            } while (size < bufsize);
            fout.write(buf);
            bufsize *= 2;
        }

        throw new IOException("too much data");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy