1 29 30 package com.caucho.ejb.cfg; 31 32 import com.caucho.bytecode.JClass; 33 import com.caucho.bytecode.JMethod; 34 import com.caucho.config.BuilderProgram; 35 import com.caucho.config.BuilderProgramContainer; 36 import com.caucho.config.ConfigException; 37 import com.caucho.config.LineConfigException; 38 import com.caucho.config.j2ee.InjectIntrospector; 39 import com.caucho.ejb.AbstractServer; 40 import com.caucho.ejb.EjbServerManager; 41 import com.caucho.ejb.gen.BeanAssembler; 42 import com.caucho.ejb.gen.SessionAssembler; 43 import com.caucho.ejb.gen.StatelessAssembler; 44 import com.caucho.ejb.session.SessionServer; 45 import com.caucho.ejb.session.StatelessServer; 46 import com.caucho.java.gen.JavaClassGenerator; 47 import com.caucho.management.j2ee.J2EEManagedObject; 48 import com.caucho.management.j2ee.StatefulSessionBean; 49 import com.caucho.management.j2ee.StatelessSessionBean; 50 import com.caucho.util.L10N; 51 52 import javax.annotation.PostConstruct; 53 import javax.ejb.CreateException ; 54 import javax.ejb.EJBHome ; 55 import javax.ejb.EJBLocalHome ; 56 import javax.ejb.SessionBean ; 57 import javax.ejb.SessionSynchronization ; 58 import java.lang.reflect.Modifier ; 59 import java.util.ArrayList ; 60 61 64 public class EjbSessionBean extends EjbBean { 65 private static final L10N L = new L10N(EjbSessionBean.class); 66 67 private boolean _isStateless; 68 private boolean _isContainerTransaction; 69 70 73 public EjbSessionBean(EjbConfig ejbConfig, String ejbModuleName) 74 { 75 super(ejbConfig, ejbModuleName); 76 } 77 78 81 public String getEJBKind() 82 { 83 return "session"; 84 } 85 86 89 public void setEJBClass(Class ejbClass) 90 throws ConfigException 91 { 92 super.setEJBClass(ejbClass); 93 94 if (Modifier.isAbstract(ejbClass.getModifiers())) 95 throw error(L.l("'{0}' must not be abstract. Session bean implementations must be fully implemented.", ejbClass.getName())); 96 97 if (! SessionBean.class.isAssignableFrom(ejbClass) && ! isAllowPOJO()) 98 throw error(L.l("'{0}' must implement SessionBean. Session beans must implement javax.ejb.SessionBean.", ejbClass.getName())); 99 100 } 101 102 105 public boolean isStateless() 106 { 107 return _isStateless; 108 } 109 110 113 public void setSessionType(String type) 114 throws ConfigException 115 { 116 if (type.equals("Stateful")) 117 _isStateless = false; 118 else if (type.equals("Stateless")) 119 _isStateless = true; 120 else 121 throw new ConfigException(L.l("'{0}' is an unknown session-type. session-type must be 'Stateless' or 'Stateful'.", type)); 122 } 123 124 127 public boolean isContainerTransaction() 128 { 129 return _isContainerTransaction; 130 } 131 132 135 public void setTransactionType(String type) 136 throws ConfigException 137 { 138 if (type.equals("Container")) 139 _isContainerTransaction = true; 140 else if (type.equals("Bean")) 141 _isContainerTransaction = false; 142 else 143 throw new ConfigException(L.l("'{0}' is an unknown transaction-type. transaction-type must be 'Container' or 'Bean'.", type)); 144 } 145 146 149 @PostConstruct 150 public void init() 151 throws ConfigException 152 { 153 super.init(); 154 155 try { 156 if (getRemoteHome() != null) 157 validateHome(getRemoteHome(), getRemote()); 158 if (getLocalHome() != null) 159 validateHome(getLocalHome(), getLocal()); 160 if (getRemote() != null) 161 validateRemote(getRemote()); 162 if (getLocal() != null) 163 validateRemote(getLocal()); 164 165 if (getEJBClass() == null) { 166 throw error(L.l("'{0}' does not have a defined ejb-class. Session beans must have an ejb-class.", 167 getEJBName())); 168 } 169 170 if (! getEJBClassWrapper().isAssignableTo(SessionSynchronization .class)) { 171 } 172 else if (isStateless()) { 173 throw error(L.l("'{0}' must not implement SessionSynchronization. Stateless session beans must not implement SessionSynchronization.", 174 getEJBClass().getName())); 175 } 176 else if (! _isContainerTransaction) { 177 throw error(L.l("'{0}' must not implement SessionSynchronization. Session beans with Bean-managed transactions may not use SessionSynchronization.", 178 getEJBClass().getName())); 179 } 180 } catch (LineConfigException e) { 181 throw e; 182 } catch (ConfigException e) { 183 throw new LineConfigException(getLocation() + e.getMessage(), e); 184 } 185 186 if (isStateless()) 187 J2EEManagedObject.register(new StatelessSessionBean(this)); 188 else 189 J2EEManagedObject.register(new StatefulSessionBean(this)); 190 } 191 192 195 protected BeanAssembler createAssembler(String fullClassName) 196 { 197 if (isStateless()) 198 return new StatelessAssembler(this, fullClassName); 199 else 200 return new SessionAssembler(this, fullClassName); 201 } 202 203 206 protected void addImports(BeanAssembler assembler) 207 { 208 super.addImports(assembler); 209 210 if (isStateless()) { 211 assembler.addImport("com.caucho.ejb.session.StatelessServer"); 212 assembler.addImport("com.caucho.ejb.session.AbstractStatelessContext"); 213 assembler.addImport("com.caucho.ejb.session.StatelessHome"); 214 assembler.addImport("com.caucho.ejb.session.StatelessObject"); 215 } 216 else { 217 assembler.addImport("com.caucho.ejb.session.SessionServer"); 218 assembler.addImport("com.caucho.ejb.session.AbstractSessionContext"); 219 assembler.addImport("com.caucho.ejb.session.SessionHome"); 220 assembler.addImport("com.caucho.ejb.session.SessionObject"); 221 } 222 } 223 224 227 protected EjbHomeView createHomeView(JClass homeClass, String prefix) 228 throws ConfigException 229 { 230 if (isStateless()) 231 return new EjbStatelessHomeView(this, homeClass, prefix); 232 else 233 return new EjbSessionHomeView(this, homeClass, prefix); 234 } 235 236 239 public AbstractServer deployServer(EjbServerManager ejbManager, 240 JavaClassGenerator javaGen) 241 throws ClassNotFoundException , ConfigException 242 { 243 AbstractServer server; 244 245 if (isStateless()) 246 server = new StatelessServer(ejbManager); 247 else 248 server = new SessionServer(ejbManager); 249 250 server.setEJBName(getEJBName()); 251 server.setJndiName(getJndiName()); 252 253 JClass remoteHome = getRemoteHome(); 254 if (remoteHome != null) 255 server.setRemoteHomeClass(remoteHome.getJavaClass()); 256 257 JClass remote = getRemote(); 258 if (remote != null) 259 server.setRemoteObjectClass(remote.getJavaClass()); 260 261 Class contextImplClass = javaGen.loadClass(getSkeletonName()); 262 263 server.setContextImplClass(contextImplClass); 264 265 Class beanClass = javaGen.loadClass(getEJBClass().getName()); 266 267 Thread thread = Thread.currentThread(); 268 ClassLoader oldLoader = thread.getContextClassLoader(); 269 270 try { 271 thread.setContextClassLoader(server.getClassLoader()); 272 273 ArrayList <BuilderProgram> initList; 274 initList = InjectIntrospector.introspect(beanClass); 275 276 BuilderProgramContainer initContainer = getInitProgram(); 277 278 if (initList != null && initList.size() > 0) { 279 if (initContainer == null) 280 initContainer = new BuilderProgramContainer(); 281 282 for (BuilderProgram init : initList) { 283 initContainer.addProgram(init); 284 } 285 } 286 287 server.setInitProgram(initContainer); 288 289 try { 290 if (getServerProgram() != null) 291 getServerProgram().configure(server); 292 } catch (ConfigException e) { 293 throw e; 294 } catch (Throwable e) { 295 throw new ConfigException(e); 296 } 297 } finally { 298 thread.setContextClassLoader(oldLoader); 299 } 300 301 return server; 302 } 303 304 private void validateMethods() 305 throws ConfigException 306 { 307 } 308 309 312 private void validateHome(JClass homeClass, JClass objectClass) 313 throws ConfigException 314 { 315 JClass beanClass = getEJBClassWrapper(); 316 String beanName = beanClass.getName(); 317 318 if (homeClass == null) 319 return; 320 String homeName = homeClass.getName(); 321 String objectName = objectClass.getName(); 322 323 boolean hasFindByPrimaryKey = false; 324 325 if (! homeClass.isPublic()) 326 throw error(L.l("'{0}' must be public", homeName)); 327 328 if (beanClass.isFinal()) 329 throw error(L.l("'{0}' must not be final", beanName)); 330 331 if (beanClass.isAbstract()) 332 throw error(L.l("'{0}' must not be abstract", beanName)); 333 334 if (! homeClass.isInterface()) 335 throw error(L.l("'{0}' must be an interface", homeName)); 336 337 boolean hasCreate = false; 338 339 JMethod []methods = getMethods(homeClass); 340 for (int i = 0; i < methods.length; i++) { 341 JMethod method = methods[i]; 342 String name = method.getName(); 343 JClass []param = method.getParameterTypes(); 344 JClass retType = method.getReturnType(); 345 346 if (method.getDeclaringClass().isAssignableFrom(EJBHome .class) || 347 method.getDeclaringClass().isAssignableFrom(EJBLocalHome .class)) 348 continue; 349 350 if (homeClass.isAssignableTo(EJBHome .class)) 351 validateException(method, java.rmi.RemoteException .class); 352 353 if (name.startsWith("create")) { 354 hasCreate = true; 355 356 if (isStateless() && (! name.equals("create") || 357 method.getParameterTypes().length != 0)) { 358 throw error(L.l("{0}: '{1}' forbidden in stateless session home. The create() method for a stateless session bean must have zero arguments.", 359 method.getFullName(), 360 homeName)); 361 } 362 363 if (! isAllowPOJO()) 364 validateException(method, CreateException .class); 365 366 if (! retType.equals(objectClass)) 367 throw error(L.l("{0}: '{1}' must return {2}. Create methods must return the local or remote interface.", 368 homeName, 369 method.getFullName(), 370 objectClass.getName())); 371 372 String createName = "ejbC" + name.substring(1); 373 JMethod implMethod = 374 validateNonFinalMethod(createName, param, 375 method, homeClass, isAllowPOJO()); 376 377 if (implMethod != null) { 378 if (! implMethod.getReturnType().getName().equals("void")) 379 throw error(L.l("'{0}' must return {1} in {2}", 380 getFullMethodName(createName, param), 381 "void", 382 beanName)); 383 384 validateExceptions(method, implMethod.getExceptionTypes()); 385 } 386 } 387 else if (name.startsWith("ejb") || name.startsWith("remove")) { 388 throw error(L.l("'{0}' forbidden in {1}", 389 method.getFullName(), 390 homeClass.getName())); 391 } 392 } 393 394 if (! hasCreate) 395 throw error(L.l("'{0}' needs at least one create method. Session beans need a create method.", 396 homeClass.getName())); 397 } 398 } 399 | Popular Tags |