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.resource.spi.endpoint.MessageEndpoint;
00041 import javax.transaction.Status;
00042 import javax.transaction.SystemException;
00043 import javax.transaction.UserTransaction;
00044 import javax.transaction.xa.XAResource;
00045
00046 import org.objectweb.jonas_ejb.deployment.api.MethodDesc;
00047
00048 import org.objectweb.security.context.SecurityContext;
00049 import org.objectweb.security.context.SecurityCurrent;
00050
00051 import org.objectweb.transaction.jta.TransactionManager;
00052 import org.objectweb.util.monolog.api.BasicLevel;
00053
00061 public class JMessageEndpoint implements MessageDrivenContext {
00062
00063 protected JMdbEndpointFactory bf = null;
00064
00065 protected MessageDrivenBean mdb = null;
00066
00067 protected MessageEndpoint mep = null;
00068
00069 protected int txattr;
00070
00071
00072 protected TransactionManager tm = null;
00073
00074 protected XAResource xar = null;
00075
00076 protected boolean released = false;
00077
00078 private static final int MAX_NB_RETRY = 2;
00079
00085 public JMessageEndpoint(JMdbEndpointFactory bf, MessageDrivenBean mdb) {
00086 this.bf = bf;
00087 this.mdb = mdb;
00088
00089 txattr = bf.getTransactionAttribute();
00090 tm = bf.getTransactionManager();
00091 }
00092
00093 public void setProxy(MessageEndpoint mep) {
00094 this.mep = mep;
00095 }
00096
00097 public XAResource getXAResource() {
00098 return xar;
00099 }
00100
00101 public void setXAResource(XAResource xa) {
00102 xar = xa;
00103
00104 }
00105
00106 public boolean getReleasedState() {
00107 return released;
00108 }
00109
00110 public void setReleasedState(boolean state) {
00111 released = state;
00112 }
00113
00114
00115
00116
00117
00124 public TimerService getTimerService() throws IllegalStateException {
00125 TraceEjb.interp.log(BasicLevel.DEBUG, "");
00126 return bf.getTimerService();
00127 }
00128
00129
00130
00131
00132
00133 private static final String DISALLOWED_MSG = " is disallowed in a message driven bean";
00134
00140 public Identity getCallerIdentity() {
00141 TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
00142 throw new IllegalStateException("getCallerIdentity()" + DISALLOWED_MSG);
00143 }
00144
00149 public Principal getCallerPrincipal() {
00150 boolean inRunAs = false;
00151 if (bf.dd.getRunAsRole() != null) {
00152 inRunAs = true;
00153 }
00154
00155 SecurityCurrent current = SecurityCurrent.getCurrent();
00156 if (current != null) {
00157 SecurityContext sctx = current.getSecurityContext();
00158 if (sctx == null) {
00159 TraceEjb.security.log(BasicLevel.DEBUG, "runas : Security context is null, create a new one");
00160 sctx = new SecurityContext();
00161 current.setSecurityContext(sctx);
00162 }
00163 }
00164
00165 Principal principal = bf.getContainer().getPrincipalFactory().getCallerPrincipal(inRunAs);
00166 if (principal == null) {
00167 throw new IllegalStateException("No principal exists in security context");
00168 }
00169 return principal;
00170 }
00171
00177 public boolean isCallerInRole(Identity role) {
00178 TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
00179 throw new IllegalStateException("isCallerInRole()" + DISALLOWED_MSG);
00180 }
00181
00187 public boolean isCallerInRole(java.lang.String roleLink) {
00188 TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
00189 throw new IllegalStateException("isCallerInRole()" + DISALLOWED_MSG);
00190 }
00191
00198 public void setRollbackOnly() {
00199
00200 TraceEjb.mdb.log(BasicLevel.DEBUG, "");
00201
00202 if(bf.isTxBeanManaged())
00203 throw new IllegalStateException("Bean-managed transaction, not use this method.");
00204 try {
00205 tm.setRollbackOnly();
00206 } catch (IllegalStateException e) {
00207 TraceEjb.logger.log(BasicLevel.ERROR, "current thread not associated with transaction");
00208 throw e;
00209 } catch (SystemException e) {
00210 TraceEjb.logger.log(BasicLevel.ERROR, "unexpected exception:", e);
00211 }
00212 }
00213
00218 public boolean getRollbackOnly() {
00219 TraceEjb.mdb.log(BasicLevel.DEBUG, "");
00220 if(bf.isTxBeanManaged())
00221 throw new IllegalStateException("Bean-managed transaction, not use this method.");
00222 try {
00223 if (tm.getTransaction() != null) {
00224 switch (tm.getStatus()) {
00225 case Status.STATUS_MARKED_ROLLBACK:
00226 case Status.STATUS_ROLLEDBACK:
00227 case Status.STATUS_ROLLING_BACK:
00228 return true;
00229 case Status.STATUS_NO_TRANSACTION:
00230 throw new IllegalStateException("No transaction");
00231 default:
00232 return false;
00233 }
00234 } else {
00235 TraceEjb.logger.log(BasicLevel.ERROR, "the bean is not associated in a transaction");
00236 throw new IllegalStateException("the message driven bean is not associated in a transaction");
00237 }
00238 } catch (SystemException e) {
00239 TraceEjb.logger.log(BasicLevel.ERROR, "cannot get status:", e);
00240 return false;
00241 }
00242 }
00243
00248 public EJBHome getEJBHome() {
00249 TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
00250 throw new IllegalStateException("getEJBHome()" + DISALLOWED_MSG);
00251 }
00252
00257 public EJBLocalHome getEJBLocalHome() {
00258 TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
00259 throw new IllegalStateException("getEJBLocalHome()" + DISALLOWED_MSG);
00260 }
00261
00266 public Properties getEnvironment() {
00267 TraceEjb.logger.log(BasicLevel.ERROR, "deprecated use : Use the JNDI naming context java:comp/env");
00268 return new java.util.Properties();
00269 }
00270
00279 public UserTransaction getUserTransaction() throws IllegalStateException {
00280
00281 TraceEjb.mdb.log(BasicLevel.DEBUG, "");
00282
00283 if (!bf.isTxBeanManaged()) {
00284 throw new IllegalStateException("This bean is not allowed to use UserTransaction interface");
00285 }
00286 return (UserTransaction) tm;
00287 }
00288
00289
00290
00291
00292
00297 public void deliverTimeout(Timer timer) {
00298 TraceEjb.mdb.log(BasicLevel.DEBUG, "");
00299
00300 boolean committed = false;
00301 for (int nbretry = 0; ! committed && nbretry < MAX_NB_RETRY; nbretry++) {
00302 RequestCtx rctx = null;
00303 try {
00304
00305 rctx = bf.preInvoke(MethodDesc.TX_REQUIRED);
00306 } catch (Exception e) {
00307 TraceEjb.logger.log(BasicLevel.ERROR, "preInvoke failed: ", e);
00308 return;
00309 }
00310 try {
00311 bf.checkSecurity(null);
00312 if (mdb instanceof TimedObject) {
00313 ((TimedObject) mdb).ejbTimeout(timer);
00314 } else {
00315 throw new EJBException("The bean does not implement the `TimedObject` interface");
00316 }
00317 committed = ! getRollbackOnly();
00318 } catch (EJBException e) {
00319 rctx.sysExc = e;
00320 TraceEjb.logger.log(BasicLevel.ERROR, "EJB exception thrown by an enterprise Bean", e);
00321 } catch (RuntimeException e) {
00322 rctx.sysExc = e;
00323 TraceEjb.logger.log(BasicLevel.ERROR, "runtime exception thrown by an enterprise Bean", e);
00324 } catch (Error e) {
00325 rctx.sysExc = e;
00326 TraceEjb.logger.log(BasicLevel.ERROR, "error thrown by an enterprise Bean", e);
00327 } finally {
00328 try {
00329 bf.postInvoke(rctx);
00330 } catch (Exception e) {
00331 TraceEjb.logger.log(BasicLevel.ERROR, "exception on postInvoke: ", e);
00332 }
00333 }
00334 }
00335 }
00336 }