00001
00026 package org.objectweb.jonas_ejb.container;
00027
00028 import java.security.Identity;
00029 import java.security.Principal;
00030 import java.util.Properties;
00031
00032 import javax.ejb.EJBException;
00033 import javax.ejb.EJBHome;
00034 import javax.ejb.EJBLocalHome;
00035 import javax.ejb.MessageDrivenBean;
00036 import javax.ejb.MessageDrivenContext;
00037 import javax.ejb.TimedObject;
00038 import javax.ejb.Timer;
00039 import javax.ejb.TimerService;
00040 import javax.jms.JMSException;
00041 import javax.jms.Message;
00042 import javax.jms.MessageListener;
00043 import javax.jms.ServerSession;
00044 import javax.jms.Session;
00045 import javax.jms.XASession;
00046 import javax.transaction.Status;
00047 import javax.transaction.SystemException;
00048 import javax.transaction.UserTransaction;
00049 import javax.transaction.xa.XAResource;
00050
00051 import org.objectweb.jonas_ejb.deployment.api.MethodDesc;
00052
00053 import org.objectweb.transaction.jta.TransactionManager;
00054 import org.objectweb.util.monolog.api.BasicLevel;
00055
00065 public class JMessageDrivenBean implements MessageListener, ServerSession, Runnable, MessageDrivenContext {
00066
00067 protected Session sess = null;
00068
00069 protected JMdbFactory bf = null;
00070
00071 protected MessageDrivenBean mdb = null;
00072
00077 protected int txattr;
00078
00083 protected int timerTxAttr;
00084
00085 protected TransactionManager tm = null;
00086
00087 protected ThreadPool thpool = null;
00088
00096 public JMessageDrivenBean(JMdbFactory bf, Session sess, MessageDrivenBean mdb, ThreadPool thpool) {
00097 this.bf = bf;
00098 this.sess = sess;
00099 this.mdb = mdb;
00100 this.thpool = thpool;
00101
00102 txattr = bf.getTransactionAttribute();
00103 timerTxAttr = bf.getTimerTxAttribute();
00104 tm = bf.getTransactionManager();
00105 }
00106
00107
00108
00109
00110
00117 public TimerService getTimerService() throws IllegalStateException {
00118 TraceEjb.interp.log(BasicLevel.DEBUG, "");
00119 return bf.getTimerService();
00120 }
00121
00122
00123
00124
00125
00132 public synchronized void onMessage(Message message) {
00133 TraceEjb.mdb.log(BasicLevel.DEBUG, "");
00134
00135 RequestCtx rctx = null;
00136 try {
00137
00138 if (tm.getTransaction() != null) {
00139
00140 TraceEjb.logger.log(BasicLevel.ERROR, "Transaction already OPENED");
00141 TraceEjb.logger.log(BasicLevel.ERROR, "Transaction = " + tm.getTransaction());
00142 Thread.dumpStack();
00143 return;
00144 }
00145
00146 rctx = bf.preInvoke(txattr);
00147 bf.checkSecurity(null);
00148 if (rctx.mustCommit) {
00149 TraceEjb.tx.log(BasicLevel.DEBUG, "enlistResource");
00150 rctx.currTx.enlistResource(((XASession) sess).getXAResource());
00151 }
00152 } catch (Exception e) {
00153 TraceEjb.logger.log(BasicLevel.ERROR, "preInvoke failed: ", e);
00154 return;
00155 }
00156 try {
00157 TraceEjb.mdb.log(BasicLevel.DEBUG, "Call MDB");
00158 ((MessageListener) mdb).onMessage(message);
00159 TraceEjb.mdb.log(BasicLevel.DEBUG, "Return from MDB");
00160 } catch (RuntimeException e) {
00161 rctx.sysExc = e;
00162 TraceEjb.logger.log(BasicLevel.ERROR, "runtime exception thrown by an enterprise Bean", e);
00163 } catch (Error e) {
00164 rctx.sysExc = e;
00165 TraceEjb.logger.log(BasicLevel.ERROR, "error thrown by an enterprise Bean", e);
00166 } finally {
00167 try {
00168 if (rctx.mustCommit) {
00169 TraceEjb.tx.log(BasicLevel.DEBUG, "delistResource");
00170 rctx.currTx.delistResource(((XASession) sess).getXAResource(), XAResource.TMSUCCESS);
00171 }
00172 bf.postInvoke(rctx);
00173 } catch (Exception e) {
00174 TraceEjb.logger.log(BasicLevel.ERROR, "exception on postInvoke: ", e);
00175 }
00176 }
00177 }
00178
00179
00180
00181
00182
00192 public Session getSession() throws JMSException {
00193 TraceEjb.mdb.log(BasicLevel.DEBUG, "");
00194 return sess;
00195 }
00196
00203 public void start() throws JMSException {
00204 TraceEjb.mdb.log(BasicLevel.DEBUG, "");
00205 thpool.addRunnable(this);
00206 }
00207
00208
00209
00210
00211
00216 public void run() {
00217 TraceEjb.mdb.log(BasicLevel.DEBUG, "");
00218
00219
00220
00221 Thread.currentThread().setContextClassLoader(bf.myClassLoader());
00222
00223 sess.run();
00224 bf.releaseServerSession(this);
00225 }
00226
00227
00228
00229
00230
00231 private static final String DISALLOWED_MSG = " is disallowed in a message driven bean";
00232
00238 public Identity getCallerIdentity() {
00239 TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
00240 throw new IllegalStateException("getCallerIdentity()" + DISALLOWED_MSG);
00241 }
00242
00249 public Principal getCallerPrincipal() {
00250 TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
00251 throw new IllegalStateException("getCallerPrincipal()" + DISALLOWED_MSG);
00252 }
00253
00259 public boolean isCallerInRole(Identity role) {
00260 TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
00261 throw new IllegalStateException("isCallerInRole()" + DISALLOWED_MSG);
00262 }
00263
00269 public boolean isCallerInRole(java.lang.String roleLink) {
00270 TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
00271 throw new IllegalStateException("isCallerInRole()" + DISALLOWED_MSG);
00272 }
00273
00280 public void setRollbackOnly() {
00281
00282 TraceEjb.mdb.log(BasicLevel.DEBUG, "");
00283 try {
00284 tm.setRollbackOnly();
00285 } catch (IllegalStateException e) {
00286 TraceEjb.logger.log(BasicLevel.ERROR, "current thread not associated with transaction");
00287 throw e;
00288 } catch (SystemException e) {
00289 TraceEjb.logger.log(BasicLevel.ERROR, "unexpected exception:", e);
00290 }
00291 }
00292
00297 public boolean getRollbackOnly() {
00298 TraceEjb.mdb.log(BasicLevel.DEBUG, "");
00299
00300 try {
00301 if (tm.getTransaction() != null) {
00302 switch (tm.getStatus()) {
00303 case Status.STATUS_MARKED_ROLLBACK:
00304 case Status.STATUS_ROLLEDBACK:
00305 case Status.STATUS_ROLLING_BACK:
00306 return true;
00307 case Status.STATUS_NO_TRANSACTION:
00308 throw new IllegalStateException("No transaction");
00309 default:
00310 return false;
00311 }
00312 } else {
00313 TraceEjb.logger.log(BasicLevel.ERROR, "the bean is not associated in a transaction");
00314 throw new IllegalStateException("the message driven bean is not associated in a transaction");
00315 }
00316 } catch (SystemException e) {
00317 TraceEjb.logger.log(BasicLevel.ERROR, "cannot get status:", e);
00318 return false;
00319 }
00320 }
00321
00326 public EJBHome getEJBHome() {
00327 TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
00328 throw new IllegalStateException("getEJBHome()" + DISALLOWED_MSG);
00329 }
00330
00335 public EJBLocalHome getEJBLocalHome() {
00336 TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
00337 throw new IllegalStateException("getEJBLocalHome()" + DISALLOWED_MSG);
00338 }
00339
00344 public Properties getEnvironment() {
00345 TraceEjb.logger.log(BasicLevel.ERROR, "deprecated use : Use the JNDI naming context java:comp/env");
00346 return new java.util.Properties();
00347 }
00348
00357 public UserTransaction getUserTransaction() throws IllegalStateException {
00358
00359 TraceEjb.mdb.log(BasicLevel.DEBUG, "");
00360
00361 if (!bf.isTxBeanManaged()) {
00362 throw new IllegalStateException("This bean is not allowed to use UserTransaction interface");
00363 }
00364 return (UserTransaction) tm;
00365 }
00366
00367
00368
00369
00370
00375 public void deliverTimeout(Timer timer) {
00376 TraceEjb.mdb.log(BasicLevel.DEBUG, "");
00377
00378 RequestCtx rctx = null;
00379 try {
00380 rctx = bf.preInvoke(timerTxAttr);
00381 } catch (Exception e) {
00382 TraceEjb.logger.log(BasicLevel.ERROR, "preInvoke failed: ", e);
00383 return;
00384 }
00385 try {
00386 bf.checkSecurity(null);
00387 if (mdb instanceof TimedObject) {
00388 ((TimedObject) mdb).ejbTimeout(timer);
00389 } else {
00390 throw new EJBException("The bean does not implement the `TimedObject` interface");
00391 }
00392 } catch (EJBException e) {
00393 rctx.sysExc = e;
00394 TraceEjb.logger.log(BasicLevel.ERROR, "EJB exception thrown by an enterprise Bean", e);
00395 } catch (RuntimeException e) {
00396 rctx.sysExc = e;
00397 TraceEjb.logger.log(BasicLevel.ERROR, "runtime exception thrown by an enterprise Bean", e);
00398 } catch (Error e) {
00399 rctx.sysExc = e;
00400 TraceEjb.logger.log(BasicLevel.ERROR, "error thrown by an enterprise Bean", e);
00401 } finally {
00402 try {
00403 bf.postInvoke(rctx);
00404 } catch (Exception e) {
00405 TraceEjb.logger.log(BasicLevel.ERROR, "exception on postInvoke: ", e);
00406 }
00407 }
00408 }
00409 }