1 22 package org.jboss.ejb3.stateless; 23 24 25 import org.jboss.annotation.ejb.LocalBinding; 26 import org.jboss.annotation.ejb.RemoteBinding; 27 import org.jboss.annotation.ejb.RemoteBindings; 28 import org.jboss.aop.AspectManager; 29 import org.jboss.aop.MethodInfo; 30 import org.jboss.aop.advice.Interceptor; 31 import org.jboss.aop.joinpoint.Invocation; 32 import org.jboss.aop.joinpoint.InvocationResponse; 33 import org.jboss.aop.joinpoint.MethodInvocation; 34 import org.jboss.aop.util.MethodHashing; 35 import org.jboss.aspects.asynch.FutureHolder; 36 import org.jboss.ejb.AllowedOperationsAssociation; 37 import org.jboss.ejb.AllowedOperationsFlags; 38 import org.jboss.ejb3.EJBContainerInvocation; 39 import org.jboss.ejb3.Ejb3Deployment; 40 import org.jboss.ejb3.ProxyFactoryHelper; 41 import org.jboss.ejb3.ProxyUtils; 42 import org.jboss.ejb3.SessionContainer; 43 import org.jboss.ejb3.BeanContext; 44 import org.jboss.ejb3.interceptor.InterceptorInfoRepository; 45 import org.jboss.ejb3.timerservice.TimedObjectInvoker; 46 import org.jboss.ejb3.timerservice.TimerServiceFactory; 47 import org.jboss.logging.Logger; 48 import org.jboss.proxy.ejb.handle.HomeHandleImpl; 49 import org.jboss.proxy.ejb.handle.StatelessHandleImpl; 50 import org.jboss.injection.EncInjector; 51 52 import javax.ejb.EJBException ; 53 import javax.ejb.Handle ; 54 import javax.ejb.Timer ; 55 import javax.ejb.TimerService ; 56 import javax.naming.NamingException ; 57 import java.lang.reflect.Method ; 58 import java.util.Hashtable ; 59 import java.util.Map ; 60 import java.util.HashMap ; 61 62 63 69 public class StatelessContainer extends SessionContainer implements TimedObjectInvoker 70 { 71 private static final Logger log = Logger.getLogger(StatelessContainer.class); 72 73 protected TimerService timerService; 74 75 public StatelessContainer(ClassLoader cl, String beanClassName, String ejbName, AspectManager manager, 76 Hashtable ctxProperties, InterceptorInfoRepository interceptorRepository, 77 Ejb3Deployment deployment) 78 { 79 super(cl, beanClassName, ejbName, manager, ctxProperties, interceptorRepository, deployment); 80 beanContextClass = StatelessBeanContext.class; 81 } 82 83 public Object createSession(Class initTypes[], Object initArgs[]) 84 { 85 if((initTypes != null && initTypes.length > 0) || (initArgs != null && initArgs.length > 0)) 86 throw new IllegalArgumentException ("stateless bean create method must take no arguments (EJB3 4.5)"); 87 return null; 90 } 91 92 public void start() throws Exception 93 { 94 try 95 { 96 super.start(); 97 timerService = TimerServiceFactory.getInstance().createTimerService(this.getObjectName(), this); 99 100 TimerServiceFactory.getInstance().restoreTimerService(timerService); 101 } 102 catch (Exception e) 103 { 104 try 105 { 106 stop(); 107 } 108 catch (Exception ignore) 109 { 110 log.debug("Failed to cleanup after start() failure", ignore); 111 } 112 throw e; 113 } 114 } 115 116 public void stop() throws Exception 117 { 118 if (timerService != null) TimerServiceFactory.getInstance().removeTimerService(timerService); 120 super.stop(); 121 } 122 123 public TimerService getTimerService() 124 { 125 return timerService; 126 } 127 128 public TimerService getTimerService(Object pKey) 129 { 130 assert timerService != null : "Timer Service not yet initialized"; 131 return timerService; 132 } 133 134 public void callTimeout(Timer timer) throws Exception 135 { 136 Method timeout = callbackHandler.getTimeoutCallback(); 137 if (timeout == null) throw new EJBException ("No method has been annotated with @Timeout"); 138 Object [] args = {timer}; 139 ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); 140 try 141 { 142 AllowedOperationsAssociation.pushInMethodFlag(AllowedOperationsFlags.IN_EJB_TIMEOUT); 143 try 144 { 145 MethodInfo info = (MethodInfo) methodInterceptors.get(callbackHandler.getTimeoutCalllbackHash()); 146 Interceptor[] aspects = info.getInterceptors(); 147 EJBContainerInvocation nextInvocation = new EJBContainerInvocation(info, aspects); 148 nextInvocation.setAdvisor(this); 149 nextInvocation.setArguments(args); 150 nextInvocation.invokeNext(); 151 } 152 catch (Throwable throwable) 153 { 154 if (throwable instanceof Exception ) throw (Exception ) throwable; 155 throw new RuntimeException (throwable); 156 } 157 finally 158 { 159 AllowedOperationsAssociation.popInMethodFlag(); 160 } 161 } 162 finally 163 { 164 Thread.currentThread().setContextClassLoader(oldLoader); 165 } 166 } 167 168 171 public Object localInvoke(Method method, Object [] args) throws Throwable 172 { 173 return localInvoke(method, args, null); 174 } 175 176 181 public Object localInvoke(Method method, Object [] args, FutureHolder provider) throws Throwable 182 { 183 long start = System.currentTimeMillis(); 184 185 ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); 186 try 187 { 188 long hash = MethodHashing.calculateHash(method); 189 MethodInfo info = (MethodInfo) methodInterceptors.get(hash); 190 if (info == null) 191 { 192 throw new RuntimeException ("Could not resolve beanClass method from proxy call: " + method.toString()); 193 } 194 195 Method unadvisedMethod = info.getUnadvisedMethod(); 196 197 try 198 { 199 invokeStats.callIn(); 200 201 invokedMethod.push(new InvokedMethod(true, unadvisedMethod)); 202 203 if (unadvisedMethod != null && isHomeMethod(unadvisedMethod)) 204 { 205 return invokeLocalHomeMethod(info, args); 206 } 207 208 Interceptor[] aspects = info.getInterceptors(); 209 EJBContainerInvocation nextInvocation = new EJBContainerInvocation(info, aspects); 210 nextInvocation.setAdvisor(this); 211 nextInvocation.setArguments(args); 212 213 ProxyUtils.addLocalAsynchronousInfo(nextInvocation, provider); 214 return nextInvocation.invokeNext(); 215 } 216 finally 217 { 218 if (unadvisedMethod != null) 219 { 220 long end = System.currentTimeMillis(); 221 long elapsed = end - start; 222 invokeStats.updateStats(unadvisedMethod, elapsed); 223 } 224 225 invokeStats.callOut(); 226 227 invokedMethod.pop(); 228 } 229 } 230 finally 231 { 232 Thread.currentThread().setContextClassLoader(oldLoader); 233 } 234 } 235 236 public InvocationResponse dynamicInvoke(Object target, Invocation invocation) throws Throwable 237 { 238 long start = System.currentTimeMillis(); 239 240 ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); 241 try 242 { 243 Thread.currentThread().setContextClassLoader(classloader); 244 MethodInvocation si = (MethodInvocation) invocation; 245 MethodInfo info = (MethodInfo) methodInterceptors.get(si.getMethodHash()); 246 if (info == null) 247 { 248 throw new RuntimeException ("Could not resolve beanClass method from proxy call"); 249 } 250 251 Method unadvisedMethod = info.getUnadvisedMethod(); 252 try 253 { 254 invokeStats.callIn(); 255 256 invokedMethod.push(new InvokedMethod(false, unadvisedMethod)); 257 Map responseContext = null; 258 Object rtn = null; 259 if (unadvisedMethod != null && isHomeMethod(unadvisedMethod)) 260 { 261 rtn = invokeHomeMethod(info, si); 262 } 263 else if (info != null && unadvisedMethod != null && isEJBObjectMethod(unadvisedMethod)) 264 { 265 rtn = invokeEJBObjectMethod(info, si); 266 } 267 else 268 { 269 270 EJBContainerInvocation newSi = null; 271 Interceptor[] aspects = info.getInterceptors(); 272 273 newSi = new EJBContainerInvocation(info, aspects); 274 newSi.setArguments(si.getArguments()); 275 newSi.setMetaData(si.getMetaData()); 276 newSi.setAdvisor(this); 277 try 278 { 279 rtn = newSi.invokeNext(); 280 responseContext = newSi.getResponseContextInfo(); 281 } 282 catch (Throwable throwable) 283 { 284 responseContext = newSi.getResponseContextInfo(); 285 return marshallException(invocation, throwable, responseContext); 286 } 287 } 288 289 InvocationResponse response = marshallResponse(invocation, rtn, responseContext); 290 return response; 291 } 292 finally 293 { 294 if (unadvisedMethod != null) 295 { 296 long end = System.currentTimeMillis(); 297 long elapsed = end - start; 298 invokeStats.updateStats(unadvisedMethod, elapsed); 299 } 300 301 invokeStats.callOut(); 302 303 invokedMethod.pop(); 304 } 305 } 306 finally 307 { 308 Thread.currentThread().setContextClassLoader(oldLoader); 309 } 310 311 } 312 313 314 protected Object invokeEJBObjectMethod(MethodInfo info, MethodInvocation invocation) throws Throwable 315 { 316 Method unadvisedMethod = info.getUnadvisedMethod(); 317 if (unadvisedMethod.getName().equals("getHandle")) 318 { 319 StatelessHandleImpl handle = null; 320 RemoteBinding remoteBindingAnnotation = (RemoteBinding) resolveAnnotation(RemoteBinding.class); 321 if (remoteBindingAnnotation != null) 322 handle = new StatelessHandleImpl(remoteBindingAnnotation.jndiBinding()); 323 324 return handle; 325 } 326 else if (unadvisedMethod.getName().equals("remove")) 327 { 328 return null; 329 } 330 else if (unadvisedMethod.getName().equals("getEJBHome")) 331 { 332 HomeHandleImpl homeHandle = null; 333 334 RemoteBinding remoteBindingAnnotation = (RemoteBinding) resolveAnnotation(RemoteBinding.class); 335 if (remoteBindingAnnotation != null) 336 homeHandle = new HomeHandleImpl(remoteBindingAnnotation.jndiBinding() + "Home"); 337 338 return homeHandle.getEJBHome(); 339 } 340 else if (unadvisedMethod.getName().equals("getPrimaryKey")) 341 { 342 return null; 343 } 344 else if (unadvisedMethod.getName().equals("isIdentical")) 345 { 346 return false; 347 } 348 else 349 { 350 return null; 351 } 352 } 353 354 private Object invokeLocalHomeMethod(MethodInfo info, Object [] args) throws Exception 355 { 356 Method unadvisedMethod = info.getUnadvisedMethod(); 357 if (unadvisedMethod.getName().equals("create")) 358 { 359 LocalBinding binding = (LocalBinding) resolveAnnotation(LocalBinding.class); 360 361 StatelessLocalProxyFactory factory = new StatelessLocalProxyFactory(); 362 factory.setContainer(this); 363 factory.init(); 364 365 Object proxy = factory.createProxy(); 366 367 return proxy; 368 } 369 else { 371 return null; 372 } 373 } 374 375 protected Object invokeHomeMethod(MethodInfo info, MethodInvocation invocation) throws Throwable 376 { 377 Method unadvisedMethod = info.getUnadvisedMethod(); 378 if (unadvisedMethod.getName().equals("create")) 379 { 380 RemoteBinding binding = null; 381 382 RemoteBindings bindings = (RemoteBindings) resolveAnnotation(RemoteBindings.class); 383 if (bindings != null) 384 binding = bindings.value()[0]; 385 else 386 binding = (RemoteBinding) resolveAnnotation(RemoteBinding.class); 387 388 StatelessRemoteProxyFactory factory = new StatelessRemoteProxyFactory(); 389 factory.setContainer(this); 390 factory.setRemoteBinding(binding); 391 factory.init(); 392 393 return factory.createProxy(); 394 } 395 else { 397 return null; 398 } 399 } 400 401 @Override 402 public Object getBusinessObject(BeanContext ctx, Class intf) 403 { 404 try 405 { 406 String jndiName = ProxyFactoryHelper.getJndiName(this, intf); 407 if (jndiName == null) throw new IllegalStateException ("Cannot find BusinessObject for interface: " + intf.getName()); 408 return getInitialContext().lookup(ProxyFactoryHelper.getJndiName(this, intf)); 409 } 410 catch (NamingException e) 411 { 412 throw new RuntimeException ("failed to invoke getBusinessObject", e); 413 } 414 } 415 416 protected void removeHandle(Handle handle) 417 { 418 throw new RuntimeException ("NYI"); 419 } 420 } 421 | Popular Tags |