KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas_ejb > container > JMessageEndpoint


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: JMessageEndpoint.java,v 1.12 2005/04/28 16:52:59 benoitf Exp $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.jonas_ejb.container;
27
28 import java.security.Identity JavaDoc;
29 import java.security.Principal JavaDoc;
30 import java.util.Properties JavaDoc;
31
32 import javax.ejb.EJBException JavaDoc;
33 import javax.ejb.EJBHome JavaDoc;
34 import javax.ejb.EJBLocalHome JavaDoc;
35 import javax.ejb.MessageDrivenBean JavaDoc;
36 import javax.ejb.MessageDrivenContext JavaDoc;
37 import javax.ejb.TimedObject JavaDoc;
38 import javax.ejb.Timer JavaDoc;
39 import javax.ejb.TimerService JavaDoc;
40 import javax.resource.spi.endpoint.MessageEndpoint JavaDoc;
41 import javax.transaction.Status JavaDoc;
42 import javax.transaction.SystemException JavaDoc;
43 import javax.transaction.UserTransaction JavaDoc;
44 import javax.transaction.xa.XAResource JavaDoc;
45
46 import org.objectweb.jonas_ejb.deployment.api.MethodDesc;
47
48 import org.objectweb.security.context.SecurityContext;
49 import org.objectweb.security.context.SecurityCurrent;
50
51 import org.objectweb.transaction.jta.TransactionManager;
52 import org.objectweb.util.monolog.api.BasicLevel;
53
54 /**
55  * Generic interposed class for Message Endpoints This class presents these
56  * interfaces, depending on object reached: MessageDrivenContext interface to
57  * the bean instance
58  * @author Philippe Coq, Philippe Durieux
59  * @author Christophe Ney (Easier Enhydra integration)
60  */

61 public class JMessageEndpoint implements MessageDrivenContext JavaDoc {
62
63     protected JMdbEndpointFactory bf = null;
64
65     protected MessageDrivenBean JavaDoc mdb = null;
66
67     protected MessageEndpoint JavaDoc mep = null;
68
69     protected int txattr; // TX_NOT_SUPPORTED, TX_REQUIRED or TX_NOT_SET (= bean
70
// managed)
71

72     protected TransactionManager tm = null;
73
74     protected XAResource JavaDoc xar = null;
75
76     protected boolean released = false;
77
78     private static final int MAX_NB_RETRY = 2;
79
80     /**
81      * constructor
82      * @param bf The MDB Endpoint Factory
83      * @param mdb The Message Driven Bean
84      */

85     public JMessageEndpoint(JMdbEndpointFactory bf, MessageDrivenBean JavaDoc mdb) {
86         this.bf = bf;
87         this.mdb = mdb;
88         // keep these locally for efficiency.
89
txattr = bf.getTransactionAttribute();
90         tm = bf.getTransactionManager();
91     }
92
93     public void setProxy(MessageEndpoint JavaDoc mep) {
94         this.mep = mep;
95     }
96
97     public XAResource JavaDoc getXAResource() {
98         return xar;
99     }
100
101     public void setXAResource(XAResource JavaDoc xa) {
102         xar = xa;
103         // Check state of transaction to determine what to do
104
}
105
106     public boolean getReleasedState() {
107         return released;
108     }
109
110     public void setReleasedState(boolean state) {
111         released = state;
112     }
113
114     // ------------------------------------------------------------------
115
// EJBContext implementation
116
// ------------------------------------------------------------------
117

118     /**
119      * Get access to the EJB Timer Service.
120      * @return the EJB Timer Service
121      * @throws IllegalStateException Thrown if the instance is not allowed to
122      * use this method
123      */

124     public TimerService JavaDoc getTimerService() throws IllegalStateException JavaDoc {
125         if (TraceEjb.isDebugIc()) {
126             TraceEjb.interp.log(BasicLevel.DEBUG, "");
127         }
128         return bf.getTimerService();
129     }
130
131     // ----------------------------------------------------------------------
132
// javax.ejb.MessageDrivenContext implementation
133
// ----------------------------------------------------------------------
134

135     private static final String JavaDoc DISALLOWED_MSG = " is disallowed in a message driven bean";
136
137     /**
138      * Obtains the java.security.Identity of the caller. disallowed in
139      * messagedriven bean method because there is no security context
140      * @deprecated @exception java.lang.IllegalStateException always
141      */

142     public Identity JavaDoc getCallerIdentity() {
143         TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
144         throw new IllegalStateException JavaDoc("getCallerIdentity()" + DISALLOWED_MSG);
145     }
146
147     /**
148      * @return the java.security.Principal that identifies the caller.
149      * @throws IllegalStateException if there is no principal
150      */

151     public Principal JavaDoc getCallerPrincipal() {
152         boolean inRunAs = false;
153         if (bf.dd.getRunAsRole() != null) {
154             inRunAs = true;
155         }
156         // Set a security context if there was no one set.
157
SecurityCurrent current = SecurityCurrent.getCurrent();
158         if (current != null) {
159             SecurityContext sctx = current.getSecurityContext();
160             if (sctx == null) {
161                 if (TraceEjb.isDebugSecurity()) {
162                     TraceEjb.security.log(BasicLevel.DEBUG, "runas : Security context is null, create a new one");
163                 }
164                 sctx = new SecurityContext();
165                 current.setSecurityContext(sctx);
166             }
167         }
168
169         Principal JavaDoc principal = bf.getContainer().getPrincipalFactory().getCallerPrincipal(inRunAs);
170         if (principal == null) {
171             throw new IllegalStateException JavaDoc("No principal exists in security context");
172         }
173         return principal;
174     }
175
176     /**
177      * Test if the caller has a given role.
178      * @deprecated @throws java.lang.IllegalStateException for message driven
179      * bean because there is no security context available
180      */

181     public boolean isCallerInRole(Identity JavaDoc role) {
182         TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
183         throw new IllegalStateException JavaDoc("isCallerInRole()" + DISALLOWED_MSG);
184     }
185
186     /**
187      * Test if the caller has a given role.
188      * @throws java.lang.IllegalStateException for message driven bean because
189      * there is no security context available
190      */

191     public boolean isCallerInRole(java.lang.String JavaDoc roleLink) {
192         TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
193         throw new IllegalStateException JavaDoc("isCallerInRole()" + DISALLOWED_MSG);
194     }
195
196   /**
197    * Marks the current transaction for rollback. Should be used only if the
198    * instance is associated with a transaction
199    * @throws java.lang.IllegalStateException if the instance is not associated
200    * with a transaction
201    */

202   public void setRollbackOnly() {
203
204       if (TraceEjb.isDebugJms()) {
205           TraceEjb.mdb.log(BasicLevel.DEBUG, "");
206       }
207
208     if(bf.isTxBeanManaged())
209       throw new IllegalStateException JavaDoc("Bean-managed transaction, not use this method.");
210     try {
211       tm.setRollbackOnly();
212     } catch (IllegalStateException JavaDoc e) {
213       TraceEjb.logger.log(BasicLevel.ERROR, "current thread not associated with transaction");
214       throw e;
215     } catch (SystemException JavaDoc e) {
216       TraceEjb.logger.log(BasicLevel.ERROR, "unexpected exception:", e);
217     }
218   }
219
220   /**
221    * Tests if the transaction has been marked for rollback only.
222    * @return True if transaction has been marked for rollback.
223    */

224   public boolean getRollbackOnly() {
225       if (TraceEjb.isDebugJms()) {
226           TraceEjb.mdb.log(BasicLevel.DEBUG, "");
227       }
228     if(bf.isTxBeanManaged())
229       throw new IllegalStateException JavaDoc("Bean-managed transaction, not use this method.");
230     try {
231       if (tm.getTransaction() != null) {
232         switch (tm.getStatus()) {
233         case Status.STATUS_MARKED_ROLLBACK:
234         case Status.STATUS_ROLLEDBACK:
235         case Status.STATUS_ROLLING_BACK:
236           return true;
237         case Status.STATUS_NO_TRANSACTION:
238           throw new IllegalStateException JavaDoc("No transaction");
239         default:
240           return false;
241         }
242       } else {
243         TraceEjb.logger.log(BasicLevel.ERROR, "the bean is not associated in a transaction");
244         throw new IllegalStateException JavaDoc("the message driven bean is not associated in a transaction");
245       }
246     } catch (SystemException JavaDoc e) {
247       TraceEjb.logger.log(BasicLevel.ERROR, "cannot get status:", e);
248       return false;
249     }
250   }
251
252     /**
253      * Is disallowed. There is no home for message driven bean.
254      * @throws IllegalStateException Always.
255      */

256     public EJBHome JavaDoc getEJBHome() {
257         TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
258         throw new IllegalStateException JavaDoc("getEJBHome()" + DISALLOWED_MSG);
259     }
260
261     /**
262      * Is disallowed. There is no local home for message driven bean.
263      * @throws IllegalStateException Always.
264      */

265     public EJBLocalHome JavaDoc getEJBLocalHome() {
266         TraceEjb.logger.log(BasicLevel.ERROR, DISALLOWED_MSG);
267         throw new IllegalStateException JavaDoc("getEJBLocalHome()" + DISALLOWED_MSG);
268     }
269
270     /**
271      * @deprecated Use the JNDI naming context java:comp/env instead.
272      * @return properties for the bean.
273      */

274     public Properties JavaDoc getEnvironment() {
275         TraceEjb.logger.log(BasicLevel.ERROR, "deprecated use : Use the JNDI naming context java:comp/env");
276         return new java.util.Properties JavaDoc();
277     }
278
279     /**
280      * Obtains the transaction demarcation interface.
281      * @return The UserTransaction interface that the enterprise bean instance
282      * can use for transaction demarcation.
283      * @exception IllegalStateException: Thrown if the instance container does
284      * not make the UserTransaction interface available to the
285      * instance.
286      */

287     public UserTransaction JavaDoc getUserTransaction() throws IllegalStateException JavaDoc {
288
289         if (TraceEjb.isDebugJms()) {
290             TraceEjb.mdb.log(BasicLevel.DEBUG, "");
291         }
292
293         if (!bf.isTxBeanManaged()) {
294             throw new IllegalStateException JavaDoc("This bean is not allowed to use UserTransaction interface");
295         }
296         return (UserTransaction JavaDoc) tm;
297     }
298
299     // -----------------------------------------------------------------------
300
// other public methods
301
// -----------------------------------------------------------------------
302

303     /**
304      * Deliver a timeout to the bean
305      * @param timer timer whose expiration caused this notification.
306      */

307     public void deliverTimeout(Timer JavaDoc timer) {
308         if (TraceEjb.isDebugJms()) {
309             TraceEjb.mdb.log(BasicLevel.DEBUG, "");
310         }
311
312         boolean committed = false;
313         for (int nbretry = 0; ! committed && nbretry < MAX_NB_RETRY; nbretry++) {
314             RequestCtx rctx = null;
315             try {
316                 // For MDB, transaction attribute must be required or NotSupported.
317
rctx = bf.preInvoke(MethodDesc.TX_REQUIRED);
318             } catch (Exception JavaDoc e) {
319                 TraceEjb.logger.log(BasicLevel.ERROR, "preInvoke failed: ", e);
320                 return;
321             }
322             try {
323                 bf.checkSecurity(null);
324                 if (mdb instanceof TimedObject JavaDoc) {
325                     ((TimedObject JavaDoc) mdb).ejbTimeout(timer);
326                 } else {
327                     throw new EJBException JavaDoc("The bean does not implement the `TimedObject` interface");
328                 }
329                 committed = ! getRollbackOnly();
330             } catch (EJBException JavaDoc e) {
331                 rctx.sysExc = e;
332                 TraceEjb.logger.log(BasicLevel.ERROR, "EJB exception thrown by an enterprise Bean", e);
333             } catch (RuntimeException JavaDoc e) {
334                 rctx.sysExc = e;
335                 TraceEjb.logger.log(BasicLevel.ERROR, "runtime exception thrown by an enterprise Bean", e);
336             } catch (Error JavaDoc e) {
337                 rctx.sysExc = e;
338                 TraceEjb.logger.log(BasicLevel.ERROR, "error thrown by an enterprise Bean", e);
339             } finally {
340                 try {
341                     bf.postInvoke(rctx);
342                 } catch (Exception JavaDoc e) {
343                     TraceEjb.logger.log(BasicLevel.ERROR, "exception on postInvoke: ", e);
344                 }
345             }
346         }
347     }
348 }
349
Popular Tags