KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ws > jaxme > js > pattern > ProxyGenerator


1 /*
2  * Copyright 2003, 2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15
16  */

17 package org.apache.ws.jaxme.js.pattern;
18
19 import java.util.ArrayList JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Map JavaDoc;
23
24 import org.apache.ws.jaxme.js.JavaConstructor;
25 import org.apache.ws.jaxme.js.JavaField;
26 import org.apache.ws.jaxme.js.JavaMethod;
27 import org.apache.ws.jaxme.js.JavaQName;
28 import org.apache.ws.jaxme.js.JavaQNameImpl;
29 import org.apache.ws.jaxme.js.JavaSource;
30 import org.apache.ws.jaxme.js.JavaSourceFactory;
31 import org.apache.ws.jaxme.js.Parameter;
32
33
34 /** <p>This class is a generator for the proxy object pattern. A proxy
35  * object performs the same task as an object created by the
36  * {@link java.lang.reflect.Proxy} class: It delegates its method
37  * calls to an internal instance.</p>
38  * <p>In the case of {@link java.lang.reflect.Proxy} this works by
39  * invoking a so-called {@link java.lang.reflect.InvocationHandler}.
40  * The InvocationHandler calls the actual object via Java reflection.</p>
41  * <p>In our case, the proxy object is an instance of a generated
42  * class. The main advantage of the generated approach is that you
43  * can customize the proxy class quite easily by overwriting it.
44  * Compared to the creation of an InvocationHandler, this saves a
45  * lot of hazzle.</p>
46  */

47 public class ProxyGenerator {
48     private JavaQName extendedClass;
49
50     /** <p>Returns the class extended by the generated proxy class.
51      * Defaults to {@link java.lang.Object}.</p>
52      */

53     public JavaQName getExtendedClass() {
54         return extendedClass;
55     }
56
57     /** <p>Sets the class extended by the generated proxy class.
58      * Defaults to {@link java.lang.Object}.</p>
59      */

60     public void setExtendedClass(JavaQName pExtendedClass) {
61         extendedClass = pExtendedClass;
62     }
63
64     /** <p>Generated an instance of {@link JavaMethod} for the given
65      * {@link JavaMethod}.</p>
66      */

67     protected JavaMethod getInterfaceMethod(JavaSource pJs,
68                                             JavaMethod pMethod) {
69         JavaMethod jm = pJs.newJavaMethod(pMethod);
70         Parameter[] parameters = jm.getParams();
71         List JavaDoc callParameters = new ArrayList JavaDoc();
72         for (int i = 0; i < parameters.length; i++) {
73             Parameter parameter = parameters[i];
74             if (callParameters.size() > 0) {
75                 callParameters.add(", ");
76             }
77             callParameters.add(parameter.getName());
78         }
79         if (pMethod.getType().equals(JavaQNameImpl.VOID)) {
80             jm.addLine("((", pMethod.getJavaSource().getQName(), ") backingObject).",
81                        pMethod.getName(), "(", callParameters, ");");
82         } else {
83             jm.addLine("return ",
84                        "((", pMethod.getJavaSource().getQName(), ") backingObject).",
85                        pMethod.getName(), "(", callParameters, ");");
86         }
87         return jm;
88     }
89
90     /** <p>Generates the methods for a given interface.</p>
91      *
92      * @param pJs The Java class being generated
93      * @param pGeneratedMethods A set of already generated methods; each entry in the
94      * set is an instance of {@link MethodKey}. The method creates a new instance
95      * of {@link MethodKey} and adds it to the set. A warning is written to
96      * {@link System#err}, if the method isn't unique.
97      * @throws ClassNotFoundException
98      */

99     protected void generateInterfaceMethods(JavaSource pJs, Map JavaDoc pGeneratedMethods,
100                                             JavaSource pInterface)
101             throws ClassNotFoundException JavaDoc {
102         JavaMethod[] methods = pInterface.getMethods();
103         for (int i = 0; i < methods.length; i++) {
104             JavaMethod method = methods[i];
105             if (method.isStatic()) {
106                 continue;
107             }
108             if (!JavaSource.PUBLIC.equals(method.getProtection())) {
109                 continue;
110             }
111             MethodKey key = new MethodKey(method);
112             JavaMethod existingMethod = (JavaMethod) pGeneratedMethods.get(key);
113             if (existingMethod == null) {
114                 JavaMethod generatedMethod = getInterfaceMethod(pJs, method);
115                 pGeneratedMethods.put(key, generatedMethod);
116             } else {
117                 System.err.println("The methods "
118                         + existingMethod.getJavaSource().getQName()
119                         + "." + existingMethod.getName() + " and "
120                         + pInterface.getQName() + "."
121                         + method.getName() + " are identical, ignoring the latter.");
122             }
123         }
124     }
125
126     /** <p>Creates a constructor with protected access and a single argument,
127      * the backing object.</p>
128      */

129     protected JavaConstructor getConstructor(JavaSource pJs,
130                                              InterfaceDescription[] pInterfaces)
131             throws Exception JavaDoc{
132         JavaConstructor jcon = pJs.newJavaConstructor(JavaSource.PROTECTED);
133         jcon.addParam(Object JavaDoc.class, "o");
134         jcon.addIf("o == null");
135         jcon.addThrowNew(NullPointerException JavaDoc.class,
136                          JavaSource.getQuoted("The supplied object must not be null."));
137         jcon.addEndIf();
138         for (int i = 0; i < pInterfaces.length; i++) {
139             if (pInterfaces[i].isMandatory()) {
140                 JavaSource js = pInterfaces[i].getJavaSource();
141                 jcon.addIf("!(o instanceof ", js.getQName(), ")");
142                 jcon.addThrowNew(ClassCastException JavaDoc.class,
143                                  JavaSource.getQuoted("The supplied instance of "),
144                                  " + o.getClass().getName() + ",
145                                  JavaSource.getQuoted(" is not implementing "),
146                                  " + ", js.getQName(), ".class.getName()");
147                 jcon.addEndIf();
148             }
149         }
150         jcon.addLine("backingObject = o;");
151         return jcon;
152     }
153
154     /** <p>Creates the class.</p>
155      */

156     protected JavaSource getJavaSource(JavaSourceFactory pFactory, JavaQName pTargetName) {
157         return pFactory.newJavaSource(pTargetName, JavaSource.PUBLIC);
158     }
159
160     /** <p>Generates the <code>backingObject</code> field.</p>
161      */

162     protected JavaField getBackingObjectField(JavaSource pJs, InterfaceDescription[] pInterfaces) {
163         return pJs.newJavaField("backingObject", Object JavaDoc.class, JavaSource.PRIVATE);
164     }
165
166     /** <p>Generates a class implementing the given interfaces.</p>
167      * @param pFactory The ProxyGenerator will use this factory for creating
168      * instances of JavaSource.
169      * @param pTargetName Name of the generated class
170      * @param pInterfaces The interfaces being implemented by the generated class.
171      * @throws ClassNotFoundException
172      */

173     public JavaSource generate(JavaSourceFactory pFactory, JavaQName pTargetName,
174                                InterfaceDescription[] pInterfaces)
175             throws Exception JavaDoc {
176         JavaSource js = getJavaSource(pFactory, pTargetName);
177         if (getExtendedClass() != null) {
178             js.addExtends(getExtendedClass());
179         }
180         for (int i = 0; i < pInterfaces.length; i++) {
181             JavaQName qName = pInterfaces[i].getJavaSource().getQName();
182             js.addImplements(qName);
183         }
184
185         getBackingObjectField(js, pInterfaces);
186         getConstructor(js, pInterfaces);
187
188         Map JavaDoc methods = new HashMap JavaDoc();
189         for (int i = 0; i < pInterfaces.length; i++) {
190             generateInterfaceMethods(js, methods, pInterfaces[i].getJavaSource());
191         }
192
193         return js;
194     }
195 }
196
Popular Tags