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