169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.*;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Hashtable;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Vector;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.security.ProtectionDomain;
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The class loader for Javassist.
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This is a sample class loader using <code>ClassPool</code>.
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Unlike a regular class loader, this class loader obtains bytecode
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * from a <code>ClassPool</code>.
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>Note that Javassist can be used without this class loader; programmers
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * can define their own versions of class loader.  They can run
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * a program even without any user-defined class loader if that program
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * is statically translated with Javassist.
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This class loader is just provided as a utility class.
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>Suppose that an instance of <code>MyTranslator</code> implementing
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the interface <code>Translator</code> is responsible for modifying
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * class files.
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The startup program of an application using <code>MyTranslator</code>
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * should be something like this:
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre>
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * import javassist.*;
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * public class Main {
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *   public static void main(String[] args) throws Throwable {
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *     MyTranslator myTrans = new MyTranslator();
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *     ClassPool cp = ClassPool.getDefault();
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *     Loader cl = new Loader(cp);
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *     cl.addTranslator(cp, myTrans);
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *     cl.run("MyApp", args);
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *   }
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * }
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * </pre></ul>
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>Class <code>MyApp</code> is the main program of the application.
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This program should be executed as follows:
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre>
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * % java Main <i>arg1</i> <i>arg2</i>...
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * </pre></ul>
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>It modifies the class <code>MyApp</code> with a <code>MyTranslator</code>
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * object before the JVM loads it.
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Then it calls <code>main()</code> in <code>MyApp</code> with arguments
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <i>arg1</i>, <i>arg2</i>, ...
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This program execution is equivalent to:
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre>
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * % java MyApp <i>arg1</i> <i>arg2</i>...
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * </pre></ul>
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>except that classes are translated by <code>MyTranslator</code>
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * at load time.
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>If only a particular class must be modified when it is loaded,
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the startup program can be simpler; <code>MyTranslator</code> is
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * unnecessary.  For example, if only a class <code>test.Rectangle</code>
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * is modified, the <code>main()</code> method above will be the following:
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre>
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * ClassPool cp = ClassPool.getDefault();
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Loader cl = new Loader(cp);
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * CtClass ct = cp.get("test.Rectangle");
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * ct.setSuperclass(cp.get("test.Point"));
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * cl.run("MyApp", args);</pre></ul>
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This program changes the super class of the <code>test.Rectangle</code>
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * class.
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p><b>Note 1:</b>
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This class loader does not allow the users to intercept the loading
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * of <code>java.*</code> and <code>javax.*</code> classes (and
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>sun.*</code>, <code>org.xml.*</code>, ...) unless
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Loader.doDelegation</code> is <code>false</code>.  This is because
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the JVM prohibits a user class loader from loading a system class.
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Also see Note 2.
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * If this behavior is not appropriate, a subclass of <code>Loader</code>
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * must be defined and <code>loadClassByDelegation()</code> must be overridden.
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p><b>Note 2:</b>
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>If classes are loaded with different class loaders, they belong to
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * separate name spaces.  If class <code>C</code> is loaded by a class
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * loader <code>CL</code>, all classes that the class <code>C</code>
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * refers to are also loaded by <code>CL</code>.  However, if <code>CL</code>
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * delegates the loading of the class <code>C</code> to <code>CL'</code>,
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * then those classes that the class <code>C</code> refers to
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * are loaded by a parent class loader <code>CL'</code>
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * instead of <code>CL</code>.
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>If an object of class <code>C</code> is assigned
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * to a variable of class <code>C</code> belonging to a different name
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * space, then a <code>ClassCastException</code> is thrown.
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>Because of the fact above, this loader delegates only the loading of
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>javassist.Loader</code>
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * and classes included in package <code>java.*</code> and
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>javax.*</code> to the parent class
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * loader.  Other classes are directly loaded by this loader.
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>For example, suppose that <code>java.lang.String</code> would be loaded
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * by this loader while <code>java.io.File</code> is loaded by the parent
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * class loader.  If the constructor of <code>java.io.File</code> is called
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * with an instance of <code>java.lang.String</code>, then it may throw
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * an exception since it accepts an instance of only the
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>java.lang.String</code> loaded by the parent class loader.
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.ClassPool
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.Translator
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class Loader extends ClassLoader {
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private Hashtable notDefinedHere; // must be atomic.
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private Vector notDefinedPackages; // must be atomic.
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private ClassPool source;
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private Translator translator;
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private ProtectionDomain domain;
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Specifies the algorithm of class loading.
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>This class loader uses the parent class loader for
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>java.*</code> and <code>javax.*</code> classes.
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If this variable <code>doDelegation</code>
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * is <code>false</code>, this class loader does not delegate those
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * classes to the parent class loader.
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>The default value is <code>true</code>.
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean doDelegation = true;
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Creates a new class loader.
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Loader() {
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        this(null);
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Creates a new class loader.
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param cp        the source of class files.
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Loader(ClassPool cp) {
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        init(cp);
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Creates a new class loader
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * using the specified parent class loader for delegation.
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param parent    the parent class loader.
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param cp        the source of class files.
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Loader(ClassLoader parent, ClassPool cp) {
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(parent);
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        init(cp);
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void init(ClassPool cp) {
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        notDefinedHere = new Hashtable();
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        notDefinedPackages = new Vector();
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        source = cp;
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        translator = null;
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        domain = null;
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        delegateLoadingOf("javassist.Loader");
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Records a class so that the loading of that class is delegated
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * to the parent class loader.
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>If the given class name ends with <code>.</code> (dot), then
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * that name is interpreted as a package name.  All the classes
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * in that package and the sub packages are delegated.
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void delegateLoadingOf(String classname) {
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (classname.endsWith("."))
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            notDefinedPackages.addElement(classname);
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            notDefinedHere.put(classname, this);
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets the protection domain for the classes handled by this class
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * loader.  Without registering an appropriate protection domain,
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the program loaded by this loader will not work with a security
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * manager or a signed jar file.
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setDomain(ProtectionDomain d) {
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        domain = d;
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets the soruce <code>ClassPool</code>.
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setClassPool(ClassPool cp) {
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        source = cp;
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Adds a translator, which is called whenever a class is loaded.
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param cp        the <code>ClassPool</code> object for obtaining
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  a class file.
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param t         a translator.
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws NotFoundException        if <code>t.start()</code> throws an exception.
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws CannotCompileException   if <code>t.start()</code> throws an exception.
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void addTranslator(ClassPool cp, Translator t)
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws NotFoundException, CannotCompileException {
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        source = cp;
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        translator = t;
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        t.start(cp);
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Loads a class with an instance of <code>Loader</code>
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * and calls <code>main()</code> of that class.
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>This method calls <code>run()</code>.
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param args              command line parameters.
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <ul>
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>args[0]</code> is the class name to be loaded.
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <br><code>args[1..n]</code> are parameters passed
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                      to the target <code>main()</code>.
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * </ul>
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see javassist.Loader#run(String[])
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static void main(String[] args) throws Throwable {
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Loader cl = new Loader();
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        cl.run(args);
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Loads a class and calls <code>main()</code> in that class.
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param args              command line parameters.
26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <ul>
26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>args[0]</code> is the class name to be loaded.
26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <br><code>args[1..n]</code> are parameters passed
26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                      to the target <code>main()</code>.
26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * </ul>
26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void run(String[] args) throws Throwable {
27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = args.length - 1;
27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (n >= 0) {
27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String[] args2 = new String[n];
27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < n; ++i)
27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                args2[i] = args[i + 1];
27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            run(args[0], args2);
27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Loads a class and calls <code>main()</code> in that class.
28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param classname         the loaded class.
28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param args              parameters passed to <code>main()</code>.
28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void run(String classname, String[] args) throws Throwable {
28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Class c = loadClass(classname);
28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            c.getDeclaredMethod("main", new Class[] { String[].class }).invoke(
29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                null,
29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                new Object[] { args });
29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (java.lang.reflect.InvocationTargetException e) {
29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw e.getTargetException();
29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Requests the class loader to load a class.
30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected Class loadClass(String name, boolean resolve)
30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws ClassFormatError, ClassNotFoundException {
30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        name = name.intern();
30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        synchronized (name) {
30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Class c = findLoadedClass(name);
30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (c == null)
30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                c = loadClassByDelegation(name);
30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (c == null)
31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                c = findClass(name);
31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (c == null)
31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                c = delegateToParent(name);
31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (resolve)
31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                resolveClass(c);
31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return c;
32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Finds the specified class using <code>ClassPath</code>.
32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If the source throws an exception, this returns null.
32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>This method can be overridden by a subclass of
32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>Loader</code>.  Note that the overridden method must not throw
32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * an exception when it just fails to find a class file.
33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return      null if the specified class could not be found.
33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws ClassNotFoundException   if an exception is thrown while
33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                                  obtaining a class file.
33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected Class findClass(String name) throws ClassNotFoundException {
33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] classfile;
33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (source != null) {
33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (translator != null)
34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    translator.onLoad(source, name);
34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                try {
34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    classfile = source.get(name).toBytecode();
34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                catch (NotFoundException e) {
34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    return null;
34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                String jarname = "/" + name.replace('.', '/') + ".class";
35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                InputStream in = this.getClass().getResourceAsStream(jarname);
35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (in == null)
35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    return null;
35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                classfile = ClassPoolTail.readStream(in);
35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (Exception e) {
35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new ClassNotFoundException(
36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                "caught an exception while obtaining a class file for "
36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                + name, e);
36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int i = name.lastIndexOf('.');
36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (i != -1) {
36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String pname = name.substring(0, i);
36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (getPackage(pname) == null)
36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                try {
36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    definePackage(
37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        pname, null, null, null, null, null, null, null);
37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                catch (IllegalArgumentException e) {
37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    // ignore.  maybe the package object for the same
37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    // name has been created just right away.
37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (domain == null)
37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return defineClass(name, classfile, 0, classfile.length);
38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return defineClass(name, classfile, 0, classfile.length, domain);
38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected Class loadClassByDelegation(String name)
38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws ClassNotFoundException
38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /* The swing components must be loaded by a system
38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * class loader.
38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * javax.swing.UIManager loads a (concrete) subclass
39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * of LookAndFeel by a system class loader and cast
39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * an instance of the class to LookAndFeel for
39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * (maybe) a security reason.  To avoid failure of
39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * type conversion, LookAndFeel must not be loaded
39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * by this class loader.
39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Class c = null;
39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (doDelegation)
39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (name.startsWith("java.")
40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                || name.startsWith("javax.")
40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                || name.startsWith("sun.")
40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                || name.startsWith("com.sun.")
40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                || name.startsWith("org.w3c.")
40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                || name.startsWith("org.xml.")
40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                || notDelegated(name))
40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                c = delegateToParent(name);
40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
40869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return c;
40969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
41069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
41169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private boolean notDelegated(String name) {
41269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (notDefinedHere.get(name) != null)
41369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return true;
41469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
41569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = notDefinedPackages.size();
41669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i)
41769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (name.startsWith((String)notDefinedPackages.elementAt(i)))
41869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return true;
41969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
42069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return false;
42169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
42269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
42369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected Class delegateToParent(String classname)
42469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws ClassNotFoundException
42569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
42669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ClassLoader cl = getParent();
42769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (cl != null)
42869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return cl.loadClass(classname);
42969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
43069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return findSystemClass(classname);
43169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
43269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
43369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected Package getPackage(String name) {
43469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return super.getPackage(name);
43569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
43669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /*
43769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        // Package p = super.getPackage(name);
43869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Package p = null;
43969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (p == null)
44069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return definePackage(name, null, null, null,
44169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                 null, null, null, null);
44269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
44369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return p;
44469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
44569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    */
44669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
447