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.gen;
030:
031: import com.caucho.ejb.cfg.*;
032: import com.caucho.java.JavaWriter;
033: import com.caucho.java.gen.BaseMethod;
034: import com.caucho.java.gen.CallChain;
035: import com.caucho.java.gen.FilterCallChain;
036: import com.caucho.java.gen.MethodCallChain;
037: import com.caucho.util.L10N;
038:
039: import java.io.IOException;
040: import java.util.ArrayList;
041: import java.util.logging.*;
042:
043: import javax.ejb.*;
044: import javax.ejb.ApplicationException;
045:
046: /**
047: * Generates the skeleton for a method call.
048: */
049: public class TransactionChain extends FilterCallChain {
050: private static final Logger log = Logger
051: .getLogger(TransactionChain.class.getName());
052: private static final L10N L = new L10N(TransactionChain.class);
053:
054: private ApiMethod _apiMethod;
055: private ApiMethod _implMethod;
056:
057: private ApiClass _businessInterface;
058:
059: private TransactionAttributeType _xaType;
060:
061: private boolean _isEJB3;
062:
063: private ArrayList<ApplicationExceptionConfig> _appExceptions;
064:
065: public TransactionChain(CallChain next,
066: TransactionAttributeType xaType, ApiMethod apiMethod,
067: ApiMethod implMethod) {
068: this (next, xaType, apiMethod, implMethod, false, null);
069: }
070:
071: public TransactionChain(CallChain next,
072: TransactionAttributeType xaType, ApiMethod apiMethod,
073: ApiMethod implMethod, boolean isEJB3,
074: ArrayList<ApplicationExceptionConfig> appExceptions) {
075: super (next);
076:
077: _xaType = xaType;
078: _apiMethod = apiMethod;
079: _implMethod = implMethod;
080: _isEJB3 = isEJB3;
081: _appExceptions = appExceptions;
082:
083: if (implMethod == null)
084: _implMethod = apiMethod;
085: }
086:
087: public static TransactionChain create(CallChain next,
088: TransactionAttributeType xaType, ApiMethod apiMethod,
089: ApiMethod implMethod) {
090: return new TransactionChain(next, xaType, apiMethod, implMethod);
091: }
092:
093: public static TransactionChain create(CallChain next,
094: TransactionAttributeType xaType, ApiMethod apiMethod,
095: ApiMethod implMethod, boolean isEJB3,
096: ArrayList<ApplicationExceptionConfig> appExceptions) {
097: return new TransactionChain(next, xaType, apiMethod,
098: implMethod, isEJB3, appExceptions);
099: }
100:
101: /**
102: * Prints a call within the same JVM
103: *
104: * @param methodName the name of the method to call
105: * @param method the method to call
106: */
107: public void generateCall(JavaWriter out, String retType,
108: String var, String[] args) throws IOException {
109: // ejb/0ff0 TCK: ejb30/bb/session/stateful/sessioncontext/annotated/getInvokedBusinessInterfaceRemote2
110: //out.println("if (getServer().getContext() != null)");
111: //out.println(" getServer().getContext().__caucho_setInvokedBusinessInterface(_businessInterface);");
112:
113: if (_isEJB3 && _businessInterface != null) {
114: out.println("if (_context != null)");
115: out
116: .println(" _context.__caucho_setInvokedBusinessInterface("
117: + _businessInterface.getName() + ");");
118: out.println();
119: }
120:
121: out.println("Thread thread = Thread.currentThread();");
122: out
123: .println("ClassLoader oldLoader = thread.getContextClassLoader();");
124:
125: out
126: .print("javax.transaction.Transaction oldTrans = _xaManager.getTransaction();");
127: out.println();
128:
129: out.print("com.caucho.ejb.xa.TransactionContext trans");
130:
131: if (_xaType != null) {
132: switch (_xaType) {
133: /*
134: case EjbMethod.TRANS_SINGLE_READ:
135: out.println(" = _xaManager.beginSingleRead();");
136: break;
137: */
138:
139: case REQUIRES_NEW:
140: out.println(" = _xaManager.beginRequiresNew();");
141: break;
142: //case EjbMethod.TRANS_BEAN:
143: case NOT_SUPPORTED:
144: out.println(" = _xaManager.suspend();");
145: break;
146: case NEVER:
147: out.println(" = _xaManager.beginNever();");
148: break;
149: case REQUIRED:
150: out.println(" = _xaManager.beginRequired();");
151: break;
152: case MANDATORY:
153: out.println(" = _xaManager.beginMandatory();");
154: break;
155: default:
156: case SUPPORTS:
157: out.println(" = _xaManager.beginSupports();");
158: break;
159: }
160: }
161:
162: out.println("try {");
163: out.pushDepth();
164:
165: out
166: .println("thread.setContextClassLoader(_context._server.getClassLoader());");
167: out.println();
168:
169: /* XXX: need to check something like _context.isDead() instead
170: // ejb/0fe4: throws exception if this context has been removed.
171: out.println("getServer().getContext(_context.getPrimaryKey());");
172: out.println();
173: */
174:
175: super .generateCall(out, retType, var, args);
176:
177: out.popDepth();
178: out.println("} catch (Exception e) {");
179: out.pushDepth();
180:
181: Class beanClass = _implMethod.getDeclaringClass();
182:
183: if (_isEJB3) { // XXX && ! _implMethod.isAnnotationPresent(javax.ejb.Remove.class)) {
184: generateExceptionHandling(out);
185: }
186:
187: /*
188: if (! out.isSession())
189: out.println("if (ptr != null) ptr._ejb_state = QEntity._CAUCHO_IS_DEAD;");
190: */
191:
192: out
193: .println("e = com.caucho.ejb.EJBExceptionWrapper.create(e);");
194: out.println();
195:
196: // TCK: needs QA, ejb30/bb/localaccess/statefulclient/exceptionTest1
197: //if (_xaType != EjbMethod.TRANS_BEAN) {
198: if (_xaType != null) {
199: out.println("if (trans.getTransaction() != oldTrans) {");
200: out.println(" throw trans.setRollbackOnly(e);");
201: out.println("}");
202: }
203:
204: // ejb/02b1
205: out.println("throw (javax.ejb.EJBException) e;");
206:
207: out.popDepth();
208:
209: out.println("} finally {");
210: out.pushDepth();
211:
212: out.println("thread.setContextClassLoader(oldLoader);");
213:
214: // TCK: needs QA, ejb30/bb/localaccess/statefulclient/exceptionTest1
215: // if (_xaType != EjbMethod.TRANS_BEAN)
216: // ejb/0224 vs TCK
217: //out.println("if (trans.getTransaction() != oldTrans)");
218: // XXX TCK: ejb30/bb/session/stateful/sessioncontext/annotated/getInvokedBusinessInterfaceLocal1
219: out.println(" trans.commit();");
220:
221: /*
222: if (out.isSession())
223: out.println("if (ptr != null) ptr._ejb_isActive = false;");
224: */
225:
226: out.popDepth();
227: out.println("}");
228: }
229:
230: protected void generateExceptionHandling(JavaWriter out)
231: throws IOException {
232: // boolean isCmt = _xaType != EjbMethod.TRANS_BEAN;
233: boolean isCmt = _xaType != null;
234:
235: // ejb/0fb9
236: out
237: .println("if (e instanceof com.caucho.ejb.EJBExceptionWrapper)");
238: out.println(" e = (Exception) e.getCause();");
239: out.println();
240:
241: out
242: .println("if (e instanceof java.lang.reflect.InvocationTargetException)");
243: out.println(" e = (Exception) e.getCause();");
244: out.println();
245:
246: Class beanClass = _implMethod.getDeclaringClass();
247:
248: // ejb/0500
249: Class exnTypes[]; // = getExceptionTypes();
250:
251: // ejb/0fb3, ejb/0fbg
252: for (Class cl : _implMethod.getExceptionTypes()) {
253: if (!Exception.class.isAssignableFrom(cl)) {
254: // XXX:
255: // hessian/3600
256: log.info(cl + " is not handled by EJB");
257: continue;
258: }
259:
260: out.println("if (e instanceof " + cl.getName() + ") {");
261: out.pushDepth();
262:
263: if (isCmt) {
264: // ejb/0fc0, ejb/0fc1
265: // TCK: ejb30/bb/session/stateful/annotation/appexception/annotated/atCheckedRollbackAppExceptionTest
266:
267: boolean isApplicationException = false;
268: boolean isRollback = false;
269:
270: // Check @ApplicationException(rollback=true/false)
271: ApplicationException ann = (ApplicationException) cl
272: .getAnnotation(ApplicationException.class);
273:
274: if (ann != null) {
275: isApplicationException = true;
276: isRollback = ann.rollback();
277: } else if (_appExceptions != null) {
278: // ejb/0fc3
279: for (ApplicationExceptionConfig cfg : _appExceptions) {
280: if (cfg.getExceptionClass()
281: .equals(cl.getName())) {
282: isApplicationException = true;
283: isRollback = cfg.isRollback();
284: break;
285: }
286: }
287: }
288:
289: if (!isApplicationException) {
290: // ejb/0fc0
291: out
292: .println("if (trans.getTransaction() != oldTrans)");
293: out.println(" trans.setRollbackOnly(e);");
294: } else if (isRollback) {
295: // ejb/0fc1
296: out.println("trans.setRollbackOnly(e);");
297: }
298: // else do not rollback.
299: }
300:
301: out.println("throw (" + cl.getName() + ") e;");
302:
303: out.popDepth();
304: out.println("}");
305: out.println();
306: }
307: }
308: }
|