1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */
22 package org.jboss.ejb.plugins;
23
24 import java.lang.reflect.Method;
25 import java.rmi.RemoteException;
26
27 import javax.ejb.EJBException;
28 import javax.ejb.TimedObject;
29 import javax.ejb.Timer;
30
31 import org.jboss.ejb.AllowedOperationsAssociation;
32 import org.jboss.ejb.Container;
33 import org.jboss.ejb.EnterpriseContext;
34 import org.jboss.ejb.InstancePool;
35 import org.jboss.ejb.StatelessSessionContainer;
36 import org.jboss.ejb.StatelessSessionEnterpriseContext;
37 import org.jboss.invocation.Invocation;
38 import org.jboss.invocation.InvocationKey;
39 import org.jboss.invocation.InvocationType;
40
41 /**
42 * This container acquires the given instance. This must be used after
43 * the EnvironmentInterceptor, since acquiring instances requires a proper
44 * JNDI environment to be set
45 *
46 * @author Rickard Oberg
47 * @author Scott.Stark@jboss.org
48 * @version $Revision: 69133 $
49 */
50 public class StatelessSessionInstanceInterceptor
51 extends AbstractInterceptor
52 {
53 // Constants -----------------------------------------------------
54
55 // Attributes ----------------------------------------------------
56
57 protected StatelessSessionContainer container;
58
59 // Static --------------------------------------------------------
60
61 /** A reference to {@link javax.ejb.TimedObject#ejbTimeout}. */
62 protected static final Method ejbTimeout;
63 static
64 {
65 try
66 {
67 ejbTimeout = TimedObject.class.getMethod("ejbTimeout", new Class[]{Timer.class});
68 }
69 catch (Exception e)
70 {
71 throw new ExceptionInInitializerError(e);
72 }
73 }
74
75 // Constructors --------------------------------------------------
76
77 // Public --------------------------------------------------------
78
79 public void setContainer(final Container container)
80 {
81 super.setContainer(container);
82 this.container = (StatelessSessionContainer)container;
83 }
84
85 // Interceptor implementation --------------------------------------
86
87 public Object invokeHome(final Invocation mi) throws Exception
88 {
89 InstancePool pool = container.getInstancePool();
90 StatelessSessionEnterpriseContext ctx = null;
91 try
92 {
93 // Acquire an instance in case the ejbCreate throws a CreateException
94 ctx = (StatelessSessionEnterpriseContext) pool.get();
95 mi.setEnterpriseContext(ctx);
96 // Dispatch the method to the container
97 return getNext().invokeHome(mi);
98 }
99 finally
100 {
101 mi.setEnterpriseContext(null);
102 // If an instance was created, return it to the pool
103 if( ctx != null )
104 pool.free(ctx);
105 }
106
107 }
108
109 public Object invoke(final Invocation mi) throws Exception
110 {
111 // Get context
112 InstancePool pool = container.getInstancePool();
113 StatelessSessionEnterpriseContext ctx = null;
114 try
115 {
116 ctx = (StatelessSessionEnterpriseContext) pool.get();
117 }
118 catch (EJBException e)
119 {
120 throw e;
121 }
122 catch (RemoteException e)
123 {
124 throw e;
125 }
126 catch (Exception e)
127 {
128 InvocationType type = mi.getType();
129 boolean isLocal = (type == InvocationType.LOCAL || type == InvocationType.LOCALHOME);
130 if (isLocal)
131 throw new EJBException("Unable to get an instance from the pool", e);
132 else
133 throw new RemoteException("Unable to get an intance from the pool", e);
134 }
135
136
137 // Set the current security information
138 ctx.setPrincipal(mi.getPrincipal());
139 // Set the JACC EnterpriseBean PolicyContextHandler data
140 EnterpriseBeanPolicyContextHandler.setEnterpriseBean(ctx.getInstance());
141
142 // Use this context
143 mi.setEnterpriseContext(ctx);
144
145 // JAXRPC/JAXWS message context
146 Object msgContext = mi.getValue(InvocationKey.SOAP_MESSAGE_CONTEXT);
147
148 // Timer invocation
149 if (ejbTimeout.equals(mi.getMethod()))
150 {
151 AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_TIMEOUT);
152 }
153
154 // Service Endpoint invocation
155 else if (msgContext != null)
156 {
157 if (msgContext instanceof javax.xml.rpc.handler.MessageContext)
158 ctx.setMessageContext((javax.xml.rpc.handler.MessageContext)msgContext);
159
160 AllowedOperationsAssociation.pushInMethodFlag(IN_SERVICE_ENDPOINT_METHOD);
161 }
162
163 // Business Method Invocation
164 else
165 {
166 AllowedOperationsAssociation.pushInMethodFlag(IN_BUSINESS_METHOD);
167 }
168
169 // There is no need for synchronization since the instance is always fresh also there should
170 // never be a tx associated with the instance.
171 try
172 {
173 Object obj = getNext().invoke(mi);
174 return obj;
175
176 }
177 catch (RuntimeException e) // Instance will be GC'ed at MI return
178 {
179 mi.setEnterpriseContext(null);
180 throw e;
181 }
182 catch (RemoteException e) // Instance will be GC'ed at MI return
183 {
184 mi.setEnterpriseContext(null);
185 throw e;
186 }
187 catch (Error e) // Instance will be GC'ed at MI return
188 {
189 mi.setEnterpriseContext(null);
190 throw e;
191 }
192 finally
193 {
194 AllowedOperationsAssociation.popInMethodFlag();
195 EnterpriseBeanPolicyContextHandler.setEnterpriseBean(null);
196
197 // Return context
198 if (mi.getEnterpriseContext() != null)
199 {
200 pool.free(((EnterpriseContext) mi.getEnterpriseContext()));
201 }
202 else
203 {
204 pool.discard(ctx);
205 }
206 }
207 }
208 }