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;
23
24 import java.lang.reflect.Method;
25 import java.rmi.RemoteException;
26 import java.util.HashMap;
27 import java.util.Map;
28
29 import javax.ejb.CreateException;
30 import javax.ejb.EJBException;
31 import javax.ejb.EJBLocalObject;
32 import javax.ejb.EJBObject;
33 import javax.ejb.Handle;
34 import javax.ejb.RemoveException;
35
36 import org.jboss.invocation.Invocation;
37 import org.jboss.util.UnreachableStatementException;
38
39 /**
40 * The container for <em>stateless</em> session beans.
41 *
42 * @author <a href="mailto:rickard.oberg@telkel.com">Rickard Oberg</a>
43 * @author <a href="mailto:marc.fleury@telkel.com">Marc Fleury</a>
44 * @author <a href="mailto:docodan@mvcsoft.com">Daniel OConnor</a>
45 * @author <a href="mailto:Christoph.Jung@infor.de">Christoph G. Jung</a>
46 * @version $Revision: 66439 $
47 */
48 public class StatelessSessionContainer extends SessionContainer
49 implements EJBProxyFactoryContainer, InstancePoolContainer
50 {
51 // EJBObject implementation --------------------------------------
52
53 /**
54 * No-op.
55 */
56 public void remove(Invocation mi)
57 throws RemoteException, RemoveException
58 {
59 log.debug("Useless invocation of remove() for stateless session bean");
60 }
61
62 // EJBLocalHome implementation
63
64 public EJBLocalObject createLocalHome()
65 throws CreateException
66 {
67 if (localProxyFactory == null)
68 {
69 String msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
70 throw new IllegalStateException(msg);
71 }
72 createCount++;
73 return localProxyFactory.getStatelessSessionEJBLocalObject();
74 }
75
76 /**
77 * No-op.
78 */
79 public void removeLocalHome(Object primaryKey)
80 {
81 log.debug("Useless invocation of remove(Object) for stateless session bean");
82 }
83
84 // EJBHome implementation ----------------------------------------
85
86 public EJBObject createHome()
87 throws RemoteException, CreateException
88 {
89 EJBProxyFactory ci = getProxyFactory();
90 if (ci == null)
91 {
92 String msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
93 throw new IllegalStateException(msg);
94 }
95 createCount++;
96 Object obj = ci.getStatelessSessionEJBObject();
97 return (EJBObject) obj;
98 }
99
100 /**
101 * No-op.
102 */
103 public void removeHome(Handle handle)
104 throws RemoteException, RemoveException
105 {
106 throw new UnreachableStatementException();
107 }
108
109 /**
110 * No-op.
111 */
112 public void removeHome(Object primaryKey)
113 throws RemoteException, RemoveException
114 {
115 throw new UnreachableStatementException();
116 }
117
118 // Protected ----------------------------------------------------
119
120 protected void setupHomeMapping()
121 throws NoSuchMethodException
122 {
123 Map map = new HashMap();
124
125 if (homeInterface != null)
126 {
127 Method[] m = homeInterface.getMethods();
128 for (int i = 0; i < m.length; i++)
129 {
130 // Implemented by container
131 log.debug("Mapping " + m[i].getName());
132 map.put(m[i], getClass().getMethod(m[i].getName() + "Home", m[i].getParameterTypes()));
133 }
134 }
135 if (localHomeInterface != null)
136 {
137 Method[] m = localHomeInterface.getMethods();
138 for (int i = 0; i < m.length; i++)
139 {
140 // Implemented by container
141 log.debug("Mapping " + m[i].getName());
142 map.put(m[i], getClass().getMethod(m[i].getName() + "LocalHome", m[i].getParameterTypes()));
143 }
144 }
145
146 homeMapping = map;
147 }
148
149 Interceptor createContainerInterceptor()
150 {
151 return new ContainerInterceptor();
152 }
153
154 /**
155 * This is the last step before invocation - all interceptors are done
156 */
157 class ContainerInterceptor
158 extends AbstractContainerInterceptor
159 {
160 public Object invokeHome(Invocation mi) throws Exception
161 {
162 Method miMethod = mi.getMethod();
163 Method m = (Method) getHomeMapping().get(miMethod);
164 if (m == null)
165 {
166 String msg = "Invalid invocation, check your deployment packaging, method=" + miMethod;
167 throw new EJBException(msg);
168 }
169
170 try
171 {
172 return mi.performCall(StatelessSessionContainer.this, m, mi.getArguments());
173 }
174 catch (Exception e)
175 {
176 rethrow(e);
177 }
178
179 // We will never get this far, but the compiler does not know that
180 throw new org.jboss.util.UnreachableStatementException();
181 }
182
183 public Object invoke(Invocation mi) throws Exception
184 {
185 // wire the transaction on the context, this is how the instance remember the tx
186 EnterpriseContext ctx = (EnterpriseContext) mi.getEnterpriseContext();
187 if (ctx.getTransaction() == null)
188 ctx.setTransaction(mi.getTransaction());
189
190 // Get method and instance to invoke upon
191 Method miMethod = mi.getMethod();
192
193 Map map = getBeanMapping();
194 Method m = (Method) map.get(miMethod);
195
196 // The Invocation might contain the actual bean method
197 // e.g. For an invocation based on a JSR-181 @WebMethod annotation
198 if (m == null && map.values().contains(miMethod))
199 {
200 m = miMethod;
201 }
202
203 if (m == null)
204 {
205 String msg = "Invalid invocation, check your deployment packaging, method=" + miMethod;
206 throw new EJBException(msg);
207 }
208
209 //If we have a method that needs to be done by the container (EJBObject methods)
210 if (m.getDeclaringClass().equals(StatelessSessionContainer.class) ||
211 m.getDeclaringClass().equals(SessionContainer.class))
212 {
213 try
214 {
215 return mi.performCall(StatelessSessionContainer.this, m, new Object[]{mi});
216 }
217 catch (Exception e)
218 {
219 rethrow(e);
220 }
221 }
222 else // we have a method that needs to be done by a bean instance
223 {
224 // Invoke and handle exceptions
225 try
226 {
227 Object bean = ctx.getInstance();
228 return mi.performCall(bean, m, mi.getArguments());
229 }
230 catch (Exception e)
231 {
232 rethrow(e);
233 }
234 }
235
236 // We will never get this far, but the compiler does not know that
237 throw new org.jboss.util.UnreachableStatementException();
238 }
239 }
240 }