import java.io.OutputStream;
import java.net.URL;
import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.ArrayList;
import javassist.bytecode.Descriptor;
/**
private static final int INIT_HASH_SIZE = 191;
+ private ArrayList importedPackages;
+
/**
* Creates a root class pool. No parent class pool is specified.
*/
}
this.cflow = null;
+ clearImportedPackages();
}
/**
return source.toString();
}
+ /**
+ * Record a package name so that the Javassist compiler searches
+ * the package to resolve a class name.
+ * Don't record the <code>java.lang</code> package, which has
+ * been implicitly recorded by default.
+ *
+ * <p>Note that <code>get()</code> in <code>ClassPool</code> does
+ * not search the recorded package. Only the compiler searches it.
+ *
+ * @param packageName the package name.
+ * It must not include the last '.' (dot).
+ * For example, "java.util" is valid but "java.util." is wrong.
+ * @since 3.1
+ */
+ public void importPackage(String packageName) {
+ importedPackages.add(packageName);
+ }
+
+ /**
+ * Clear all the package names recorded by <code>importPackage()</code>.
+ * The <code>java.lang</code> package is not removed.
+ *
+ * @see #importPackage(String)
+ * @since 3.1
+ */
+ public void clearImportedPackages() {
+ importedPackages = new ArrayList();
+ importedPackages.add("java.lang");
+ }
+
+ /**
+ * Returns all the package names recorded by <code>importPackage()</code>.
+ *
+ * @see #importPackage(String)
+ * @since 3.1
+ */
+ public Iterator getImportedPackages() {
+ return importedPackages.iterator();
+ }
+
/**
* Records a name that never exists.
* For example, a package name can be recorded by this method.
* and thus it cannot be modified any more.
*
* @see #defrost()
+ * @see #detach()
*/
public boolean isFrozen() { return true; }
*
* @see #isFrozen()
* @see #stopPruning(boolean)
+ * @see #detach()
*/
public void defrost() {
throw new RuntimeException("cannot defrost " + getName());
package javassist.compiler;
import java.util.List;
+import java.util.Iterator;
import javassist.*;
import javassist.bytecode.*;
import javassist.compiler.ast.*;
try {
return lookupClass0(name, notCheckInner);
}
- catch (NotFoundException e) {}
- if (name.indexOf('.') < 0) {
- String jlangName = "java.lang." + name;
- try {
- CtClass cc = classPool.get(jlangName);
- // if java.lang... is found, then
- classPool.recordInvalidClassName(name);
- return cc;
- }
- catch (NotFoundException e) {
- classPool.recordInvalidClassName(jlangName);
+ catch (NotFoundException e) {
+ return searchImports(name);
+ }
+ }
+
+ private CtClass searchImports(String orgName)
+ throws CompileError
+ {
+ if (orgName.indexOf('.') < 0) {
+ Iterator it = classPool.getImportedPackages();
+ while (it.hasNext()) {
+ String pac = (String)it.next();
+ String fqName = pac + '.' + orgName;
+ try {
+ CtClass cc = classPool.get(fqName);
+ // if the class is found,
+ classPool.recordInvalidClassName(orgName);
+ return cc;
+ }
+ catch (NotFoundException e) {
+ classPool.recordInvalidClassName(fqName);
+ }
}
}
- throw new CompileError("no such class: " + name);
+ throw new CompileError("no such class: " + orgName);
}
private CtClass lookupClass0(String classname, boolean notCheckInner)
<br><li><a href="#alter">Altering a method body</a>
<br><li><a href="#add">Adding a new method or field</a>
<br><li><a href="#runtime">Runtime support classes</a>
+<br><li><a href="#import">Import</a>
<br><li><a href="#limit">Limitations</a>
</ul>
<p><br>
+<a name="import">
+<h3>4.5 Import</h3>
+
+<p>All the class names in source code must be fully qualified
+(they must include package names).
+However, the <code>java.lang</code> package is an
+exception; for example, the Javassist compiler can
+resolve <code>Object</code> as
+well as <code>java.lang.Object</code>.
+
+<p>To tell the compiler to search other packages when resolving a
+class name, call <code>importPackage()</code> in <code>ClassPool</code>.
+For example,
+
+<ul><pre>
+ClassPool pool = ClassPool.getDefault();
+pool.importPackage("java.awt");
+CtClass cc = pool.makeClass("Test");
+CtField f = CtField.make("public Point p;", cc);
+cc.addField(f);
+</pre></ul>
+
+<p>The seconde line instructs the compiler
+to import the <code>java.awt</code> package.
+Thus, the third line will not throw an exception.
+The compiler can recognize <code>Point</code>
+as <code>java.awt.Point</code>.
+
+<p>Note that <code>importPackage()</code> <em>does not</em> affect
+the <code>get()</code> method in <code>ClassPool</code>.
+Only the compiler considers the imported packages.
+The parameter to <code>get()</code>
+must be always a fully qualified name.
+
+<p><br>
+
<a name="limit">
-<h3>4.5 Limitations</h3>
+<h3>4.6 Limitations</h3>
<p>In the current implementation, the Java compiler included in Javassist
has several limitations with respect to the language that the compiler can
API of Javassist.
See the <code>javassist.bytecode.annotation</code> package.
-<p><li>All the class names must be fully qualified (they must include
-package names). This is because the compiler does not support
-<code>import</code>
-declarations. However, the <code>java.lang</code> package is an
-exception; for example, the compiler accepts <code>Object</code> as
-well as <code>java.lang.Object</code>.
-
<p><li>Array initializers, a comma-separated list of expressions
enclosed by braces <code>{</code> and <code>}</code>, are not
supported.