001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.ejb.gen21;
030:
031: import com.caucho.java.AbstractGenerator;
032: import com.caucho.util.IntMap;
033: import com.caucho.util.L10N;
034: import com.caucho.vfs.IOExceptionWrapper;
035:
036: import javax.ejb.EJBHome;
037: import javax.ejb.EJBLocalHome;
038: import javax.ejb.EJBLocalObject;
039: import javax.ejb.EJBObject;
040: import java.io.IOException;
041: import java.lang.reflect.Method;
042: import java.util.ArrayList;
043:
044: /**
045: * Generator for stubs.
046: */
047: abstract class JVMStubGenerator extends AbstractGenerator {
048: protected static final L10N L = new L10N(JVMStubGenerator.class);
049:
050: // Classes which can be safely passed by reference because they're
051: // immutable and part of the JDK
052: static IntMap _immutableClasses;
053:
054: protected boolean _isProxy = false;
055: protected ArrayList<Method> _proxyMethods = new ArrayList<Method>();
056: protected Class _remoteClass;
057:
058: void setProxy(boolean isProxy) {
059: _isProxy = isProxy;
060: }
061:
062: /**
063: * Prints the header for a HomeStub
064: */
065: abstract protected void printHeader() throws IOException;
066:
067: /**
068: * Prints a direct call for use in the same JVM.
069: *
070: * @param method the method to generate
071: */
072: protected void printMethod(String name, Method method)
073: throws IOException {
074: Class ret = method.getReturnType();
075: Class[] params = method.getParameterTypes();
076:
077: printMethodHeader(name, method);
078:
079: boolean needsSerialization = printMethodHead(params, ret);
080:
081: printCall(method.getName(), params, ret);
082:
083: printMethodFooter(ret, needsSerialization);
084: }
085:
086: protected boolean printMethodHead(Class[] params, Class ret)
087: throws IOException {
088: println("{");
089: pushDepth();
090: println("Thread thread = Thread.currentThread();");
091: println("ClassLoader oldLoader = thread.getContextClassLoader();");
092:
093: boolean needsSerialization = false;
094: for (int i = 0; i < params.length; i++) {
095: if (needsSerialization(params[i])) {
096: if (!needsSerialization) {
097: println("com.caucho.ejb.protocol.SelfSerializer ser;");
098: println("ser = com.caucho.ejb.protocol.SelfSerializer.allocate();");
099: }
100: println("ser.write(a" + i + ");");
101: needsSerialization = true;
102: }
103: }
104:
105: if (needsSerialization(ret) && !needsSerialization) {
106: println("com.caucho.ejb.protocol.SelfSerializer ser;");
107: println("ser = com.caucho.ejb.protocol.SelfSerializer.allocate();");
108: needsSerialization = true;
109: }
110:
111: if (!ret.getName().equals("void")) {
112: printClass(ret);
113: println(" _ret;");
114: }
115:
116: println();
117: if (!_isProxy) {
118: println(_remoteClass.getName() + " obj;");
119: println("obj = (" + _remoteClass.getName()
120: + ") _caucho_getObject();");
121: } else {
122: println("Object obj = _caucho_getObject();");
123: }
124: println("thread.setContextClassLoader(_caucho_getClassLoader());");
125: println("try {");
126: pushDepth();
127:
128: return needsSerialization;
129: }
130:
131: protected void printMethodFooter(Class ret,
132: boolean needsSerialization) throws IOException {
133: if (needsSerialization(ret)) {
134: if (needsSerialization)
135: println("ser.clear();");
136: needsSerialization = true;
137: println("ser.write(_ret);");
138: println("thread.setContextClassLoader(oldLoader);");
139: print("_ret = (");
140: printClass(ret);
141: println(") ser.read();");
142: }
143:
144: popDepth();
145: println("} finally {");
146: pushDepth();
147: println("thread.setContextClassLoader(oldLoader);");
148:
149: if (needsSerialization)
150: println("ser.close();");
151:
152: popDepth();
153: println("}");
154:
155: if (!ret.getName().equals("void"))
156: println("return _ret;");
157:
158: popDepth();
159: println("}");
160: }
161:
162: void printCall(String name, Class[] params, Class retType)
163: throws IOException {
164: if (_isProxy) {
165: printProxyCall(name, params, retType);
166: return;
167: }
168:
169: if (!retType.equals(void.class))
170: print("_ret = ");
171:
172: print("obj." + name + "(");
173: for (int i = 0; i < params.length; i++) {
174: if (i != 0)
175: print(", ");
176: if (needsSerialization(params[i])) {
177: print("(");
178: printClass(params[i]);
179: print(") ser.read()");
180: } else
181: print("a" + i);
182: }
183: println(");");
184: }
185:
186: void printProxyCall(String name, Class[] params, Class retType)
187: throws IOException {
188: Method method;
189:
190: try {
191: method = _remoteClass.getMethod(name, params);
192: } catch (NoSuchMethodException e) {
193: throw new IOExceptionWrapper(e);
194: }
195: _proxyMethods.add(method);
196:
197: if (_isProxy) {
198: println("try {");
199: pushDepth();
200: }
201:
202: int index = _proxyMethods.size() - 1;
203:
204: boolean retNeedsSerialization = needsSerialization(retType);
205:
206: if (retType.equals(void.class)) {
207: } else if (!retNeedsSerialization) {
208: print("_ret = (");
209: printClass(retType);
210: print(")");
211: } else {
212: print("Object _oret = ");
213: }
214:
215: if (retType.isPrimitive())
216: print("com.caucho.ejb.JVMObject.to_" + retType.getName()
217: + "(");
218:
219: print("method" + index + ".invoke(obj, new Object[] {");
220: for (int i = 0; i < params.length; i++) {
221: if (i != 0)
222: print(", ");
223: if (needsSerialization(params[i])) {
224: print("(");
225: printClass(params[i]);
226: print(") ser.read()");
227: } else if (params[i].isPrimitive())
228: printToObject("a" + i, params[i]);
229: else
230: print("a" + i);
231: }
232: if (retType.isPrimitive())
233: println("}));");
234: else
235: println("});");
236:
237: if (retNeedsSerialization) {
238: // println("System.out.println(_oret);");
239: println("ser.clear();");
240: println("ser.write(_oret);");
241: println("thread.setContextClassLoader(oldLoader);");
242: print("_ret = (");
243: printClass(method.getReturnType());
244: println(") ser.read();");
245: }
246:
247: popDepth();
248: println("} catch (java.lang.IllegalAccessException e) {");
249: println(" throw com.caucho.ejb.EJBExceptionWrapper.createRuntime(e);");
250: println("} catch (java.lang.reflect.InvocationTargetException e) {");
251: println(" throw com.caucho.ejb.EJBExceptionWrapper.createRuntime(e);");
252: println("}");
253: }
254:
255: void printToObject(String name, Class cl) throws IOException {
256: if (boolean.class.equals(cl))
257: print("new Boolean(" + name + ")");
258: else if (byte.class.equals(cl))
259: print("new Byte(" + name + ")");
260: else if (short.class.equals(cl))
261: print("new Short(" + name + ")");
262: else if (char.class.equals(cl))
263: print("new Character(" + name + ")");
264: else if (int.class.equals(cl))
265: print("new Integer(" + name + ")");
266: else if (long.class.equals(cl))
267: print("new Long(" + name + ")");
268: else if (float.class.equals(cl))
269: print("new Float(" + name + ")");
270: else if (double.class.equals(cl))
271: print("new Double(" + name + ")");
272: else
273: throw new RuntimeException(L.l(
274: "can't create object for type {0}", cl.getName()));
275: }
276:
277: /**
278: * Prints the class footer for the generated stub.
279: */
280: void printFooter() throws IOException {
281: for (int i = 0; i < _proxyMethods.size(); i++) {
282: println("static java.lang.reflect.Method method" + i + ";");
283: }
284: if (_proxyMethods.size() > 0) {
285: println("protected void _caucho_init_methods(Class cl)");
286: println("{");
287: pushDepth();
288: println("try {");
289: pushDepth();
290: for (int i = 0; i < _proxyMethods.size(); i++) {
291: Method method = _proxyMethods.get(i);
292:
293: print("method" + i + " = cl.getMethod(\"");
294: print(method.getName());
295: print("\", new Class[] {");
296: Class[] paramTypes = method.getParameterTypes();
297: for (int j = 0; j < paramTypes.length; j++) {
298: if (j != 0)
299: print(", ");
300: printClass(paramTypes[j]);
301: print(".class");
302: }
303: println("});");
304: }
305: popDepth();
306: println("} catch (Exception e) {");
307: println(" com.caucho.ejb.EJBExceptionWrapper.createRuntime(e);");
308: println("}");
309: popDepth();
310: println("}");
311: }
312:
313: popDepth();
314: println("}");
315: }
316:
317: /**
318: * Returns true if the class needs serialization.
319: *
320: * @param cl the class to test.
321: *
322: * @return true if the class needs serialization
323: */
324: boolean needsSerialization(Class cl) {
325: if (cl.isPrimitive())
326: return false;
327: else if (!_isProxy && EJBObject.class.isAssignableFrom(cl))
328: return false;
329: else if (!_isProxy && EJBLocalObject.class.isAssignableFrom(cl))
330: return false;
331: else if (!_isProxy && EJBHome.class.isAssignableFrom(cl))
332: return false;
333: else if (!_isProxy && EJBLocalHome.class.isAssignableFrom(cl))
334: return false;
335: else
336: return _immutableClasses.get(cl) < 0;
337: }
338:
339: /**
340: * Generates code for version changes.
341: */
342: protected void printVersionChange() throws IOException {
343: println("if (com.caucho.ejb.Version.getVersionId() != "
344: + com.caucho.ejb.Version.getVersionId() + ")");
345: println(" return true;");
346: }
347:
348: static {
349: _immutableClasses = new IntMap();
350: _immutableClasses.put(String.class, 1);
351: _immutableClasses.put(Byte.class, 1);
352: _immutableClasses.put(Character.class, 1);
353: _immutableClasses.put(Short.class, 1);
354: _immutableClasses.put(Integer.class, 1);
355: _immutableClasses.put(Long.class, 1);
356: _immutableClasses.put(Float.class, 1);
357: _immutableClasses.put(Double.class, 1);
358: _immutableClasses.put(Class.class, 1);
359: }
360: }
|