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: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.ejb.gen;
031:
032: import com.caucho.java.JavaWriter;
033: import com.caucho.util.L10N;
034:
035: import java.io.*;
036: import java.lang.reflect.*;
037: import java.util.*;
038: import javax.annotation.security.*;
039: import javax.ejb.*;
040: import javax.interceptor.*;
041:
042: /**
043: * Represents the xa interception
044: */
045: public class XaCallChain extends AbstractCallChain {
046: private static final L10N L = new L10N(XaCallChain.class);
047:
048: private BusinessMethodGenerator _bizMethod;
049: private EjbCallChain _next;
050:
051: private boolean _isContainerManaged = true;
052: private TransactionAttributeType _xa;
053: private boolean _isSynchronization;
054:
055: public XaCallChain(BusinessMethodGenerator bizMethod,
056: EjbCallChain next) {
057: super (next);
058:
059: _bizMethod = bizMethod;
060: _next = next;
061: }
062:
063: protected BusinessMethodGenerator getBusinessMethod() {
064: return _bizMethod;
065: }
066:
067: /**
068: * Returns true if the business method has any active XA annotation.
069: */
070: public boolean isEnhanced() {
071: return (_isContainerManaged && _xa != null && !_xa
072: .equals(TransactionAttributeType.SUPPORTS));
073: }
074:
075: public boolean isContainerManaged() {
076: return _isContainerManaged;
077: }
078:
079: public void setContainerManaged(boolean isContainerManaged) {
080: _isContainerManaged = isContainerManaged;
081: }
082:
083: /**
084: * Sets the transaction type
085: */
086: public void setTransactionType(TransactionAttributeType xa) {
087: _xa = xa;
088: }
089:
090: protected TransactionAttributeType getTransactionType() {
091: return _xa;
092: }
093:
094: public void setSynchronization(boolean isSynchronization) {
095: _isSynchronization = isSynchronization;
096: }
097:
098: /**
099: * Introspects the method for the default values
100: */
101: public void introspect(Method apiMethod, Method implMethod) {
102: if (!_isContainerManaged)
103: return;
104:
105: Class apiClass = apiMethod.getDeclaringClass();
106: Class implClass = null;
107:
108: if (implMethod != null)
109: implClass = implMethod.getDeclaringClass();
110:
111: TransactionAttribute xaAttr;
112:
113: xaAttr = apiMethod.getAnnotation(TransactionAttribute.class);
114:
115: if (xaAttr == null) {
116: xaAttr = (TransactionAttribute) apiClass
117: .getAnnotation(TransactionAttribute.class);
118: }
119:
120: if (xaAttr == null && implMethod != null) {
121: xaAttr = implMethod
122: .getAnnotation(TransactionAttribute.class);
123: }
124:
125: if (xaAttr == null && implClass != null) {
126: xaAttr = (TransactionAttribute) implClass
127: .getAnnotation(TransactionAttribute.class);
128: }
129:
130: if (xaAttr != null)
131: setTransactionType(xaAttr.value());
132: }
133:
134: /**
135: * Generates the static class prologue
136: */
137: @Override
138: public void generatePrologue(JavaWriter out, HashMap map)
139: throws IOException {
140: if (_isContainerManaged && map.get("caucho.ejb.xa") == null) {
141: map.put("caucho.ejb.xa", "done");
142:
143: out.println();
144: out
145: .println("private static final com.caucho.ejb3.xa.XAManager _xa");
146: out.println(" = new com.caucho.ejb3.xa.XAManager();");
147: }
148:
149: _next.generatePrologue(out, map);
150: }
151:
152: /**
153: * Generates the method interceptor code
154: */
155: public void generateCall(JavaWriter out) throws IOException {
156: boolean isPushDepth = false;
157:
158: if (_isContainerManaged && _xa != null) {
159: switch (_xa) {
160: case MANDATORY: {
161: out.println("_xa.beginMandatory();");
162: }
163: break;
164:
165: case NEVER: {
166: out.println("_xa.beginNever();");
167: }
168: break;
169:
170: case NOT_SUPPORTED: {
171: out
172: .println("Transaction xa = _xa.beginNotSupported();");
173: out.println();
174: out.println("try {");
175: out.pushDepth();
176: isPushDepth = true;
177: }
178: break;
179:
180: case REQUIRED: {
181: out.println("Transaction xa = _xa.beginRequired();");
182: out.println();
183: out.println("try {");
184: out.pushDepth();
185: isPushDepth = true;
186: }
187: break;
188:
189: case REQUIRES_NEW: {
190: out.println("Transaction xa = _xa.beginRequiresNew();");
191: out.println();
192: out.println("try {");
193: out.pushDepth();
194: isPushDepth = true;
195: }
196: break;
197: }
198: }
199:
200: if (_isSynchronization) {
201: out.println("_xa.registerSynchronization(_bean);");
202: }
203:
204: generateNext(out);
205:
206: if (_isContainerManaged && _xa != null) {
207: if (isPushDepth)
208: out.popDepth();
209:
210: for (Class exn : _bizMethod.getApiMethod()
211: .getExceptionTypes()) {
212: ApplicationException appExn = (ApplicationException) exn
213: .getAnnotation(ApplicationException.class);
214:
215: if (appExn == null)
216: continue;
217:
218: if (!RuntimeException.class.isAssignableFrom(exn)
219: && appExn.rollback()) {
220: out.println("} catch (" + exn.getName() + " e) {");
221: out.println(" _xa.markRollback(e);");
222: out.println(" throw e;");
223: } else if (RuntimeException.class.isAssignableFrom(exn)
224: && !appExn.rollback()) {
225: out.println("} catch (" + exn.getName() + " e) {");
226: out.println(" throw e;");
227: }
228: }
229:
230: switch (_xa) {
231: case REQUIRED:
232: case REQUIRES_NEW: {
233: out.println("} catch (RuntimeException e) {");
234: out.println(" _xa.markRollback(e);");
235: out.println(" throw e;");
236: }
237: }
238:
239: switch (_xa) {
240: case NOT_SUPPORTED: {
241: out.println("} finally {");
242: out.println(" if (xa != null)");
243: out.println(" _xa.resume(xa);");
244: out.println("}");
245: }
246: break;
247:
248: case REQUIRED: {
249: out.println("} finally {");
250: out.println(" if (xa == null)");
251: out.println(" _xa.commit();");
252: out.println("}");
253: }
254: break;
255:
256: case REQUIRES_NEW: {
257: out.println("} finally {");
258: out.println(" _xa.endRequiresNew(xa);");
259: out.println("}");
260: }
261: break;
262: }
263: }
264: }
265:
266: protected void generateNext(JavaWriter out) throws IOException {
267: _next.generateCall(out);
268: }
269: }
|