AbstractEjbHandlerpublic abstract class AbstractEjbHandler extends AbstractHandler This is an abstract class for EJB annotation handler.
Concrete subclass handlers need to implements the following methods:
public Class<? extends Annotation> getAnnotationType();
protected String getAnnotatedName(Annotation annotation );
protected boolean isValidEjbDescriptor(EjbDescriptor ejbDesc);
Annotation annotation);
protected EjbDescriptor createEjbDescriptor(String elementName,
AnnotationInfo ainfo) throws AnnotationProcessorException;
protected HandlerProcessingResult setEjbDescriptorInfo(
EjbDescriptor ejbDesc, AnnotationInfo ainfo)
throws AnnotationProcessorException; |
Methods Summary |
---|
protected abstract com.sun.enterprise.deployment.EjbDescriptor | createEjbDescriptor(java.lang.String elementName, com.sun.enterprise.deployment.annotation.AnnotationInfo ainfo)Create a new EjbDescriptor for a given elementName and AnnotationInfo.
| protected void | doDescriptionProcessing(java.lang.String description, com.sun.enterprise.deployment.EjbDescriptor ejbDescriptor)
// Since there are multiple descriptions allowed in the deployment
// descriptor, there are no overriding issues here. If the
// component-defining annotation contains a description, it will
// always be added to the list of descriptions for the bean.
if( (description != null) && !description.equals("") ) {
ejbDescriptor.setDescription(description);
}
| protected void | doMappedNameProcessing(java.lang.String mappedName, com.sun.enterprise.deployment.EjbDescriptor ejbDesc)
// Set mappedName() if a value has been given in the annotation and
// it hasn't already been set on the descriptor via the .xml.
if( ejbDesc.getMappedName().equals("") ) {
if( !mappedName.equals("") ) {
ejbDesc.setMappedName(mappedName);
}
}
| private void | doTimedObjectProcessing(java.lang.Class ejbClass, com.sun.enterprise.deployment.EjbDescriptor ejbDesc)Process TimedObject and @Timeout annotation. It's better to do it
when processing the initial bean type since Timeout method is a
business method that should be included in any tx processing defaulting
that takes place.
// Timeout methods can be declared on the bean class or any
// super-class and can be public, protected, private, or
// package access. There can be at most one timeout method for
// the entire bean class hierarchy, so we start from the bean
// class and go up, stopping when we find the first one.
MethodDescriptor timeoutMethodDesc = null;
Class nextClass = ejbClass;
while((nextClass != Object.class) && (nextClass != null)
&& (timeoutMethodDesc == null) ) {
Method[] methods = nextClass.getDeclaredMethods();
for(Method m : methods) {
if( (m.getAnnotation(Timeout.class) != null) ) {
timeoutMethodDesc =
new MethodDescriptor(m, MethodDescriptor.EJB_BEAN);
break;
}
}
nextClass = nextClass.getSuperclass();
}
if( (timeoutMethodDesc == null) &&
javax.ejb.TimedObject.class.isAssignableFrom(ejbClass) ) {
// If the class implements the TimedObject interface, it must
// be ejbTimeout.
timeoutMethodDesc = new MethodDescriptor
("ejbTimeout", "@Timeout method",
new String[] { "javax.ejb.Timer" },
MethodDescriptor.EJB_BEAN);
}
if( timeoutMethodDesc != null ) {
ejbDesc.setEjbTimeoutMethod(timeoutMethodDesc);
}
return;
| protected boolean | excludedFromImplementsClause(java.lang.Class intf)
return ( (intf == java.io.Serializable.class) ||
(intf == java.io.Externalizable.class) ||
( (intf.getPackage() != null) &&
intf.getPackage().getName().equals("javax.ejb")) );
| protected abstract java.lang.String | getAnnotatedName(java.lang.annotation.Annotation annotation)Return the name attribute of given annotation.
| private java.lang.Class | getComponentIntfFromHome(java.lang.Class homeIntf)
Class componentIntf = null;
Method[] methods = homeIntf.getMethods();
for (Method m : methods) {
if (m.getName().startsWith("create")) {
componentIntf = m.getReturnType();
break;
}
}
return componentIntf;
| protected abstract boolean | isValidEjbDescriptor(com.sun.enterprise.deployment.EjbDescriptor ejbDesc, java.lang.annotation.Annotation annotation)
| public com.sun.enterprise.deployment.annotation.HandlerProcessingResult | processAnnotation(com.sun.enterprise.deployment.annotation.AnnotationInfo ainfo)Process a particular annotation which type is the same as the
one returned by @see getAnnotationType(). All information
pertinent to the annotation and its context is encapsulated
in the passed AnnotationInfo instance.
This is a method in interface AnnotationHandler.
Class ejbClass = (Class) ainfo.getAnnotatedElement();
Annotation annotation = ainfo.getAnnotation();
if (logger.isLoggable(Level.FINER)) {
logger.finer("@ process ejb annotation " +
annotation + " in " + ejbClass);
}
AnnotatedElementHandler aeHandler =
ainfo.getProcessingContext().getHandler();
if (aeHandler != null && aeHandler instanceof EjbContext) {
EjbContext context = (EjbContext)aeHandler;
EjbDescriptor desc = context.getDescriptor();
if (isValidEjbDescriptor(desc, annotation)) {
return getDefaultProcessedResult();
} else {
log(Level.SEVERE, ainfo,
localStrings.getLocalString(
"enterprise.deployment.annotation.handlers.notcompsuperclass",
"The annotation symbol defined in super-class is not compatible with {0} ejb {1}.",
new Object[] { desc.getType(), desc.getName() }));
return getDefaultFailedResult();
}
} else if (aeHandler == null || !(aeHandler instanceof EjbBundleContext)) {
return getInvalidAnnotatedElementHandlerResult(
ainfo.getProcessingContext().getHandler(), ainfo);
}
EjbBundleContext ctx = (EjbBundleContext)aeHandler;
if (logger.isLoggable(Level.FINE)) {
logger.fine("My context is " + ctx);
}
String elementName = getAnnotatedName(annotation);
if (elementName.length() == 0) {
elementName = ejbClass.getSimpleName();
}
EjbBundleDescriptor currentBundle = ctx.getDescriptor();
EjbDescriptor ejbDesc = null;
try {
ejbDesc = currentBundle.getEjbByName(elementName);
} catch(IllegalArgumentException ex) {
//getEjbByName throws IllegalArgumentException when no ejb is found
}
if (ejbDesc != null && !(ejbDesc instanceof DummyEjbDescriptor) ) {
// element has already been defined in the standard DDs,
// overriding rules applies
if (logger.isLoggable(Level.FINE)) {
logger.fine("Overriding rules apply for " + ejbClass.getName());
}
// don't allow ejb-jar.xml overwrite ejb type
if (!isValidEjbDescriptor(ejbDesc, annotation)) {
// this is an error
log(Level.SEVERE, ainfo,
localStrings.getLocalString(
"enterprise.deployment.annotation.handlers.wrongejbtype",
"Wrong annotation symbol for ejb {1}",
new Object[] { ejbDesc }));
return getDefaultFailedResult();
}
// <ejb-class> is optional if a component-defining
// annotation is used. If present, <ejb-class> element
// must match the class on which the component defining annotation
// appears.
String descriptorEjbClass = ejbDesc.getEjbClassName();
if( descriptorEjbClass == null ) {
ejbDesc.setEjbClassName(ejbClass.getName());
ejbDesc.applyDefaultClassToLifecycleMethods();
} else if( !descriptorEjbClass.equals(ejbClass.getName()) ) {
log(Level.SEVERE, ainfo,
localStrings.getLocalString(
"enterprise.deployment.annotation.handlers.ejbclsmismatch",
"",
new Object[] { descriptorEjbClass, elementName,
ejbClass.getName() }));
return getDefaultFailedResult();
}
} else {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Creating a new descriptor for "
+ ejbClass.getName());
}
EjbDescriptor dummyEjbDesc = ejbDesc;
ejbDesc = createEjbDescriptor(elementName, ainfo);
// create the actual ejb descriptor using annotation info and
// the information from dummy ejb descriptor if applicable
if (dummyEjbDesc != null &&
dummyEjbDesc instanceof DummyEjbDescriptor ) {
currentBundle.removeEjb(dummyEjbDesc);
ejbDesc.addEjbDescriptor(dummyEjbDesc);
// reset ejbClassName on ejbDesc
ejbDesc.setEjbClassName(ejbClass.getName());
}
// add the actual ejb descriptor to the ejb bundle
currentBundle.addEjb(ejbDesc);
if (logger.isLoggable(Level.FINE)) {
logger.fine("New " +
getAnnotationType().getName() + " bean " + elementName);
}
}
HandlerProcessingResult procResult = setEjbDescriptorInfo(ejbDesc, ainfo);
doTimedObjectProcessing(ejbClass, ejbDesc);
EjbContext ejbContext = new EjbContext(ejbDesc, ejbClass);
// we push the new context on the stack...
ctx.getProcessingContext().pushHandler(ejbContext);
return procResult;
| protected com.sun.enterprise.deployment.annotation.HandlerProcessingResult | setBusinessAndHomeInterfaces(com.sun.enterprise.deployment.EjbDescriptor ejbDesc, com.sun.enterprise.deployment.annotation.AnnotationInfo ainfo)MessageDriven bean does not need to invoke this API.
Set<String> localIntfNames = new HashSet<String>();
Set<String> remoteIntfNames = new HashSet<String>();
Class ejbClass = (Class)ainfo.getAnnotatedElement();
// First check for annotations specifying remote/local business intfs.
// We analyze them here because they are needed during the
// implements clause processing for beans that specify
// @Stateless/@Stateful. In addition, they should *not* be processed
// if there is no @Stateful/@Stateless annotation.
Remote remoteBusAnn = (Remote) ejbClass.getAnnotation(Remote.class);
boolean emptyRemoteBusAnn = false;
if( remoteBusAnn != null ) {
for(Class next : remoteBusAnn.value()) {
remoteIntfNames.add(next.getName());
}
emptyRemoteBusAnn = remoteIntfNames.isEmpty();
}
Local localBusAnn = (Local) ejbClass.getAnnotation(Local.class);
if( localBusAnn != null ) {
for(Class next : localBusAnn.value()) {
localIntfNames.add(next.getName());
}
}
List<Class> eligibleInterfaces = new LinkedList<Class>();
for(Class next : ejbClass.getInterfaces()) {
if( !excludedFromImplementsClause(next) ) {
eligibleInterfaces.add(next);
}
}
// total number of local/remote business interfaces declared
// outside of the implements clause
int nonImplementsClauseBusinessInterfaceCount =
remoteIntfNames.size() + localIntfNames.size() +
ejbDesc.getRemoteBusinessClassNames().size() +
ejbDesc.getLocalBusinessClassNames().size();
for(Class next : eligibleInterfaces) {
String nextIntfName = next.getName();
if( remoteIntfNames.contains(nextIntfName)
||
localIntfNames.contains(nextIntfName)
||
ejbDesc.getRemoteBusinessClassNames().contains(nextIntfName)
||
ejbDesc.getLocalBusinessClassNames().contains(nextIntfName)){
// Interface has already been identified as a Remote/Local
// business interface, so ignore.
} else if( next.getAnnotation(Local.class) != null ) {
localIntfNames.add(nextIntfName);
} else if( next.getAnnotation(Remote.class) != null ) {
remoteIntfNames.add(nextIntfName);
} else {
if( nonImplementsClauseBusinessInterfaceCount == 0 ) {
// If there's an empty @Remote annotation on the class,
// it's treated as a remote business interface. Otherwise,
// it's treated as a local business interface.
if( emptyRemoteBusAnn ) {
remoteIntfNames.add(nextIntfName);
} else {
localIntfNames.add(nextIntfName);
}
} else {
// Since the component has at least one other business
// interface, each implements clause interface that cannot
// be identified as business interface via the deployment
// descriptor or a @Remote/@Local annotation is ignored.
}
}
}
if (localIntfNames.size() > 0) {
for(String next : localIntfNames) {
ejbDesc.addLocalBusinessClassName(next);
}
}
if (remoteIntfNames.size() > 0) {
for(String next : remoteIntfNames) {
ejbDesc.addRemoteBusinessClassName(next);
}
}
// Do Adapted @Home / Adapted @LocalHome processing here too since
// they are logically part of the structural @Stateless/@Stateful info.
RemoteHome remoteHomeAnn = (RemoteHome)
ejbClass.getAnnotation(RemoteHome.class);
if( remoteHomeAnn != null ) {
Class remoteHome = remoteHomeAnn.value();
Class remoteIntf = getComponentIntfFromHome(remoteHome);
if( EJBHome.class.isAssignableFrom(remoteHome) &&
(remoteIntf != null) ) {
ejbDesc.setHomeClassName(remoteHome.getName());
ejbDesc.setRemoteClassName(remoteIntf.getName());
} else {
log(Level.SEVERE, ainfo,
localStrings.getLocalString(
"enterprise.deployment.annotation.handlers.invalidremotehome",
"Encountered invalid @RemoteHome interface {0}.",
new Object[] { remoteHome }));
return getDefaultFailedResult();
}
}
LocalHome localHomeAnn = (LocalHome)
ejbClass.getAnnotation(LocalHome.class);
if( localHomeAnn != null ) {
Class localHome = localHomeAnn.value();
Class localIntf = getComponentIntfFromHome(localHome);
if( EJBLocalHome.class.isAssignableFrom(localHome) &&
(localIntf != null) ) {
ejbDesc.setLocalHomeClassName(localHome.getName());
ejbDesc.setLocalClassName(localIntf.getName());
} else {
log(Level.SEVERE, ainfo,
localStrings.getLocalString(
"enterprise.deployment.annotation.handlers.invalidlocalhome",
"Encountered invalid @LocalHome interface {0}.",
new Object[] { localHome }));
return getDefaultFailedResult();
}
}
return getDefaultProcessedResult();
| protected abstract com.sun.enterprise.deployment.annotation.HandlerProcessingResult | setEjbDescriptorInfo(com.sun.enterprise.deployment.EjbDescriptor ejbDesc, com.sun.enterprise.deployment.annotation.AnnotationInfo ainfo)Set Annotation information to Descriptor.
This method will also be invoked for an existing descriptor with
annotation as user may not specific a complete xml.
|
|