You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jaxme-dev@ws.apache.org by jo...@apache.org on 2004/09/05 17:42:26 UTC
cvs commit: ws-jaxme/src/js/org/apache/ws/jaxme/js/pattern InterfaceDescription.java ChainGenerator.java Ant.java ProxyGenerator.java
jochen 2004/09/05 08:42:26
Modified: src/documentation/content/xdocs/js/patterns proxy.xml
src/js/org/apache/ws/jaxme/js/pattern ChainGenerator.java
Ant.java ProxyGenerator.java
Added: src/js/org/apache/ws/jaxme/js/pattern
InterfaceDescription.java
Log:
The proxy and chain generators are now supporting either Java reflection or the Java source parser.
Revision Changes Path
1.3 +71 -0 ws-jaxme/src/documentation/content/xdocs/js/patterns/proxy.xml
Index: proxy.xml
===================================================================
RCS file: /home/cvs/ws-jaxme/src/documentation/content/xdocs/js/patterns/proxy.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- proxy.xml 23 Jul 2004 07:18:00 -0000 1.2
+++ proxy.xml 5 Sep 2004 15:42:26 -0000 1.3
@@ -38,6 +38,77 @@
<p>The proxy generator is implemented by the class
<link href="../../apidocs/org/apache/ws/jaxme/js/pattern/ProxyGenerator.html">ProxyGenerator</link>.
Use of the ProxyGenerator is demonstrated in the Ant target "generate.proxy".</p>
+ <p>The proxy generator Ant task supports the following attributes:</p>
+ <table>
+ <tr>
+ <th>Name</th>
+ <th>Description</th>
+ <th>Required<br/>Default</th>
+ </tr>
+ <tr>
+ <td>classpathRef</td>
+ <td>Reference to a class path, being used to load Java
+ classes or sources. See the "type" attribute in the
+ nested element "implementedInterface" below for details.
+ Use of the "classpathRef" attribute is mutually exclusive
+ with the nested element "classpath".
+ </td>
+ <td>No<br/>Ant's class path</td>
+ </tr>
+ <tr>
+ <td>destDir</td>
+ <td>Path of the directory, where the generated sources are
+ being created. A package structure will be created below.
+ In other words, if a class "org.apache.Foo" is generated,
+ then it will be found in the file ${destDir}/org/apache/Foo.class.
+ </td>
+ <td>No<br/>Current directory</td>
+ </tr>
+ <tr>
+ <td>extendedClass</td>
+ <td>Specifies the fully qualified name of a class, which is being
+ extended by the generated sources.</td>
+ <td>No<br/>java.lang.Object</td>
+ </tr>
+ </table>
+ <p>The proxy generator Ant task also supports the following nested elements:</p>
+ <table>
+ <tr>
+ <th>Name</th>
+ <th>Description</th>
+ <th>Required<br/>Default</th>
+ </tr>
+ <tr>
+ <td>classPath</td>
+ <td>Specifies a path, which is being used for loading
+ Java classes or sources. See the "type" attribute in
+ the nested element "implementedInterface" below for
+ details. The "classpath" element is mutually exclusive
+ with the "classpathRef" attribute.</td>
+ <td>No<br/>Ant's class path</td>
+ </tr>
+ <tr>
+ <td>implementedInterface</td>
+ <td>Specifies an additional interface being implemented.
+ This element must have an attribute "interface" with
+ the fully qualified name of a Java interface which is
+ being implemented by the generated classes.<br/>
+ The generator needs to determine the methods specified
+ by the interface.
+ If the element has an attribute "type" with the value
+ "Reflection", then the specified interface will be
+ loaded as a compiled Java class. Otherwise, if the
+ attribute "type" has the value "Source", then the
+ generator attempts to load a Java source file with
+ the same name from the class path and parse it.
+ Otherwise, if the "type" attribute is missing, it will
+ attempt both "Reflection" and "Source", in that order.
+ </td>
+ <td>
+ Yes, at least one
+ </td>
+ </tr>
+ </table>
</section>
<anchor id="multiple_inheritance"/>
1.6 +21 -20 ws-jaxme/src/js/org/apache/ws/jaxme/js/pattern/ChainGenerator.java
Index: ChainGenerator.java
===================================================================
RCS file: /home/cvs/ws-jaxme/src/js/org/apache/ws/jaxme/js/pattern/ChainGenerator.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ChainGenerator.java 15 Aug 2004 11:46:28 -0000 1.5
+++ ChainGenerator.java 5 Sep 2004 15:42:26 -0000 1.6
@@ -19,7 +19,6 @@
import java.util.ArrayList;
import java.util.List;
-import org.apache.tools.ant.AntClassLoader;
import org.apache.ws.jaxme.js.JavaConstructor;
import org.apache.ws.jaxme.js.JavaField;
import org.apache.ws.jaxme.js.JavaMethod;
@@ -159,6 +158,8 @@
}
}
+ /** Validates the input data.
+ */
public void finish() {
if (controllerInterface == null) {
throw new NullPointerException("A controller interface must be given.");
@@ -170,8 +171,7 @@
private class ProxyInterfaceGenerator extends ProxyGenerator {
public JavaMethod getInterfaceMethod(JavaSource pSource,
- ProxyGenerator.InterfaceDescription pDescription,
- java.lang.reflect.Method pMethod) throws ClassNotFoundException {
+ JavaMethod pMethod) throws ClassNotFoundException {
JavaMethod jm = pSource.newJavaMethod(pMethod);
Parameter[] parameters = jm.getParams();
JavaQName controllerInterfaceQName = JavaQNameImpl.getInstance(getControllerInterface());
@@ -184,7 +184,7 @@
}
public JavaSource generate(JavaSourceFactory pInterfaceFactory,
JavaQName pTargetClass,
- ProxyGenerator.InterfaceDescription[] pDescription) throws ClassNotFoundException {
+ InterfaceDescription[] pDescription) throws Exception {
JavaSource result = super.generate(pInterfaceFactory, pTargetClass,
pDescription);
result.clearImplements();
@@ -209,8 +209,7 @@
}
public JavaMethod getInterfaceMethod(JavaSource pSource,
- ProxyGenerator.InterfaceDescription pDescription,
- java.lang.reflect.Method pMethod) throws ClassNotFoundException {
+ JavaMethod pMethod) throws ClassNotFoundException {
JavaMethod jm = pSource.newJavaMethod(pMethod);
Parameter[] parameters = jm.getParams();
JavaQName controllerInterfaceQName = JavaQNameImpl.getInstance(getControllerInterface());
@@ -226,14 +225,14 @@
callParameters.add(", ");
callParameters.add(parameter.getName());
}
- jm.addLine((Void.TYPE.equals(pMethod.getReturnType()) ? "" : " return "),
- "backingObject.",
- pMethod.getName(), "(", callParameters, ");");
+ jm.addLine((JavaQNameImpl.VOID.equals(pMethod.getType()) ? "" : "return "),
+ "backingObject.",
+ pMethod.getName(), "(", callParameters, ");");
return jm;
}
public JavaSource generate(JavaSourceFactory pImplementationFactory,
JavaQName pTargetClass,
- ProxyGenerator.InterfaceDescription[] pDescription) throws ClassNotFoundException {
+ InterfaceDescription[] pDescription) throws Exception {
JavaSource result = super.generate(pImplementationFactory, pTargetClass, pDescription);
result.clearImplements();
result.addImplements(getChainInterface());
@@ -257,8 +256,7 @@
return jcon;
}
public JavaMethod getInterfaceMethod(JavaSource pSource,
- ProxyGenerator.InterfaceDescription pDescription,
- java.lang.reflect.Method pMethod) {
+ JavaMethod pMethod) {
JavaMethod jm = pSource.newJavaMethod(pMethod);
Parameter[] parameters = jm.getParams();
List callParameters = new ArrayList();
@@ -268,7 +266,7 @@
callParameters.add(", ");
callParameters.add(parameter.getName());
}
- jm.addLine((Void.TYPE.equals(pMethod.getReturnType()) ? "" : " return "),
+ jm.addLine((JavaQNameImpl.VOID.equals(pMethod.getType()) ? "" : "return "),
"backingObject.",
pMethod.getName(), "(", callParameters, ");");
return jm;
@@ -282,22 +280,25 @@
}
public JavaSource generate(JavaSourceFactory pImplementationFactory,
JavaQName pTargetClass,
- ProxyGenerator.InterfaceDescription[] pDescription) throws ClassNotFoundException {
+ InterfaceDescription[] pDescription) throws Exception {
JavaSource result = super.generate(pImplementationFactory, pTargetClass, pDescription);
getGetHeadOfChainMethod(result);
return result;
}
}
- public JavaSource[] generate(JavaSourceFactory pFactory) throws ClassNotFoundException {
- ProxyGenerator.InterfaceDescription controllerDescription =
- new ProxyGenerator.InterfaceDescription();
+ /** Performs the actual work by generating classes using
+ * the given <code>pFactory</code>.
+ */
+ public JavaSource[] generate(JavaSourceFactory pFactory) throws Exception {
+ InterfaceDescription controllerDescription =
+ new InterfaceDescription();
controllerInterface = getControllerInterface();
- controllerDescription.setInterface(controllerInterface);
+ controllerDescription.setInterface(controllerInterface.getName());
controllerDescription.setMandatory(true);
- ProxyGenerator.InterfaceDescription[] interfaces =
- new ProxyGenerator.InterfaceDescription[]{controllerDescription};
+ InterfaceDescription[] interfaces =
+ new InterfaceDescription[]{controllerDescription};
ProxyGenerator proxyInterfaceGenerator = new ProxyInterfaceGenerator();
JavaSource proxyInterface = proxyInterfaceGenerator.generate(pFactory, getChainInterface(), interfaces);
1.5 +14 -7 ws-jaxme/src/js/org/apache/ws/jaxme/js/pattern/Ant.java
Index: Ant.java
===================================================================
RCS file: /home/cvs/ws-jaxme/src/js/org/apache/ws/jaxme/js/pattern/Ant.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- Ant.java 15 Aug 2004 11:46:28 -0000 1.4
+++ Ant.java 5 Sep 2004 15:42:26 -0000 1.5
@@ -178,15 +178,22 @@
}
}
+ /** The <code>AntProxyGenerator</code> is an Ant task
+ * providing access to the {@link ProxyGenerator}.
+ */
public static class AntProxyGenerator extends BasicAntTask {
private JavaQName extendedClass;
private List implementedInterfaces = new ArrayList();
+ /** Sets the class being extended, if any.
+ */
public void setExtendedClass(String pTargetClass) {
extendedClass = getJavaQName(pTargetClass);
}
- public ProxyGenerator.InterfaceDescription createImplementedInterface() {
- ProxyGenerator.InterfaceDescription result = new ProxyGenerator.InterfaceDescription();
+ /** Adds a new interface being implemented.
+ */
+ public InterfaceDescription createImplementedInterface() {
+ InterfaceDescription result = new InterfaceDescription();
implementedInterfaces.add(result);
return result;
}
@@ -204,9 +211,9 @@
}
try {
proxyGenerator.generate(pFactory, pTargetClass,
- (ProxyGenerator.InterfaceDescription[])
- implementedInterfaces.toArray(new ProxyGenerator.InterfaceDescription[implementedInterfaces.size()]));
- } catch (ClassNotFoundException e) {
+ (InterfaceDescription[])
+ implementedInterfaces.toArray(new InterfaceDescription[implementedInterfaces.size()]));
+ } catch (Exception e) {
throw new BuildException(e, getLocation());
}
}
@@ -262,7 +269,7 @@
ChainGenerator chain = (ChainGenerator) iter.next();
try {
chain.generate(pFactory);
- } catch (ClassNotFoundException e) {
+ } catch (Exception e) {
throw new BuildException(e, getLocation());
}
}
1.6 +159 -287 ws-jaxme/src/js/org/apache/ws/jaxme/js/pattern/ProxyGenerator.java
Index: ProxyGenerator.java
===================================================================
RCS file: /home/cvs/ws-jaxme/src/js/org/apache/ws/jaxme/js/pattern/ProxyGenerator.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ProxyGenerator.java 15 Aug 2004 11:46:28 -0000 1.5
+++ ProxyGenerator.java 5 Sep 2004 15:42:26 -0000 1.6
@@ -16,8 +16,6 @@
*/
package org.apache.ws.jaxme.js.pattern;
-import java.io.Serializable;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -27,6 +25,7 @@
import org.apache.ws.jaxme.js.JavaField;
import org.apache.ws.jaxme.js.JavaMethod;
import org.apache.ws.jaxme.js.JavaQName;
+import org.apache.ws.jaxme.js.JavaQNameImpl;
import org.apache.ws.jaxme.js.JavaSource;
import org.apache.ws.jaxme.js.JavaSourceFactory;
import org.apache.ws.jaxme.js.Parameter;
@@ -37,309 +36,186 @@
* {@link java.lang.reflect.Proxy} class: It delegates its method
* calls to an internal instance.</p>
* <p>In the case of {@link java.lang.reflect.Proxy} this works by
- * calling a so-called {@link java.lang.reflect.InvocationHandler}.
+ * invoking a so-called {@link java.lang.reflect.InvocationHandler}.
* The InvocationHandler calls the actual object via Java reflection.</p>
* <p>In our case, the proxy object is an instance of a generated
* class. The main advantage of the generated approach is that you
* can customize the proxy class quite easily by overwriting it.
* Compared to the creation of an InvocationHandler, this saves a
* lot of hazzle.</p>
- *
- * @author <a href="mailto:joe@ispsoft.de">Jochen Wiedmann</a>
- * @version $Id$
*/
public class ProxyGenerator {
- /** <p>This class describes a generated method. The class is used to guarantee,
- * that the generated methods are unique, even if multiple interfaces define
- * them.</p>
- */
- protected static class GeneratedMethod implements Serializable, Comparable {
- private JavaMethod method;
- private String name;
- private Class[] parameters;
- private Class declaringInterface;
- /** <p>Sets the JavaMethod generated for this method.</p>
- */
- public void setMethod(JavaMethod pMethod) { method = pMethod; }
- /** <p>Returns the JavaMethod generated for this method.</p>
- */
- public JavaMethod getMethod() { return method; }
- /** <p>Sets the methods name.</p>
- */
- public void setName(String pName) { name = pName; }
- /** <p>Returns the methods name.</p>
- */
- public String getName() { return name; }
- /** <p>Sets the methods parameters.</p>
- */
- public void setParameters(Class[] pParameters) { parameters = pParameters; }
- /** <p>Returns the methods parameters.</p>
- */
- public Class[] getParameters() { return parameters; }
- /** <p>Sets the interface declaring this method.</p>
- */
- public void setDeclaringInterface(Class pInterface) {
- declaringInterface = pInterface;
- }
- /** <p>Returns the interface declaring this method.</p>
- */
- public Class getDeclaringInterface() {
- return declaringInterface;
- }
- /** <p>Returns whether this GeneratedMethod equals the object <code>o</code>.
- * This is the case, if <code>o != null</code>, <code>o instanceof GeneratedMethod</code>,
- * and <code>compareTo(o) != 0</code>.</p>
- */
- public boolean equals(Object o) {
- if (o == null || !(o instanceof GeneratedMethod)) { return false; }
- return compareTo(o) == 0;
- }
- /** <p>Compares this GeneratedMethod to the given GeneratedMethod <code>o</code>.
- * More precise, compares the method name, the number of parameters and the
- * class names of the parameters, in that order.</p>
- * @throws ClassCastException The object o is not an instance of GeneratedMethod.
- */
- public int compareTo(Object o) {
- GeneratedMethod gm = (GeneratedMethod) o;
- if (name == null) {
- if (gm.name != null) { return -1; }
- } else if (gm.name == null) {
- return 1;
- } else {
- int result = name.compareTo(gm.name);
- if (result != 0) { return result; }
- }
- if (parameters == null) {
- if (gm.parameters != null) { return -1; }
- } else if (gm.parameters == null) {
- return 1;
- } else {
- if (parameters.length != gm.parameters.length) {
- return parameters.length - gm.parameters.length;
- }
- for (int i = 0; i < parameters.length; i++) {
- Class c1 = parameters[i];
- Class c2 = gm.parameters[i];
- if (c1 == null) {
- if (c2 != null) { return -1; }
- } else if (c2 == null) {
- return 1;
- } else {
- int result = c1.getName().compareTo(c2.getName());
- if (result != 0) { return result; }
- }
- }
- }
- return 0;
- }
- public int hashCode() {
- int result = (name == null) ? 0 : name.hashCode();
- if (parameters != null) {
- result += parameters.length;
- for (int i = 0; i < parameters.length; i++) {
- Class c = parameters[i];
- if (c != null) {
- result += c.getName().hashCode();
- }
- }
- }
- return result;
- }
- }
-
+ /** This class is a key for generated methods. The main
+ * purpose is to determine, whether some method is
+ * present in more than one interface. In that case
+ * we have to ensure, that it is generated only once.
+ */
+ public static class MethodKey implements Comparable {
+ private JavaMethod method;
- /** <p>This class describes the properties of an interface, which is extended
- * by the generated class.</p>
- */
- public static class InterfaceDescription {
- Class interfaceClass;
- boolean isMandatory = true;
+ /** Creates a new instance of {@link MethodKey}.
+ */
+ public MethodKey(JavaMethod pMethod) {
+ method = pMethod;
+ }
- /** <p>Sets the Java interface. Similar to
- * <code>setInterface(Class.forName(pName))</code>.</p>
- */
- public void setInterfaceName(String pName) throws ClassNotFoundException {
- ClassNotFoundException ex = null;
- try {
- Class c = Class.forName(pName);
- if (c != null) {
- setInterface(c);
- return;
+ /** <p>Returns whether this method key equals the object <code>o</code>.
+ * This is the case, if <code>o != null</code>,
+ * <code>o instanceof MethodKey</code>,
+ * and <code>compareTo(o) == 0</code>.</p>
+ */
+ public boolean equals(Object o) {
+ if (o == null || !(o instanceof MethodKey)) { return false; }
+ return compareTo(o) == 0;
}
- } catch (ClassNotFoundException e) {
- ex = e;
- }
- try {
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
- if (cl != null) {
- Class c = cl.loadClass(pName);
- if (c != null) {
- setInterface(c);
- return;
- }
- } else {
- throw new ClassNotFoundException(pName);
+
+ /** <p>Compares this GeneratedMethod to the given GeneratedMethod <code>o</code>.
+ * More precise, compares the method name, the number of parameters
+ * and the class names of the parameters, in that order.</p>
+ * @throws ClassCastException The object o is not an instance of MethodKey.
+ */
+ public int compareTo(Object o) {
+ MethodKey other = (MethodKey) o;
+ int result = method.getName().compareTo(other.method.getName());
+ if (result != 0) {
+ return result;
+ }
+ Parameter[] params = method.getParams();
+ Parameter[] oparams = other.method.getParams();
+ result = params.length - oparams.length;
+ if (result != 0) {
+ return result;
+ }
+ for (int i = 0; i < params.length; i++) {
+ result = params[i].getType().toString().compareTo(oparams[i].getType().toString());
+ if (result != 0) {
+ return result;
+ }
+ }
+ return 0;
+ }
+ public int hashCode() {
+ int result = method.getName().hashCode();
+ Parameter[] params = method.getParams();
+ result += params.length;
+ for (int i = 0; i < params.length; i++) {
+ result += params[i].getType().toString().hashCode();
+ }
+ return result;
}
- } catch (ClassNotFoundException e) {
- if (ex == null) { ex = e; }
- }
- if (ex == null) {
- ex = new ClassNotFoundException("Failed to load class: " + pName);
- }
- throw ex;
}
- /** <p>Sets the Java interface.</p>
- */
- public void setInterface(Class pClass) {
- if (!pClass.isInterface()) {
- throw new IllegalArgumentException("The class " + pClass.getName() +
- " is not an interface.");
- }
- interfaceClass = pClass;
- }
- /** <p>Returns the Java interface.</p>
- */
- public Class getInterface() { return interfaceClass; }
- /** <p>Sets whether this interface is mandatory. By default interfaces
- * are mandatory and the backing objects must implement this interface.
- * If an interface isn't mandatory, then a Proxy instance can be created
- * even for objects which don't implement the interface. However, in that
- * case it may happen that a ClassCastException is thrown while invoking
- * a method declared by the interface.</p>
- */
- public void setMandatory(boolean pMandatory) { isMandatory = pMandatory; }
- /** <p>Returns whether this interface is mandatory. By default interfaces
- * are mandatory and the backing objects must implement this interface.
- * If an interface isn't mandatory, then a Proxy instance can be created
- * even for objects which don't implement the interface. However, in that
- * case it may happen that a ClassCastException is thrown while invoking
- * a method declared by the interface.</p>
- */
- public boolean isMandatory() { return isMandatory; }
- }
- private JavaQName extendedClass;
+ private JavaQName extendedClass;
- /** <p>Returns the class extended by the generated proxy class.
- * Defaults to {@link java.lang.Object}.</p>
- */
- public JavaQName getExtendedClass() {
- return extendedClass;
- }
-
- /** <p>Sets the class extended by the generated proxy class.
- * Defaults to {@link java.lang.Object}.</p>
- */
- public void setExtendedClass(JavaQName pExtendedClass) {
- extendedClass = pExtendedClass;
- }
+ /** <p>Returns the class extended by the generated proxy class.
+ * Defaults to {@link java.lang.Object}.</p>
+ */
+ public JavaQName getExtendedClass() {
+ return extendedClass;
+ }
- /** <p>Converts the given {@link Method} into an instance of
- * {@link GeneratedMethod}.</p>
+ /** <p>Sets the class extended by the generated proxy class.
+ * Defaults to {@link java.lang.Object}.</p>
*/
- protected GeneratedMethod getGeneratedMethod(Method pMethod) {
- GeneratedMethod result = new GeneratedMethod();
- result.setDeclaringInterface(pMethod.getDeclaringClass());
- result.setName(pMethod.getName());
- result.setParameters(pMethod.getParameterTypes());
- return result;
+ public void setExtendedClass(JavaQName pExtendedClass) {
+ extendedClass = pExtendedClass;
}
- /** <p>Generated an instance of {@link JavaMethod} for the given
- * {@link Method}.</p>
- * @throws ClassNotFoundException
- */
- protected JavaMethod getInterfaceMethod(JavaSource pJs,
- InterfaceDescription pInterfaceDescription,
- Method pMethod) throws ClassNotFoundException {
- JavaMethod jm = pJs.newJavaMethod(pMethod);
- Parameter[] parameters = jm.getParams();
+ /** <p>Generated an instance of {@link JavaMethod} for the given
+ * {@link JavaMethod}.</p>
+ */
+ protected JavaMethod getInterfaceMethod(JavaSource pJs,
+ JavaMethod pMethod) throws ClassNotFoundException {
+ JavaMethod jm = pJs.newJavaMethod(pMethod);
+ Parameter[] parameters = jm.getParams();
List callParameters = new ArrayList();
- for (int i = 0; i < parameters.length; i++) {
+ for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
- if (callParameters.size() > 0) {
- callParameters.add(", ");
- }
- callParameters.add(parameter.getName());
+ if (callParameters.size() > 0) {
+ callParameters.add(", ");
}
- jm.addLine((Void.TYPE.equals(pMethod.getReturnType()) ? "" : " return "),
- "((", pInterfaceDescription.getInterface(), ") backingObject).",
- pMethod.getName(), "(", callParameters, ");");
+ callParameters.add(parameter.getName());
+ }
+ if (pMethod.getType().equals(JavaQNameImpl.VOID)) {
+ jm.addLine("((", pMethod.getJavaSource().getQName(), ") backingObject).",
+ pMethod.getName(), "(", callParameters, ");");
+ } else {
+ jm.addLine("return ",
+ "((", pMethod.getJavaSource().getQName(), ") backingObject).",
+ pMethod.getName(), "(", callParameters, ");");
+ }
return jm;
}
- /** <p>Generates the methods for a given interface.</p>
- *
- * @param pJs The Java class being generated
- * @param pGeneratedMethods A set of already generated methods; each entry in the
- * set is an instance of {@link GeneratedMethod}. The method creates a new instance
- * of {@link GeneratedMethod} and adds it to the set. A warning is written to
- * {@link System#err}, if the method isn't unique.
- * @throws ClassNotFoundException
- */
- protected void generateInterfaceMethods(JavaSource pJs, Map pGeneratedMethods,
- InterfaceDescription pDescription) throws ClassNotFoundException {
- Class c = pDescription.interfaceClass;
- Method[] methods = c.getMethods();
- if (methods != null) {
- for (int i = 0; i < methods.length; i++) {
- Method method = methods[i];
- GeneratedMethod generatedMethod = getGeneratedMethod(method);
- GeneratedMethod existingMethod = (GeneratedMethod) pGeneratedMethods.get(generatedMethod);
- if (existingMethod != null) {
- if (generatedMethod.getDeclaringInterface().equals(existingMethod.getDeclaringInterface())) {
- // Already done, skip it
- continue;
- } else {
- System.err.println("The interfaces " + existingMethod.getDeclaringInterface().getName() +
- "." + existingMethod.getName() + " and " +
- generatedMethod.getDeclaringInterface().getName() +
- "." + generatedMethod.getName() + " are identical, ignoring the latter.");
- }
- } else {
- pGeneratedMethods.put(generatedMethod, generatedMethod);
- generatedMethod.setMethod(getInterfaceMethod(pJs, pDescription, method));
- }
- }
- }
- }
+ /** <p>Generates the methods for a given interface.</p>
+ *
+ * @param pJs The Java class being generated
+ * @param pGeneratedMethods A set of already generated methods; each entry in the
+ * set is an instance of {@link MethodKey}. The method creates a new instance
+ * of {@link MethodKey} and adds it to the set. A warning is written to
+ * {@link System#err}, if the method isn't unique.
+ * @throws ClassNotFoundException
+ */
+ protected void generateInterfaceMethods(JavaSource pJs, Map pGeneratedMethods,
+ JavaSource pInterface)
+ throws ClassNotFoundException {
+ JavaMethod[] methods = pInterface.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ JavaMethod method = methods[i];
+ MethodKey key = new MethodKey(method);
+ JavaMethod existingMethod = (JavaMethod) pGeneratedMethods.get(key);
+ if (existingMethod == null) {
+ JavaMethod generatedMethod = getInterfaceMethod(pJs, method);
+ pGeneratedMethods.put(key, generatedMethod);
+ } else {
+ System.err.println("The methods "
+ + existingMethod.getJavaSource().getQName()
+ + "." + existingMethod.getName() + " and "
+ + pInterface.getQName() + "."
+ + method.getName() + " are identical, ignoring the latter.");
+ }
+ }
+ }
- /** <p>Creates a constructor with protected access and a single argument,
- * the backing object.</p>
- */
- protected JavaConstructor getConstructor(JavaSource pJs, InterfaceDescription[] pInterfaces) {
- JavaConstructor jcon = pJs.newJavaConstructor(JavaSource.PROTECTED);
+ /** <p>Creates a constructor with protected access and a single argument,
+ * the backing object.</p>
+ */
+ protected JavaConstructor getConstructor(JavaSource pJs,
+ InterfaceDescription[] pInterfaces)
+ throws Exception{
+ JavaConstructor jcon = pJs.newJavaConstructor(JavaSource.PROTECTED);
jcon.addParam(Object.class, "o");
- jcon.addIf("o == null");
- jcon.addThrowNew(NullPointerException.class,
- JavaSource.getQuoted("The supplied object must not be null."));
- jcon.addEndIf();
+ jcon.addIf("o == null");
+ jcon.addThrowNew(NullPointerException.class,
+ JavaSource.getQuoted("The supplied object must not be null."));
+ jcon.addEndIf();
for (int i = 0; i < pInterfaces.length; i++) {
- if (pInterfaces[i].isMandatory) {
- jcon.addIf("!(o instanceof ", pInterfaces[i].getInterface(), ")");
- jcon.addThrowNew(ClassCastException.class,
- JavaSource.getQuoted("The supplied instance of "),
- " + o.getClass().getName() + ",
- JavaSource.getQuoted(" is not implementing "),
- " + ", pInterfaces[i].getInterface(), ".class.getName()");
- jcon.addEndIf();
+ if (pInterfaces[i].isMandatory()) {
+ JavaSource js = pInterfaces[i].getJavaSource();
+ jcon.addIf("!(o instanceof ", js.getQName(), ")");
+ jcon.addThrowNew(ClassCastException.class,
+ JavaSource.getQuoted("The supplied instance of "),
+ " + o.getClass().getName() + ",
+ JavaSource.getQuoted(" is not implementing "),
+ " + ", js.getQName(), ".class.getName()");
+ jcon.addEndIf();
}
}
jcon.addLine("backingObject = o;");
return jcon;
}
- /** <p>Creates the class.</p>
- */
- protected JavaSource getJavaSource(JavaSourceFactory pFactory, JavaQName pTargetName) {
- return pFactory.newJavaSource(pTargetName, JavaSource.PUBLIC);
- }
-
- /** <p>Generates the <code>backingObject</code> field.</p>
- */
- protected JavaField getBackingObjectField(JavaSource pJs, InterfaceDescription[] pInterfaces) {
- return pJs.newJavaField("backingObject", Object.class, JavaSource.PRIVATE);
- }
+ /** <p>Creates the class.</p>
+ */
+ protected JavaSource getJavaSource(JavaSourceFactory pFactory, JavaQName pTargetName) {
+ return pFactory.newJavaSource(pTargetName, JavaSource.PUBLIC);
+ }
+
+ /** <p>Generates the <code>backingObject</code> field.</p>
+ */
+ protected JavaField getBackingObjectField(JavaSource pJs, InterfaceDescription[] pInterfaces) {
+ return pJs.newJavaField("backingObject", Object.class, JavaSource.PRIVATE);
+ }
/** <p>Generates a class implementing the given interfaces.</p>
* @param pFactory The ProxyGenerator will use this factory for creating
@@ -349,27 +225,23 @@
* @throws ClassNotFoundException
*/
public JavaSource generate(JavaSourceFactory pFactory, JavaQName pTargetName,
- InterfaceDescription[] pInterfaces) throws ClassNotFoundException {
- for (int i = 0; i < pInterfaces.length; i++) {
- if (pInterfaces[i] == null || pInterfaces[i].interfaceClass == null) {
- throw new NullPointerException("The interfaces being implemented must be non-null");
- }
- }
-
- JavaSource js = getJavaSource(pFactory, pTargetName);
- if (getExtendedClass() != null) {
- js.addExtends(getExtendedClass());
- }
- for (int i = 0; i < pInterfaces.length; i++) {
- js.addImplements(pInterfaces[i].getInterface());
- }
+ InterfaceDescription[] pInterfaces)
+ throws Exception {
+ JavaSource js = getJavaSource(pFactory, pTargetName);
+ if (getExtendedClass() != null) {
+ js.addExtends(getExtendedClass());
+ }
+ for (int i = 0; i < pInterfaces.length; i++) {
+ JavaQName qName = pInterfaces[i].getJavaSource().getQName();
+ js.addImplements(qName);
+ }
- getBackingObjectField(js, pInterfaces);
+ getBackingObjectField(js, pInterfaces);
getConstructor(js, pInterfaces);
Map methods = new HashMap();
for (int i = 0; i < pInterfaces.length; i++) {
- generateInterfaceMethods(js, methods, pInterfaces[i]);
+ generateInterfaceMethods(js, methods, pInterfaces[i].getJavaSource());
}
return js;
1.1 ws-jaxme/src/js/org/apache/ws/jaxme/js/pattern/InterfaceDescription.java
Index: InterfaceDescription.java
===================================================================
package org.apache.ws.jaxme.js.pattern;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Iterator;
import org.apache.ws.jaxme.js.JavaMethod;
import org.apache.ws.jaxme.js.JavaQNameImpl;
import org.apache.ws.jaxme.js.JavaSource;
import org.apache.ws.jaxme.js.JavaSourceFactory;
import org.apache.ws.jaxme.js.util.JavaParser;
import antlr.RecognitionException;
import antlr.TokenStreamException;
/** The <code>InterfaceDescription</code> is used by the
* {@link ProxyGenerator} as information storage about
* the interfaces being implemented.<br>
* The main purporse of an intermediate class is to
* encapsulate the way, how information about these
* classes is gathered:
* <ol>
* <li>If the interface being implemented is a compiled
* class, then Java reflection is used.</li>
* <li>Otherwise, if the interface being implemented is
* present as a Java source file, then the
* {@link org.apache.ws.jaxme.js.util.JavaParser}
* is used.</li>
* </ol
*/
public class InterfaceDescription {
private class IDJavaSource {
private final JavaSource js;
/** Creates a new instance of IDJavaSource, storing
* information about the given Java source file
* <code>pInterfaceName</code>.
* @throws TokenStreamException An error occured in the Java lexer.
* @throws RecognitionException An error occured in the Java parser.
* @throws IllegalArgumentException The class is not an interface
*/
public IDJavaSource(String pInterfaceName)
throws IOException, RecognitionException, TokenStreamException {
JavaSourceFactory jsf = new JavaSourceFactory();
JavaParser jp = new JavaParser(jsf);
ClassLoader[] classLoaders = getClassLoaders();
String resource = pInterfaceName.replace('.', '/') + ".class";
URL url = null;
for (int i = 0; i < classLoaders.length; i++) {
url = classLoaders[i].getResource(pInterfaceName);
if (url != null) {
break;
}
}
if (url == null) {
throw new IOException("Failed to locate resource " + resource
+ " in class path.");
}
jp.parse(new InputStreamReader(url.openStream()));
String className = pInterfaceName;
int offset = className.lastIndexOf('.');
if (offset >= 0) {
className = pInterfaceName.substring(offset+1);
}
JavaSource myjs = null;
for (Iterator iter = jsf.getJavaSources(); iter.hasNext(); ) {
JavaSource source = (JavaSource) iter.next();
if (source.getQName().getClassName().equals(className)) {
myjs = source;
break;
}
}
if (myjs == null) {
throw new IllegalStateException("Class " + className
+ " not found in parsed Java file "
+ url);
}
js = myjs;
if (!js.isInterface()) {
throw new IllegalArgumentException("Class " + js.getQName()
+ " is not an interface.");
}
}
/** Returns the generated instance of {@link JavaSource}.
*/
public JavaSource getJavaSource() {
return js;
}
}
private class IDReflection {
private final Class interfaceClass;
/** Creates a new instance of IDReflection, storing
* information about the given, compiled class
* <code>pInterfaceName</code>.
* @throws ClassNotFoundException The class could not be loaded
* @throws IllegalArgumentException The class is not an interface
*/
public IDReflection(String pInterfaceName) throws ClassNotFoundException {
ClassLoader[] classLoaders = getClassLoaders();
Class c = null;
ClassNotFoundException ex = null;
for (int i = 0; c == null && i < classLoaders.length; i++) {
try {
c = classLoaders[i].loadClass(pInterfaceName);
} catch (ClassNotFoundException e) {
if (ex == null) {
ex = e;
}
}
}
if (c == null) {
if (ex == null) {
ex = new ClassNotFoundException("Unable to load class: " + pInterfaceName);
}
throw ex;
}
interfaceClass = c;
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException("The class " + c.getName()
+ " is not an interface.");
}
}
/** <p>Converts the given {@link Method} into an instance of
* {@link JavaSource}.</p>
*/
protected JavaMethod getMethod(JavaSource pSource, Method pMethod) {
JavaMethod method = pSource.newJavaMethod(pMethod.getName(),
JavaQNameImpl.getInstance(pMethod.getReturnType()),
JavaSource.PUBLIC);
Class[] classes = pMethod.getParameterTypes();
for (int i = 0; i < classes.length; i++) {
method.addParam(classes[i], "arg" + i);
}
Class[] exceptions = pMethod.getExceptionTypes();
for (int i = 0; i < exceptions.length; i++) {
method.addThrows(exceptions[i]);
}
return method;
}
/** Reads the interface methods and converts them
* into an instance of {@link JavaSource}.
*/
public JavaSource getJavaSource() {
JavaSource js = new JavaSourceFactory().newJavaSource(JavaQNameImpl.getInstance(interfaceClass.getName()));
Method[] methods = interfaceClass.getMethods();
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
if (!Modifier.isPublic(m.getModifiers())) {
continue;
}
if (Modifier.isStatic(m.getModifiers())) {
continue;
}
getMethod(js, m);
}
return js;
}
}
private boolean isMandatory = true;
private String interfaceName;
private String type;
private JavaSource javaSource;
private ClassLoader[] getClassLoaders() {
return new ClassLoader[]{
Thread.currentThread().getContextClassLoader(),
IDReflection.class.getClassLoader(),
ClassLoader.getSystemClassLoader()
};
}
/** Sets the name of the interface being implemented.
*/
public void setInterface(String pName) {
interfaceName = pName;
}
/** Returns the name of the interface being implemented.
*/
public String getInterface() {
return interfaceName;
}
/** Sets, how to gather information about the interface.
* Supported values are "Reflection" (Java reflection),
* or "Source" ({@link org.apache.ws.jaxme.js.util.JavaParser}).
* The default is null, in which case "Reflection" and "Source"
* are tried, in that order.
*/
public void setType(String pType) {
if (pType == null
|| "Reflection".equalsIgnoreCase(pType)
|| "Source".equalsIgnoreCase(pType)) {
type = pType;
} else {
throw new IllegalArgumentException("Invalid type: " + pType +
", expected 'Reflection', 'Source', or null.");
}
}
/** Returns, how to gather information about the interface.
* Supported values are "Reflection" (Java reflection),
* or "Source" ({@link org.apache.ws.jaxme.js.util.JavaParser}).
* The default is null, in which case "Reflection" and "Source"
* are tried, in that order.
*/
public String getType() {
return type;
}
/** Sets whether this interface is mandatory. By default interfaces
* are mandatory and the backing objects must implement this interface.
* If an interface isn't mandatory, then a Proxy instance can be created
* even for objects which don't implement the interface. However, in that
* case it may happen that a ClassCastException is thrown while invoking
* a method declared by the interface.
*/
public void setMandatory(boolean pMandatory) { isMandatory = pMandatory; }
/** Returns whether this interface is mandatory. By default interfaces
* are mandatory and the backing objects must implement this interface.
* If an interface isn't mandatory, then a Proxy instance can be created
* even for objects which don't implement the interface. However, in that
* case it may happen that a ClassCastException is thrown while invoking
* a method declared by the interface.
*/
public boolean isMandatory() { return isMandatory; }
/** Returns an instance of {@link JavaSource}, matching
* the interface {@link #getInterface()}.
*/
public JavaSource getJavaSource() throws Exception {
if (javaSource == null) {
javaSource = initJavaSource();
}
return javaSource;
}
/** Initializes the object, after all parameters are set.
*/
private JavaSource initJavaSource() throws Exception {
Exception ex = null;
String mode = getType();
if (mode == null || "Reflection".equals(mode)) {
try {
IDReflection idReflection = new IDReflection(getInterface());
return idReflection.getJavaSource();
} catch (Exception e) {
ex = e;
}
}
if (mode == null || "Source".equals(mode)) {
try {
IDJavaSource idJavaSource = new IDJavaSource(getInterface());
return idJavaSource.getJavaSource();
} catch (Exception e) {
if (ex != null) {
ex = e;
}
}
}
if (ex == null) {
throw new IllegalStateException("Failed to locate Java class "
+ getInterface());
} else {
throw ex;
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: jaxme-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: jaxme-dev-help@ws.apache.org