00001
00026 package org.objectweb.jonas_ejb.container;
00027
00028 import java.lang.reflect.InvocationHandler;
00029 import java.lang.reflect.InvocationTargetException;
00030 import java.lang.reflect.Method;
00031 import java.lang.reflect.Proxy;
00032
00033 import javax.ejb.MessageDrivenBean;
00034 import javax.ejb.EJBException;
00035 import javax.resource.ResourceException;
00036 import javax.resource.spi.IllegalStateException;
00037 import javax.transaction.xa.XAResource;
00038
00039 import org.objectweb.jonas_ejb.deployment.api.MethodDesc;
00040
00041 import org.objectweb.transaction.jta.TransactionManager;
00042 import org.objectweb.util.monolog.api.BasicLevel;
00043
00051 public class JMessageEndpointProxy implements InvocationHandler {
00052
00053 protected JMdbEndpointFactory bf = null;
00054
00055 protected JMessageEndpoint ep = null;
00056
00057 protected MessageDrivenBean mdb = null;
00058
00059 protected TransactionManager tm = null;
00060
00061 boolean b4Delivery = false;
00062
00063 int msgCount = 0;
00064
00065
00066
00067 private transient static ThreadLocal requestCtx = new ThreadLocal();
00068
00076 public JMessageEndpointProxy(JMdbEndpointFactory bf, MessageDrivenBean mdb, JMessageEndpoint ep) {
00077 this.bf = bf;
00078 this.mdb = mdb;
00079 this.ep = ep;
00080
00081 tm = bf.getTransactionManager();
00082 }
00083
00084
00085
00086
00087
00088 public Object invoke(Object obj, Method method, Object[] aobj) throws Throwable, NoSuchMethodException,
00089 ResourceException, Exception {
00090 RequestCtx rctx = null;
00091 String methodName = method.getName();
00092 Object ret = null;
00093 Throwable invokeEx = null;
00094
00095 TraceEjb.mdb.log(BasicLevel.DEBUG, "Calling " + methodName + " on " + this);
00096 if (ep.released) {
00097 throw new IllegalStateException("Endpoint is in a released state and must be reactivated before using");
00098 }
00099
00100 if ("equals".equals(methodName)) {
00101 Object obj1 = null;
00102 if (Proxy.isProxyClass(aobj[0].getClass())) {
00103 obj1 = (Object) Proxy.getInvocationHandler(aobj[0]);
00104 } else {
00105 obj1 = aobj[0];
00106 }
00107 ret = new Boolean(this.equals(obj1));
00108 } else if ("hashCode".equals(methodName)) {
00109 ret = new Integer(this.hashCode());
00110 } else if ("toString".equals(methodName)) {
00111 ret = this.toString();
00112 } else if ("afterDelivery".equals(methodName)) {
00113 if (!b4Delivery) {
00114 throw new IllegalStateException(methodName + " called w/o call to beforeDelivery");
00115 }
00116 b4Delivery = false;
00117 msgCount = 0;
00118 rctx = (RequestCtx) requestCtx.get();
00119 try {
00120 if (rctx.mustCommit && ep.getXAResource() != null) {
00121 rctx.currTx.delistResource(ep.getXAResource(), XAResource.TMSUCCESS);
00122 }
00123 bf.postInvoke(rctx);
00124 } catch (Exception e) {
00125 TraceEjb.logger.log(BasicLevel.ERROR, "exception on postInvoke: ", e);
00126 throw new RuntimeException(e);
00127 }
00128 } else if ("beforeDelivery".equals(methodName)) {
00129
00130 TraceEjb.mdb.log(BasicLevel.DEBUG, "beforeDelivery called");
00131 if (b4Delivery) {
00132 throw new IllegalStateException(methodName + " called w/o call to afterDelivery");
00133 }
00134 if (bf.isTxBeanManaged()) {
00135 throw new IllegalStateException(methodName + " cannot be called when using bean managed transactions");
00136 }
00137 if (tm.getTransaction() != null) {
00138 throw new IllegalStateException(methodName + " cannot be called when using an imported transaction");
00139 }
00140 msgCount = 0;
00141
00142 Object obj1 = null;
00143 if (Proxy.isProxyClass(aobj[0].getClass())) {
00144 obj1 = (Object) Proxy.getInvocationHandler(aobj[0]);
00145 } else {
00146 obj1 = aobj[0];
00147 }
00148 Method intentedTargetMethod = (Method) obj1;
00149 String intentedTargetMethodName = intentedTargetMethod.getName();
00150
00151 TraceEjb.mdb.log(BasicLevel.DEBUG, "intentedTargetMethodName=" + intentedTargetMethodName);
00152 try {
00153 TraceEjb.mdb.log(BasicLevel.DEBUG, "before preInvoke");
00154 rctx = bf.preInvoke(getTxAttr(intentedTargetMethod));
00155
00156
00157
00158
00159 requestCtx.set(rctx);
00160 b4Delivery = true;
00161 if (rctx.mustCommit && ep.getXAResource() != null) {
00162
00163 rctx.currTx.enlistResource(ep.getXAResource());
00164 TraceEjb.mdb.log(BasicLevel.DEBUG, "enlistResource Ok");
00165 }
00166 } catch (Exception e) {
00167 TraceEjb.logger.log(BasicLevel.ERROR, "preInvoke failed: ", e);
00168 throw new RuntimeException(e);
00169 }
00170 TraceEjb.mdb.log(BasicLevel.DEBUG, "beforeDelivery ended");
00171 } else if ("release".equals(methodName)) {
00172 bf.releaseEndpoint(ep);
00173 } else {
00174 msgCount++;
00175
00176 if (!b4Delivery) {
00177 boolean isImportedTx = tm.getTransaction() != null;
00178 rctx = bf.preInvoke(getTxAttr(method));
00179
00180
00181
00182 if (rctx.mustCommit) {
00183 if (!isImportedTx) {
00184
00185 if (ep.getXAResource() != null) {
00186 rctx.currTx.enlistResource(ep.getXAResource());
00187 }
00188 } else {
00189 rctx.mustCommit = false;
00190 }
00191 }
00192 bf.checkSecurity(null);
00193 } else if (msgCount > 1) {
00194 throw new IllegalStateException("Unable to deliver multiple messages");
00195 } else {
00196 rctx = (RequestCtx) requestCtx.get();
00197 }
00198 try {
00199 TraceEjb.mdb.log(BasicLevel.DEBUG, "Before invoke");
00200 ret = method.invoke(mdb, aobj);
00201 TraceEjb.mdb.log(BasicLevel.DEBUG, "After invoke");
00202 } catch (InvocationTargetException ite) {
00203 Throwable t = ite.getTargetException();
00204 if (t instanceof RuntimeException) {
00205 if (rctx != null) {
00206 rctx.sysExc = new EJBException((RuntimeException) t);
00207 }
00208 } else {
00209 if (rctx != null) {
00210 rctx.sysExc = t;
00211 }
00212 }
00213 invokeEx = rctx.sysExc;
00214 TraceEjb.logger.log(BasicLevel.ERROR, "error thrown by an enterprise Bean", t);
00215 } catch (Throwable ex) {
00216
00217 if (rctx != null) {
00218 rctx.sysExc = ex;
00219 }
00220 invokeEx = ex;
00221
00222 TraceEjb.logger.log(BasicLevel.ERROR, "error thrown by an enterprise Bean", ex);
00223 } finally {
00224 if (!b4Delivery) {
00225 try {
00226 if (!bf.isTxBeanManaged() && rctx.mustCommit && ep.getXAResource() != null) {
00227 rctx.currTx.delistResource(ep.getXAResource(), XAResource.TMSUCCESS);
00228 }
00229 bf.postInvoke(rctx);
00230 } catch (Exception e) {
00231 TraceEjb.logger.log(BasicLevel.ERROR, "exception on postInvoke: ", e);
00232 if (invokeEx == null) {
00233 invokeEx = e;
00234 }
00235 }
00236 } else {
00237
00238 msgCount = 0;
00239 }
00240 }
00241 }
00242 if (invokeEx != null) {
00243 TraceEjb.logger.log(BasicLevel.ERROR, "Exception raised: ", invokeEx);
00244 throw invokeEx;
00245 }
00246 TraceEjb.mdb.log(BasicLevel.DEBUG, "ret="+ret);
00247 return ret;
00248 }
00249
00250 private int getTxAttr(Method m) {
00251 int ret = MethodDesc.TX_NOT_SUPPORTED;
00252 try {
00253 ret = bf.isDeliveryTransacted(m) ? MethodDesc.TX_REQUIRED : MethodDesc.TX_NOT_SUPPORTED;
00254 } catch (NoSuchMethodException nsme) {
00255 }
00256 return ret;
00257 }
00258 }
00259