Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.openejb.config;
import org.apache.openejb.BeanContext;
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.api.LocalClient;
import org.apache.openejb.api.Proxy;
import org.apache.openejb.api.RemoteClient;
import org.apache.openejb.cdi.CdiBeanInfo;
import org.apache.openejb.config.rules.CheckClasses;
import org.apache.openejb.core.EmptyResourcesClassLoader;
import org.apache.openejb.core.webservices.JaxWsUtils;
import org.apache.openejb.dyni.DynamicSubclass;
import org.apache.openejb.jee.ActivationConfig;
import org.apache.openejb.jee.ActivationSpec;
import org.apache.openejb.jee.AdminObject;
import org.apache.openejb.jee.ApplicationClient;
import org.apache.openejb.jee.AroundInvoke;
import org.apache.openejb.jee.AroundTimeout;
import org.apache.openejb.jee.AssemblyDescriptor;
import org.apache.openejb.jee.AsyncMethod;
import org.apache.openejb.jee.AuthenticationMechanism;
import org.apache.openejb.jee.Beans;
import org.apache.openejb.jee.ConcurrencyManagementType;
import org.apache.openejb.jee.ConcurrentLockType;
import org.apache.openejb.jee.ConcurrentMethod;
import org.apache.openejb.jee.ConfigProperty;
import org.apache.openejb.jee.ContainerConcurrency;
import org.apache.openejb.jee.ContainerTransaction;
import org.apache.openejb.jee.DataSource;
import org.apache.openejb.jee.EjbJar;
import org.apache.openejb.jee.EjbLocalRef;
import org.apache.openejb.jee.EjbRef;
import org.apache.openejb.jee.EjbReference;
import org.apache.openejb.jee.Empty;
import org.apache.openejb.jee.EnterpriseBean;
import org.apache.openejb.jee.EnvEntry;
import org.apache.openejb.jee.ExcludeList;
import org.apache.openejb.jee.FacesConfig;
import org.apache.openejb.jee.FacesManagedBean;
import org.apache.openejb.jee.Filter;
import org.apache.openejb.jee.Handler;
import org.apache.openejb.jee.HandlerChains;
import org.apache.openejb.jee.Icon;
import org.apache.openejb.jee.InboundResourceadapter;
import org.apache.openejb.jee.InitMethod;
import org.apache.openejb.jee.Injectable;
import org.apache.openejb.jee.InjectionTarget;
import org.apache.openejb.jee.Interceptor;
import org.apache.openejb.jee.InterceptorBinding;
import org.apache.openejb.jee.Invokable;
import org.apache.openejb.jee.IsolationLevel;
import org.apache.openejb.jee.JndiConsumer;
import org.apache.openejb.jee.JndiReference;
import org.apache.openejb.jee.License;
import org.apache.openejb.jee.Lifecycle;
import org.apache.openejb.jee.LifecycleCallback;
import org.apache.openejb.jee.Listener;
import org.apache.openejb.jee.MessageAdapter;
import org.apache.openejb.jee.MessageDrivenBean;
import org.apache.openejb.jee.MessageListener;
import org.apache.openejb.jee.MethodAttribute;
import org.apache.openejb.jee.MethodParams;
import org.apache.openejb.jee.MethodPermission;
import org.apache.openejb.jee.NamedMethod;
import org.apache.openejb.jee.OutboundResourceAdapter;
import org.apache.openejb.jee.ParamValue;
import org.apache.openejb.jee.PersistenceContextRef;
import org.apache.openejb.jee.PersistenceContextType;
import org.apache.openejb.jee.PersistenceUnitRef;
import org.apache.openejb.jee.PortComponent;
import org.apache.openejb.jee.Property;
import org.apache.openejb.jee.RemoteBean;
import org.apache.openejb.jee.RemoveMethod;
import org.apache.openejb.jee.ResAuth;
import org.apache.openejb.jee.ResSharingScope;
import org.apache.openejb.jee.ResourceAdapter;
import org.apache.openejb.jee.ResourceEnvRef;
import org.apache.openejb.jee.ResourceRef;
import org.apache.openejb.jee.SecurityIdentity;
import org.apache.openejb.jee.SecurityRoleRef;
import org.apache.openejb.jee.ServiceRef;
import org.apache.openejb.jee.Servlet;
import org.apache.openejb.jee.ServletMapping;
import org.apache.openejb.jee.Session;
import org.apache.openejb.jee.SessionBean;
import org.apache.openejb.jee.SessionType;
import org.apache.openejb.jee.SingletonBean;
import org.apache.openejb.jee.StatefulBean;
import org.apache.openejb.jee.StatelessBean;
import org.apache.openejb.jee.Tag;
import org.apache.openejb.jee.Text;
import org.apache.openejb.jee.Timeout;
import org.apache.openejb.jee.Timer;
import org.apache.openejb.jee.TimerConsumer;
import org.apache.openejb.jee.TimerSchedule;
import org.apache.openejb.jee.TldTaglib;
import org.apache.openejb.jee.TransAttribute;
import org.apache.openejb.jee.TransactionSupportType;
import org.apache.openejb.jee.TransactionType;
import org.apache.openejb.jee.WebApp;
import org.apache.openejb.jee.WebserviceDescription;
import org.apache.openejb.jee.oejb3.OpenejbJar;
import org.apache.openejb.loader.JarLocation;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.util.Classes;
import org.apache.openejb.util.Join;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.openejb.util.SuperProperties;
import org.apache.openejb.util.URLs;
import org.apache.openejb.util.proxy.DynamicProxyImplFactory;
import org.apache.xbean.finder.Annotated;
import org.apache.xbean.finder.AnnotationFinder;
import org.apache.xbean.finder.IAnnotationFinder;
import org.apache.xbean.finder.MetaAnnotatedClass;
import org.apache.xbean.finder.archive.Archive;
import org.apache.xbean.finder.archive.ClassesArchive;
import javax.annotation.ManagedBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.annotation.Resources;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.DenyAll;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.annotation.security.RunAs;
import javax.annotation.sql.DataSourceDefinition;
import javax.annotation.sql.DataSourceDefinitions;
import javax.ejb.AccessTimeout;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.AfterBegin;
import javax.ejb.AfterCompletion;
import javax.ejb.ApplicationException;
import javax.ejb.Asynchronous;
import javax.ejb.BeforeCompletion;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.DependsOn;
import javax.ejb.EJB;
import javax.ejb.EJBHome;
import javax.ejb.EJBLocalHome;
import javax.ejb.EJBLocalObject;
import javax.ejb.EJBObject;
import javax.ejb.EJBs;
import javax.ejb.Init;
import javax.ejb.Local;
import javax.ejb.LocalBean;
import javax.ejb.LocalHome;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.MessageDriven;
import javax.ejb.PostActivate;
import javax.ejb.PrePassivate;
import javax.ejb.Remote;
import javax.ejb.RemoteHome;
import javax.ejb.Remove;
import javax.ejb.Schedule;
import javax.ejb.Schedules;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Stateful;
import javax.ejb.StatefulTimeout;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.interceptor.ExcludeClassInterceptors;
import javax.interceptor.ExcludeDefaultInterceptors;
import javax.interceptor.Interceptors;
import javax.jms.Queue;
import javax.jws.HandlerChain;
import javax.jws.WebService;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.MappedSuperclass;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContexts;
import javax.persistence.PersistenceUnit;
import javax.persistence.PersistenceUnits;
import javax.resource.spi.Activation;
import javax.resource.spi.AdministeredObject;
import javax.resource.spi.ConnectionDefinition;
import javax.resource.spi.ConnectionDefinitions;
import javax.resource.spi.Connector;
import javax.resource.spi.SecurityPermission;
import javax.resource.spi.work.WorkContext;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceProvider;
import javax.xml.ws.WebServiceRef;
import javax.xml.ws.WebServiceRefs;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import static java.util.Arrays.asList;
/**
* @version $Rev$ $Date$
*/
@SuppressWarnings("UnusedDeclaration")
public class AnnotationDeployer implements DynamicDeployer {
public static final Logger logger = Logger.getInstance(LogCategory.OPENEJB_STARTUP, AnnotationDeployer.class.getPackage().getName());
public static final Logger startupLogger = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, "org.apache.openejb.util.resources");
public static final String OPENEJB_JPA_AUTO_SCAN = "openejb.jpa.auto-scan";
public static final String OPENEJB_JPA_AUTO_SCAN_PACKAGE = "openejb.jpa.auto-scan.package";
private static final ThreadLocal currentModule = new ThreadLocal();
private static final Set lookupMissing = new HashSet(2);
private static final String[] JSF_CLASSES = new String[]{
"javax.faces.application.ResourceDependencies",
"javax.faces.application.ResourceDependency",
"javax.faces.bean.ApplicationScoped",
"javax.faces.bean.CustomScoped",
"javax.faces.bean.ManagedBean",
"javax.faces.bean.ManagedProperty",
"javax.faces.bean.NoneScoped",
"javax.faces.bean.ReferencedBean",
"javax.faces.bean.RequestScoped",
"javax.faces.bean.SessionScoped",
"javax.faces.bean.ViewScoped",
"javax.faces.component.FacesComponent",
"javax.faces.component.UIComponent",
"javax.faces.convert.Converter",
"javax.faces.convert.FacesConverter",
"javax.faces.event.ListenerFor",
"javax.faces.event.ListenersFor",
"javax.faces.event.NamedEvent",
"javax.faces.render.FacesBehaviorRenderer",
"javax.faces.render.FacesRenderer",
"javax.faces.render.Renderer",
"javax.faces.validator.FacesValidator",
"javax.faces.validator.Validator"
};
private static final String[] WEB_CLASSES = new String[]{
// Servlet 3.0
"javax.servlet.annotation.WebServlet",
"javax.servlet.annotation.WebFilter",
"javax.servlet.annotation.WebListener",
// WebSocket 1.0 (since Tomcat 7.0.47)
"javax.websocket.server.ServerEndpoint",
"javax.websocket.server.ServerApplicationConfig",
"javax.websocket.Endpoint"
};
private static final Collection API_CLASSES = new ArrayList(WEB_CLASSES.length + JSF_CLASSES.length);
static {
API_CLASSES.addAll(asList(JSF_CLASSES));
API_CLASSES.addAll(asList(WEB_CLASSES));
}
public static final Set knownResourceEnvTypes = new TreeSet(asList(
"javax.ejb.EJBContext",
"javax.ejb.SessionContext",
"javax.ejb.EntityContext",
"javax.ejb.MessageDrivenContext",
"javax.transaction.UserTransaction",
"javax.jms.Queue",
"javax.jms.Topic",
"javax.xml.ws.WebServiceContext",
"javax.ejb.TimerService",
"javax.enterprise.inject.spi.BeanManager",
"javax.validation.Validator",
"javax.validation.ValidatorFactory"
));
public static final Set knownEnvironmentEntries = new TreeSet(asList(
"boolean", "java.lang.Boolean",
"char", "java.lang.Character",
"byte", "java.lang.Byte",
"short", "java.lang.Short",
"int", "java.lang.Integer",
"long", "java.lang.Long",
"float", "java.lang.Float",
"double", "java.lang.Double",
"java.lang.String",
"java.lang.Class"
));
private final DiscoverAnnotatedBeans discoverAnnotatedBeans;
private final ProcessAnnotatedBeans processAnnotatedBeans;
private final EnvEntriesPropertiesDeployer envEntriesPropertiesDeployer;
private final MBeanDeployer mBeanDeployer;
private final BuiltInEnvironmentEntries builtInEnvironmentEntries;
private final MergeWebappJndiContext mergeWebappJndiContext;
public AnnotationDeployer() {
discoverAnnotatedBeans = new DiscoverAnnotatedBeans();
processAnnotatedBeans = new ProcessAnnotatedBeans(SystemInstance.get().getOptions().get("openejb.jaxws.add-remote", false));
builtInEnvironmentEntries = new BuiltInEnvironmentEntries();
envEntriesPropertiesDeployer = new EnvEntriesPropertiesDeployer();
mBeanDeployer = new MBeanDeployer();
mergeWebappJndiContext = new MergeWebappJndiContext();
}
public AppModule deploy(AppModule appModule) throws OpenEJBException {
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(appModule.getClassLoader());
setModule(appModule);
try {
appModule = discoverAnnotatedBeans.deploy(appModule);
appModule = envEntriesPropertiesDeployer.deploy(appModule);
appModule = mergeWebappJndiContext.deploy(appModule);
appModule = builtInEnvironmentEntries.deploy(appModule);
appModule = processAnnotatedBeans.deploy(appModule);
appModule = mergeWebappJndiContext.deploy(appModule);
appModule = mBeanDeployer.deploy(appModule);
return appModule;
} finally {
envEntriesPropertiesDeployer.resetAdditionalEnvEntries();
Thread.currentThread().setContextClassLoader(classLoader);
removeModule();
}
}
// TODO Remove this section. It's called by some code in the assembler.
// The scanning portion should be completed prior to this point
public void deploy(final CdiBeanInfo beanInfo) throws OpenEJBException {
this.processAnnotatedBeans.deploy(beanInfo);
}
public WebModule deploy(WebModule webModule) throws OpenEJBException {
setModule(webModule);
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(webModule.getClassLoader());
try {
webModule = discoverAnnotatedBeans.deploy(webModule);
webModule = envEntriesPropertiesDeployer.deploy(webModule);
webModule = processAnnotatedBeans.deploy(webModule);
return webModule;
} finally {
envEntriesPropertiesDeployer.resetAdditionalEnvEntries();
Thread.currentThread().setContextClassLoader(classLoader);
removeModule();
}
}
public static DeploymentModule getModule() {
return currentModule.get();
}
private static void setModule(final DeploymentModule module) {
currentModule.set(module);
}
private static void removeModule() {
currentModule.remove();
}
private static ValidationContext getValidationContext() {
return getModule().getValidation();
}
private static void mergeApplicationExceptionAnnotation(final AssemblyDescriptor assemblyDescriptor, final Class> exceptionClass, final ApplicationException annotation) {
final org.apache.openejb.jee.ApplicationException applicationException = assemblyDescriptor.getApplicationException(exceptionClass);
if (applicationException.getRollback() == null) {
applicationException.setRollback(annotation.rollback());
}
if (applicationException.getInherited() == null) {
applicationException.setInherited(annotation.inherited());
}
}
public static boolean isKnownEnvironmentEntryType(final Class type) {
return knownEnvironmentEntries.contains(type.getName()) || type.isEnum();
}
public static boolean isShareableJNDINamespace(final String jndiName) {
return jndiName.startsWith("java:global/") || jndiName.startsWith("java:app/") || jndiName.startsWith("java:module/");
}
@SuppressWarnings("unchecked")
public static class DiscoverAnnotatedBeans implements DynamicDeployer {
public AppModule deploy(AppModule appModule) throws OpenEJBException {
if (!appModule.isWebapp() && !appModule.getWebModules().isEmpty()) { // need to scan for jsf stuff at least
try {
appModule.setEarLibFinder(FinderFactory.createFinder(appModule));
} catch (final Exception e) {
logger.error("Can't create a finder for ear libs", e);
}
}
for (final EjbModule ejbModule : appModule.getEjbModules()) {
ejbModule.initAppModule(appModule);
setModule(ejbModule);
try {
deploy(ejbModule);
} finally {
removeModule();
}
}
for (final ClientModule clientModule : appModule.getClientModules()) {
clientModule.initAppModule(appModule);
setModule(clientModule);
try {
deploy(clientModule);
} finally {
removeModule();
}
}
for (final ConnectorModule connectorModule : appModule.getConnectorModules()) {
connectorModule.initAppModule(appModule);
setModule(connectorModule);
try {
deploy(connectorModule);
} finally {
removeModule();
}
}
for (final WebModule webModule : appModule.getWebModules()) { // here we scan by inheritance so great to keep it last
webModule.initAppModule(appModule);
setModule(webModule);
try {
deploy(webModule);
} finally {
removeModule();
}
}
final AdditionalBeanDiscoverer discoverer = SystemInstance.get().getComponent(AdditionalBeanDiscoverer.class);
if (discoverer != null) {
appModule = discoverer.discover(appModule);
}
return appModule;
}
public ClientModule deploy(final ClientModule clientModule) throws OpenEJBException {
if (clientModule.getApplicationClient() == null) {
clientModule.setApplicationClient(new ApplicationClient());
}
// Lots of jars have main classes so this might not even be an app client.
// We're not going to scrape it for @LocalClient or @RemoteClient annotations
// unless they flag us specifically by adding a META-INF/application-client.xml
//
// ClientModules that already have a AnnotationFinder have been generated automatically
// from an EjbModule, so we don't skip those ever.
if (clientModule.getFinder() == null && clientModule.getAltDDs().containsKey("application-client.xml")) {
if (clientModule.getApplicationClient() != null && clientModule.getApplicationClient().isMetadataComplete()) {
return clientModule;
}
}
IAnnotationFinder finder = clientModule.getFinder();
if (finder == null) {
try {
finder = FinderFactory.createFinder(clientModule);
} catch (final MalformedURLException e) {
startupLogger.warning("startup.scrapeFailedForClientModule.url", clientModule.getJarLocation());
return clientModule;
} catch (final Exception e) {
startupLogger.warning("startup.scrapeFailedForClientModule", e, clientModule.getJarLocation());
return clientModule;
}
}
// This method is also called by the deploy(EjbModule) method to see if those
// modules have any @LocalClient or @RemoteClient classes
for (final Annotated> clazz : finder.findMetaAnnotatedClasses(LocalClient.class)) {
clientModule.getLocalClients().add(clazz.get().getName());
}
for (final Annotated> clazz : finder.findMetaAnnotatedClasses(RemoteClient.class)) {
clientModule.getRemoteClients().add(clazz.get().getName());
}
if (clientModule.getApplicationClient() == null) {
if (clientModule.getRemoteClients().size() > 0 || clientModule.getLocalClients().size() > 0) {
clientModule.setApplicationClient(new ApplicationClient());
}
}
return clientModule;
}
public ConnectorModule deploy(final ConnectorModule connectorModule) throws OpenEJBException {
org.apache.openejb.jee.Connector connector = connectorModule.getConnector();
if (connector == null) {
connector = new org.apache.openejb.jee.Connector();
}
// JCA 1.6 - 18.3.1 do not look at annotations if the provided connector
// deployment descriptor is "meta-data complete".
float specVersion = 0;
try {
specVersion = Float.parseFloat(connector.getVersion());
} catch (final Exception e) {
// no-op
}
if (specVersion < 1.6 || Boolean.TRUE.equals(connector.isMetadataComplete())) {
return connectorModule;
}
IAnnotationFinder finder = connectorModule.getFinder();
if (finder == null) {
try {
finder = FinderFactory.createFinder(connectorModule);
connectorModule.setFinder(finder);
} catch (final Exception e) {
// TODO: some sort of error
return connectorModule;
}
}
final List> connectorClasses = finder.findAnnotatedClasses(Connector.class);
// are we allowed to have more than one connector class? Not without a deployment descriptor
if (connector.getResourceAdapter() == null || connector.getResourceAdapter().getResourceAdapterClass() == null || connector.getResourceAdapter().getResourceAdapterClass().length() == 0) {
if (connectorClasses.size() == 0) { //NOPMD
// TODO: fail some validation here too
}
if (connectorClasses.size() > 1) { //NOPMD
// too many connector classes, this is against the spec
// TODO: something like connectorModule.getValidation().fail(ejbName, "abstractAnnotatedAsBean", annotationClass.getSimpleName(), beanClass.get().getName());
}
}
Class> connectorClass = null;
if (connectorClasses.size() == 1) {
connectorClass = connectorClasses.get(0);
}
if (connectorClasses.size() > 1) {
for (final Class> cls : connectorClasses) {
if (cls.getName().equals(connector.getResourceAdapter().getResourceAdapterClass())) {
connectorClass = cls;
break;
}
}
}
if (connectorClass != null) {
if (connector.getResourceAdapter() == null) {
connector.setResourceAdapter(new ResourceAdapter());
}
if (connector.getResourceAdapter().getResourceAdapterClass() == null || connector.getResourceAdapter().getResourceAdapterClass().length() == 0) {
connector.getResourceAdapter().setResourceAdapterClass(connectorClass.getName());
}
final Connector connectorAnnotation = connectorClass.getAnnotation(Connector.class);
connector.setDisplayNames(getTexts(connector.getDisplayNames(), connectorAnnotation.displayName()));
connector.setDescriptions(getTexts(connector.getDescriptions(), connectorAnnotation.description()));
connector.setEisType(getString(connector.getEisType(), connectorAnnotation.eisType()));
connector.setVendorName(getString(connector.getVendorName(), connectorAnnotation.vendorName()));
connector.setResourceAdapterVersion(getString(connector.getResourceAdapterVersion(), connectorAnnotation.version()));
if (connector.getIcons().isEmpty()) {
final int smallIcons = connectorAnnotation.smallIcon().length;
final int largeIcons = connectorAnnotation.largeIcon().length;
for (int i = 0; i < smallIcons && i < largeIcons; i++) {
final Icon icon = new Icon();
// locale can't be specified in the annotation and it is en by default
// so on other systems it doesn't work because Icon return the default locale
icon.setLang(Locale.getDefault().getLanguage());
if (i < smallIcons) {
icon.setSmallIcon(connectorAnnotation.smallIcon()[i]);
}
if (i < largeIcons) {
icon.setLargeIcon(connectorAnnotation.largeIcon()[i]);
}
connector.getIcons().add(icon);
}
}
if (connector.getLicense() == null) {
final License license = new License();
connector.setLicense(license);
license.setLicenseRequired(connectorAnnotation.licenseRequired());
}
connector.getLicense().setDescriptions(getTexts(connector.getLicense().getDescriptions(), connectorAnnotation.licenseDescription()));
final SecurityPermission[] annotationSecurityPermissions = connectorAnnotation.securityPermissions();
List securityPermission = connector.getResourceAdapter().getSecurityPermission();
if (securityPermission == null) {
securityPermission = new ArrayList();
}
if (securityPermission.size() == 0) {
for (final SecurityPermission sp : annotationSecurityPermissions) {
final org.apache.openejb.jee.SecurityPermission permission = new org.apache.openejb.jee.SecurityPermission();
permission.setSecurityPermissionSpec(sp.permissionSpec());
permission.setDescriptions(stringsToTexts(sp.description()));
securityPermission.add(permission);
}
}
final Class extends WorkContext>[] annotationRequiredWorkContexts = connectorAnnotation.requiredWorkContexts();
final List requiredWorkContext = connector.getRequiredWorkContext();
if (requiredWorkContext.size() == 0) {
for (final Class extends WorkContext> cls : annotationRequiredWorkContexts) {
requiredWorkContext.add(cls.getName());
}
}
OutboundResourceAdapter outboundResourceAdapter = connector.getResourceAdapter().getOutboundResourceAdapter();
if (outboundResourceAdapter == null) {
outboundResourceAdapter = new OutboundResourceAdapter();
connector.getResourceAdapter().setOutboundResourceAdapter(outboundResourceAdapter);
}
final List authenticationMechanisms = outboundResourceAdapter.getAuthenticationMechanism();
final javax.resource.spi.AuthenticationMechanism[] authMechanisms = connectorAnnotation.authMechanisms();
if (authenticationMechanisms.size() == 0) {
for (final javax.resource.spi.AuthenticationMechanism am : authMechanisms) {
final AuthenticationMechanism authMechanism = new AuthenticationMechanism();
authMechanism.setAuthenticationMechanismType(am.authMechanism());
authMechanism.setCredentialInterface(am.credentialInterface().toString());
authMechanism.setDescriptions(stringsToTexts(am.description()));
authenticationMechanisms.add(authMechanism);
}
}
if (outboundResourceAdapter.getTransactionSupport() == null) {
outboundResourceAdapter.setTransactionSupport(TransactionSupportType.fromValue(connectorAnnotation.transactionSupport().toString()));
}
if (outboundResourceAdapter.isReauthenticationSupport() == null) {
outboundResourceAdapter.setReauthenticationSupport(connectorAnnotation.reauthenticationSupport());
}
}
// process @ConnectionDescription(s)
List> classes = finder.findAnnotatedClasses(ConnectionDefinitions.class);
for (final Class> cls : classes) {
final ConnectionDefinitions connectionDefinitionsAnnotation = cls.getAnnotation(ConnectionDefinitions.class);
final ConnectionDefinition[] definitions = connectionDefinitionsAnnotation.value();
for (final ConnectionDefinition definition : definitions) {
processConnectionDescription(connector.getResourceAdapter(), definition, cls);
}
}
classes = finder.findAnnotatedClasses(ConnectionDefinition.class);
for (final Class> cls : classes) {
final ConnectionDefinition connectionDefinitionAnnotation = cls.getAnnotation(ConnectionDefinition.class);
processConnectionDescription(connector.getResourceAdapter(), connectionDefinitionAnnotation, cls);
}
InboundResourceadapter inboundResourceAdapter = connector.getResourceAdapter().getInboundResourceAdapter();
if (inboundResourceAdapter == null) {
inboundResourceAdapter = new InboundResourceadapter();
connector.getResourceAdapter().setInboundResourceAdapter(inboundResourceAdapter);
}
MessageAdapter messageAdapter = inboundResourceAdapter.getMessageAdapter();
if (messageAdapter == null) {
messageAdapter = new MessageAdapter();
inboundResourceAdapter.setMessageAdapter(messageAdapter);
}
classes = finder.findAnnotatedClasses(Activation.class);
for (final Class> cls : classes) {
MessageListener messageListener = null;
final Activation activationAnnotation = cls.getAnnotation(Activation.class);
final List messageListeners = messageAdapter.getMessageListener();
for (final MessageListener ml : messageListeners) {
if (cls.getName().equals(ml.getActivationSpec().getActivationSpecClass())) {
messageListener = ml;
break;
}
}
if (messageListener == null) {
final Class>[] listeners = activationAnnotation.messageListeners();
for (final Class> listener : listeners) {
messageAdapter.addMessageListener(new MessageListener(listener.getName(), cls.getName()));
}
}
}
classes = finder.findAnnotatedClasses(AdministeredObject.class);
final List adminObjects = connector.getResourceAdapter().getAdminObject();
for (final Class> cls : classes) {
final AdministeredObject administeredObjectAnnotation = cls.getAnnotation(AdministeredObject.class);
final Class[] adminObjectInterfaces = administeredObjectAnnotation.adminObjectInterfaces();
AdminObject adminObject = null;
for (final AdminObject admObj : adminObjects) {
if (admObj.getAdminObjectClass().equals(cls.getName())) {
adminObject = admObj;
}
}
if (adminObject == null) {
for (final Class iface : adminObjectInterfaces) {
final AdminObject newAdminObject = new AdminObject();
newAdminObject.setAdminObjectClass(cls.getName());
newAdminObject.setAdminObjectInterface(iface.getName());
adminObjects.add(newAdminObject);
}
}
}
// need to make a list of classes to process for config properties
// resource adapter
final String raCls = connector.getResourceAdapter().getResourceAdapterClass();
process(connectorModule.getClassLoader(), raCls, connector.getResourceAdapter());
// managedconnectionfactory
if (connector.getResourceAdapter() != null && connector.getResourceAdapter().getOutboundResourceAdapter() != null) {
final List connectionDefinitions = connector.getResourceAdapter().getOutboundResourceAdapter().getConnectionDefinition();
for (final org.apache.openejb.jee.ConnectionDefinition connectionDefinition : connectionDefinitions) {
process(connectorModule.getClassLoader(), connectionDefinition.getManagedConnectionFactoryClass(), connectionDefinition);
}
}
// administeredobject
if (connector.getResourceAdapter() != null) {
final List raAdminObjects = connector.getResourceAdapter().getAdminObject();
for (final AdminObject raAdminObject : raAdminObjects) {
process(connectorModule.getClassLoader(), raAdminObject.getAdminObjectClass(), raAdminObject);
}
}
// activationspec
if (connector.getResourceAdapter() != null && connector.getResourceAdapter().getInboundResourceAdapter() != null && connector.getResourceAdapter().getInboundResourceAdapter().getMessageAdapter() != null) {
final List messageListeners = connector.getResourceAdapter().getInboundResourceAdapter().getMessageAdapter().getMessageListener();
for (final MessageListener messageListener : messageListeners) {
final ActivationSpec activationSpec = messageListener.getActivationSpec();
process(connectorModule.getClassLoader(), activationSpec.getActivationSpecClass(), activationSpec);
}
}
return connectorModule;
}
void process(final ClassLoader cl, final String cls, final Object object) {
List configProperties = null;
try {
// grab a list of ConfigProperty objects
configProperties = (List) object.getClass().getDeclaredMethod("getConfigProperty").invoke(object);
} catch (final Exception e) {
// no-op
}
if (configProperties == null) {
// can't get config properties
return;
}
ClassLoader classLoader = cl;
if (classLoader == null) {
classLoader = Thread.currentThread().getContextClassLoader();
}
final List allowedTypes = asList(Boolean.class.getName(), String.class.getName(), Integer.class.getName(), Double.class.getName(), Byte.class.getName(), Short.class.getName(), Long.class.getName(), Float.class.getName(), Character.class.getName());
try {
final Class> clazz = classLoader.loadClass(realClassName(cls));
final Object o = clazz.newInstance();
// add any introspected properties
final BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
final PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (final PropertyDescriptor propertyDescriptor : propertyDescriptors) {
final String name = propertyDescriptor.getName();
Class> type = propertyDescriptor.getPropertyType();
if (type == null) {
continue;
}
if (type.isPrimitive()) {
type = getWrapper(type.getName());
}
if (!allowedTypes.contains(type.getName())) {
continue;
}
if (!containsConfigProperty(configProperties, name)) {
final ConfigProperty configProperty = new ConfigProperty();
configProperties.add(configProperty);
Object value = null;
if (propertyDescriptor.getReadMethod() != null) {
try {
value = propertyDescriptor.getReadMethod().invoke(o);
} catch (final Exception e) {
// no-op
}
}
final Method write = propertyDescriptor.getWriteMethod();
javax.resource.spi.ConfigProperty annotation = null;
if (write != null) {
annotation = write.getAnnotation(javax.resource.spi.ConfigProperty.class);
if (annotation == null) {
try {
// if there's no annotation on the setter, we'll try and scrape one off the field itself (assuming the same name)
annotation = clazz.getDeclaredField(name).getAnnotation(javax.resource.spi.ConfigProperty.class);
} catch (final Exception ignored) {
// no-op : getDeclaredField() throws exceptions and does not return null
}
}
}
configProperty.setConfigPropertyName(name);
configProperty.setConfigPropertyType(getConfigPropertyType(annotation, type));
if (value != null) {
configProperty.setConfigPropertyValue(value.toString());
}
if (annotation != null) {
if (annotation.defaultValue() != null && annotation.defaultValue().length() > 0) {
configProperty.setConfigPropertyValue(annotation.defaultValue());
}
configProperty.setConfigPropertyConfidential(annotation.confidential());
configProperty.setConfigPropertyIgnore(annotation.ignore());
configProperty.setConfigPropertySupportsDynamicUpdates(annotation.supportsDynamicUpdates());
configProperty.setDescriptions(stringsToTexts(annotation.description()));
}
}
}
// add any annotated fields we haven't already picked up
final Field[] declaredFields = clazz.getDeclaredFields();
for (final Field field : declaredFields) {
final javax.resource.spi.ConfigProperty annotation = field.getAnnotation(javax.resource.spi.ConfigProperty.class);
final String name = field.getName();
Object value = null;
try {
value = field.get(o);
} catch (final Exception e) {
// no-op
}
if (!containsConfigProperty(configProperties, name)) {
final String type = getConfigPropertyType(annotation, field.getType());
if (type != null) {
final ConfigProperty configProperty = new ConfigProperty();
configProperties.add(configProperty);
configProperty.setConfigPropertyName(name);
configProperty.setConfigPropertyType(type);
if (value != null) {
configProperty.setConfigPropertyValue(value.toString());
}
if (annotation != null) {
if (annotation.defaultValue() != null) {
configProperty.setConfigPropertyValue(annotation.defaultValue());
}
configProperty.setConfigPropertyConfidential(annotation.confidential());
configProperty.setConfigPropertyIgnore(annotation.ignore());
configProperty.setConfigPropertySupportsDynamicUpdates(annotation.supportsDynamicUpdates());
}
}
}
}
} catch (final Exception e) {
e.printStackTrace();
}
}
private String getConfigPropertyType(final javax.resource.spi.ConfigProperty annotation, final Class> type) {
Class> t = annotation == null ? null : annotation.type();
if (t == null && type != null) {
return type.getName();
} else if (t == null) {
return null;
}
if (t.equals(Object.class)) {
t = type;
}
if (t == null) { // t == null && type == null
return null;
}
if (t.isPrimitive()) {
t = getWrapper(t.getName());
}
return t.getName();
}
private boolean containsConfigProperty(final List configProperties, final String name) {
for (final ConfigProperty configProperty : configProperties) {
if (configProperty.getConfigPropertyName().equals(name)) {
return true;
}
}
return false;
}
private Class> getWrapper(final String primitiveType) {
final Map> builtInMap = new HashMap>();
{
builtInMap.put("int", Integer.class);
builtInMap.put("long", Long.class);
builtInMap.put("double", Double.class);
builtInMap.put("float", Float.class);
builtInMap.put("boolean", Boolean.class);
builtInMap.put("char", Character.class);
builtInMap.put("byte", Byte.class);
builtInMap.put("void", Void.class);
builtInMap.put("short", Short.class);
}
return builtInMap.get(primitiveType);
}
private void processConnectionDescription(final ResourceAdapter resourceAdapter, final ConnectionDefinition connectionDefinitionAnnotation, final Class> cls) {
// try and find the managed connection factory
OutboundResourceAdapter outboundResourceAdapter = resourceAdapter.getOutboundResourceAdapter();
if (outboundResourceAdapter == null) {
outboundResourceAdapter = new OutboundResourceAdapter();
resourceAdapter.setOutboundResourceAdapter(outboundResourceAdapter);
}
final List connectionDefinition = outboundResourceAdapter.getConnectionDefinition();
org.apache.openejb.jee.ConnectionDefinition definition = null;
for (final org.apache.openejb.jee.ConnectionDefinition cd : connectionDefinition) {
if (cd.getManagedConnectionFactoryClass().equals(cls.getName())) {
definition = cd;
break;
}
}
if (definition == null) {
definition = new org.apache.openejb.jee.ConnectionDefinition();
outboundResourceAdapter.getConnectionDefinition().add(definition);
}
if (definition.getManagedConnectionFactoryClass() == null) {
definition.setManagedConnectionFactoryClass(cls.getName());
}
if (definition.getConnectionInterface() == null) {
definition.setConnectionInterface(connectionDefinitionAnnotation.connection().getName());
}
if (definition.getConnectionImplClass() == null) {
definition.setConnectionImplClass(connectionDefinitionAnnotation.connectionImpl().getName());
}
if (definition.getConnectionFactoryInterface() == null) {
definition.setConnectionFactoryInterface(connectionDefinitionAnnotation.connectionFactory().getName());
}
if (definition.getConnectionFactoryImplClass() == null) {
definition.setConnectionFactoryImplClass(connectionDefinitionAnnotation.connectionFactoryImpl().getName());
}
}
private Text[] stringsToTexts(final String[] strings) {
if (strings == null) {
return null;
}
final Text[] result = new Text[strings.length];
for (int i = 0; i < result.length; i++) {
result[i] = new Text();
result[i].setValue(strings[i]);
}
return result;
}
private String getString(final String descriptorString, final String annotationString) {
if (descriptorString != null && descriptorString.length() > 0) {
return descriptorString;
}
if (annotationString != null && annotationString.length() > 0) {
return annotationString;
}
return null;
}
private Text[] getTexts(final Text[] originalTexts, final String[] newStrings) {
if (newStrings != null && newStrings.length > 0 && (originalTexts == null || originalTexts.length == 0)) {
final Text[] texts = new Text[newStrings.length];
for (int i = 0; i < newStrings.length; i++) {
texts[i] = new Text(null, newStrings[i]);
}
return texts;
} else {
return originalTexts;
}
}
public WebModule deploy(final WebModule webModule) throws OpenEJBException {
WebApp webApp = webModule.getWebApp();
if (webApp != null && webApp.isMetadataComplete()) {
return webModule;
}
try {
if (webModule.getFinder() == null) {
webModule.setFinder(FinderFactory.createFinder(webModule));
}
} catch (final Exception e) {
startupLogger.warning("Unable to scrape for @WebService or @WebServiceProvider annotations. AnnotationFinder failed.", e);
return webModule;
}
if (webApp == null) {
webApp = new WebApp();
webModule.setWebApp(webApp);
}
final List existingServlets = new ArrayList();
for (final Servlet servlet : webApp.getServlet()) {
if (servlet.getServletClass() != null) {
existingServlets.add(servlet.getServletClass());
}
}
final IAnnotationFinder finder = webModule.getFinder();
final List classes = new ArrayList();
classes.addAll(finder.findAnnotatedClasses(WebService.class));
classes.addAll(finder.findAnnotatedClasses(WebServiceProvider.class));
for (final Class> webServiceClass : classes) {
// If this class is also annotated @Stateless or @Singleton, we should skip it
if (webServiceClass.isAnnotationPresent(Singleton.class) || webServiceClass.isAnnotationPresent(Stateless.class)) {
webModule.getEjbWebServices().add(webServiceClass.getName());
continue;
}
final int modifiers = webServiceClass.getModifiers();
if (!Modifier.isPublic(modifiers) || Modifier.isFinal(modifiers) || Modifier.isAbstract(modifiers)) {
continue;
}
if (existingServlets.contains(webServiceClass.getName())) {
continue;
}
// create webApp and webservices objects if they don't exist already
// add new element
final Servlet servlet = new Servlet();
servlet.setServletName(webServiceClass.getName());
servlet.setServletClass(webServiceClass.getName());
final ParamValue param = new ParamValue();
param.setParamName("openejb-internal");
param.setParamValue("true");
servlet.getInitParam().add(param);
webApp.getServlet().add(servlet);
}
/*
* REST
*/
boolean restHandledByTheWebApp;
try {
restHandledByTheWebApp = webModule.getClassLoader().loadClass(Application.class.getName()) != Application.class;
} catch (final Throwable e) { // ClassNotFoundException or NoClassDefFoundError
restHandledByTheWebApp = false;
}
if (!restHandledByTheWebApp) {
// get by annotations
webModule.getRestClasses().addAll(findRestClasses(webModule, finder));
addJaxRsProviders(finder, webModule.getJaxrsProviders(), Provider.class);
// Applications with a default constructor
// findSubclasses will not work by default to gain a lot of time
// look FinderFactory for the flag to activate it or
// use @ApplicationPath("/")
final List> applications = finder.findSubclasses(Application.class);
for (final Class extends Application> app : applications) {
addRestApplicationIfPossible(webModule, app);
}
// look for ApplicationPath, it will often return the same than the previous one
// but without finder.link() invocation it still works
// so it can save a lot of startup time
final List>> applicationsByAnnotation = finder.findMetaAnnotatedClasses(ApplicationPath.class);
for (final Annotated> annotatedApp : applicationsByAnnotation) {
final Class> app = annotatedApp.get();
if (!Application.class.isAssignableFrom(app)) {
logger.error("class '" + app.getName() + "' is annotated with @ApplicationPath but doesn't implement " + Application.class.getName());
continue;
}
addRestApplicationIfPossible(webModule, (Class extends Application>) app);
}
}
/*
* JSF
*/
// we need to look for JSF stuff in ear libs (converters...) so get back the finder for this part
IAnnotationFinder parentFinder = null;
final AppModule appModule = webModule.getAppModule();
if (appModule != null) {
parentFinder = appModule.getEarLibFinder();
} else {
logger.info("Web module has no App module: " + webModule.toString());
}
final ClassLoader classLoader = webModule.getClassLoader();
for (final String jsfClass : JSF_CLASSES) {
final Class extends Annotation> clazz;
try {
clazz = (Class extends Annotation>) classLoader.loadClass(jsfClass);
} catch (final ClassNotFoundException e) {
continue;
}
final Set convertedClasses = new HashSet();
if (parentFinder != null) {
final List>> foundParent = parentFinder.findMetaAnnotatedClasses(clazz);
for (final Annotated> annotated : foundParent) {
convertedClasses.add(annotated.get().getName());
}
if (null != appModule) {
for (final EjbModule module : appModule.getEjbModules()) {
// if we are deploying a webapp we don't need to (re)do it
// or if this module is another webapp we don't need to look it
// otherwise that's a common part of ear we want to scan
if (appModule.isWebapp() || module.isWebapp() && !module.getModuleId().equals(webModule.getModuleId())) {
continue;
}
final List>> ejbFound = module.getFinder().findMetaAnnotatedClasses(clazz);
for (final Annotated> annotated : ejbFound) {
convertedClasses.add(annotated.get().getName());
}
}
}
}
final List>> found = finder.findMetaAnnotatedClasses(clazz);
for (final Annotated> annotated : found) {
convertedClasses.add(annotated.get().getName());
}
webModule.getJsfAnnotatedClasses().put(jsfClass, convertedClasses);
}
/*
* Servlet, Filter, Listener...
* here we can scan by inheritance so do it last
*/
Map urlByClasses = null;
for (final String apiClassName : WEB_CLASSES) {
final Class extends Annotation> clazz;
try {
clazz = (Class extends Annotation>) classLoader.loadClass(apiClassName);
} catch (final ClassNotFoundException e) {
continue;
}
if (urlByClasses == null) { // try to reuse scanning info, maybe some better indexing can be a nice idea
if (finder instanceof FinderFactory.ModuleLimitedFinder) {
final IAnnotationFinder limitedFinder = ((FinderFactory.ModuleLimitedFinder) finder).getDelegate();
if (limitedFinder instanceof AnnotationFinder) {
final Archive archive = ((AnnotationFinder) limitedFinder).getArchive();
if (archive instanceof WebappAggregatedArchive) {
final Map> index = ((WebappAggregatedArchive) archive).getClassesMap();
urlByClasses = new HashMap();
for (final Map.Entry> entry : index.entrySet()) {
final String url = entry.getKey().toExternalForm();
for (final String current : entry.getValue()) {
urlByClasses.put(current, url);
}
}
}
}
}
}
final List>> found = finder.findMetaAnnotatedClasses(clazz);
addWebAnnotatedClassInfo(urlByClasses, webModule.getWebAnnotatedClasses(), found);
}
if (urlByClasses != null) {
urlByClasses.clear();
}
return webModule;
}
private void addJaxRsProviders(final IAnnotationFinder finder, final Collection set, final Class extends Annotation> annotation) {
for (final Annotated> provider : finder.findMetaAnnotatedClasses(annotation)) {
set.add(provider.get().getName());
}
}
private static void addRestApplicationIfPossible(final WebModule webModule, final Class extends Application> app) {
if (!isInstantiable(app)) {
return;
}
if (app.getConstructors().length == 0) {
webModule.getRestApplications().add(app.getName());
} else {
for (final Constructor> ctr : app.getConstructors()) {
if (ctr.getParameterTypes().length == 0) {
webModule.getRestApplications().add(app.getName());
break;
}
}
}
}
public EjbModule deploy(final EjbModule ejbModule) throws OpenEJBException {
if (ejbModule.getEjbJar() != null && ejbModule.getEjbJar().isMetadataComplete()) {
return ejbModule;
}
try {
if (ejbModule.getFinder() == null) {
ejbModule.setFinder(FinderFactory.createFinder(ejbModule));
}
} catch (final MalformedURLException e) {
startupLogger.warning("startup.scrapeFailedForModule", ejbModule.getJarLocation());
return ejbModule;
} catch (final Exception e) {
startupLogger.warning("Unable to scrape for @Stateful, @Stateless, @Singleton or @MessageDriven annotations. AnnotationFinder failed.", e);
return ejbModule;
}
final IAnnotationFinder finder = ejbModule.getFinder();
final List managedClasses;
{
final Beans beans = ejbModule.getBeans();
if (beans != null) {
managedClasses = beans.getManagedClasses();
managedClasses.addAll(getBeanClasses(finder));
// passing jar location to be able to manage maven classes/test-classes which have the same moduleId
String id = ejbModule.getModuleId();
if (ejbModule.getJarLocation() != null && ejbModule.getJarLocation().contains(ejbModule.getModuleId() + "/target/test-classes".replace("/", File.separator))) {
// with maven if both src/main/java and src/test/java are deployed
// moduleId.Comp exists twice so it fails
// here we simply modify the test comp bean name to avoid it
id += "_test";
}
final String name = BeanContext.Comp.openejbCompName(id);
final org.apache.openejb.jee.ManagedBean managedBean = new CompManagedBean(name, BeanContext.Comp.class);
managedBean.setTransactionType(TransactionType.BEAN);
ejbModule.getEjbJar().addEnterpriseBean(managedBean);
if ("true".equals(SystemInstance.get().getProperty("openejb.cdi.support.@Startup", "true"))) {
final List>> forceStart = finder.findMetaAnnotatedClasses(Startup.class);
final List startupBeans = beans.getStartupBeans();
for (final Annotated> clazz : forceStart) {
startupBeans.add(clazz.get().getName());
}
}
} else {
managedClasses = new LinkedList();
}
}
// Fill in default sessionType for xml declared EJBs
for (final EnterpriseBean bean : ejbModule.getEjbJar().getEnterpriseBeans()) {
if (!(bean instanceof SessionBean)) {
continue;
}
final SessionBean sessionBean = (SessionBean) bean;
if (sessionBean.getSessionType() != null) {
continue;
}
try {
final Class> clazz = ejbModule.getClassLoader().loadClass(bean.getEjbClass());
sessionBean.setSessionType(getSessionType(clazz));
} catch (final Throwable handledInValidation) {
// no-op
}
}
// Fill in default ejbName for xml declared EJBs
for (final EnterpriseBean bean : ejbModule.getEjbJar().getEnterpriseBeans()) {
if (bean.getEjbClass() == null) {
continue;
}
if (bean.getEjbName() == null || bean.getEjbName().startsWith("@NULL@")) {
ejbModule.getEjbJar().removeEnterpriseBean(bean.getEjbName());
try {
final Class> clazz = ejbModule.getClassLoader().loadClass(bean.getEjbClass());
final String ejbName = getEjbName(bean, clazz);
bean.setEjbName(ejbName);
} catch (final Throwable handledInValidation) {
// no-op
}
ejbModule.getEjbJar().addEnterpriseBean(bean);
}
}
/* 19.2: ejb-name: Default is the unqualified name of the bean class */
final EjbJar ejbJar = ejbModule.getEjbJar();
for (final Annotated> beanClass : finder.findMetaAnnotatedClasses(Singleton.class)) {
final Singleton singleton = beanClass.getAnnotation(Singleton.class);
final String ejbName = getEjbName(singleton, beanClass.get());
if (!isValidEjbAnnotationUsage(Singleton.class, beanClass, ejbName, ejbModule)) {
continue;
}
EnterpriseBean enterpriseBean = ejbJar.getEnterpriseBean(ejbName);
if (enterpriseBean == null) {
enterpriseBean = new SingletonBean(ejbName, beanClass.get());
ejbJar.addEnterpriseBean(enterpriseBean);
}
if (enterpriseBean.getEjbClass() == null) {
enterpriseBean.setEjbClass(beanClass.get());
}
if (enterpriseBean instanceof SessionBean) {
final SessionBean sessionBean = (SessionBean) enterpriseBean;
sessionBean.setSessionType(SessionType.SINGLETON);
if (singleton.mappedName() != null) {
sessionBean.setMappedName(singleton.mappedName());
}
}
LegacyProcessor.process(beanClass.get(), enterpriseBean);
}
for (final Annotated> beanClass : finder.findMetaAnnotatedClasses(Stateless.class)) {
final Stateless stateless = beanClass.getAnnotation(Stateless.class);
final String ejbName = getEjbName(stateless, beanClass.get());
if (!isValidEjbAnnotationUsage(Stateless.class, beanClass, ejbName, ejbModule)) {
continue;
}
EnterpriseBean enterpriseBean = ejbJar.getEnterpriseBean(ejbName);
if (enterpriseBean == null) {
enterpriseBean = new StatelessBean(ejbName, beanClass.get());
ejbJar.addEnterpriseBean(enterpriseBean);
}
if (enterpriseBean.getEjbClass() == null) {
enterpriseBean.setEjbClass(beanClass.get());
}
if (enterpriseBean instanceof SessionBean) {
final SessionBean sessionBean = (SessionBean) enterpriseBean;
sessionBean.setSessionType(SessionType.STATELESS);
if (stateless.mappedName() != null) {
sessionBean.setMappedName(stateless.mappedName());
}
}
LegacyProcessor.process(beanClass.get(), enterpriseBean);
}
// The Specialization code is good, but it possibly needs to be moved to after the full processing of the bean
// the plus is that it would get the required interfaces. The minus is that it would get all the other items
// Possibly study alternatives. Alternatives might have different meta data completely while it seems Specializing beans inherit all meta-data
// Anyway.. the qualifiers aren't getting inherited, so we need to fix that
for (final Annotated> beanClass : finder.findMetaAnnotatedClasses(Stateful.class)) {
final Stateful stateful = beanClass.getAnnotation(Stateful.class);
final String ejbName = getEjbName(stateful, beanClass.get());
if (!isValidEjbAnnotationUsage(Stateful.class, beanClass, ejbName, ejbModule)) {
continue;
}
EnterpriseBean enterpriseBean = ejbJar.getEnterpriseBean(ejbName);
if (enterpriseBean == null) {
enterpriseBean = new StatefulBean(ejbName, beanClass.get());
ejbJar.addEnterpriseBean(enterpriseBean);
}
if (enterpriseBean.getEjbClass() == null) {
enterpriseBean.setEjbClass(beanClass.get());
}
if (enterpriseBean instanceof SessionBean) {
final SessionBean sessionBean = (SessionBean) enterpriseBean;
// TODO: We might be stepping on an xml override here
sessionBean.setSessionType(SessionType.STATEFUL);
if (stateful.mappedName() != null) {
sessionBean.setMappedName(stateful.mappedName());
}
}
LegacyProcessor.process(beanClass.get(), enterpriseBean);
}
for (final Annotated> beanClass : finder.findMetaAnnotatedClasses(ManagedBean.class)) {
final ManagedBean managed = beanClass.getAnnotation(ManagedBean.class);
final String ejbName = getEjbName(managed, beanClass.get());
// TODO: this is actually against the spec, but the requirement is rather silly
// (allowing @Stateful and @ManagedBean on the same class)
// If the TCK doesn't complain we should discourage it
if (!isValidEjbAnnotationUsage(ManagedBean.class, beanClass, ejbName, ejbModule)) {
continue;
}
EnterpriseBean enterpriseBean = ejbJar.getEnterpriseBean(ejbName);
if (enterpriseBean == null) {
enterpriseBean = new org.apache.openejb.jee.ManagedBean(ejbName, beanClass.get());
ejbJar.addEnterpriseBean(enterpriseBean);
}
if (enterpriseBean.getEjbClass() == null) {
enterpriseBean.setEjbClass(beanClass.get());
}
if (enterpriseBean instanceof SessionBean) {
final SessionBean sessionBean = (SessionBean) enterpriseBean;
sessionBean.setSessionType(SessionType.MANAGED);
final TransactionType transactionType = sessionBean.getTransactionType();
if (transactionType == null) {
sessionBean.setTransactionType(TransactionType.BEAN);
}
}
}
for (final Annotated> beanClass : finder.findMetaAnnotatedClasses(MessageDriven.class)) {
final MessageDriven mdb = beanClass.getAnnotation(MessageDriven.class);
final String ejbName = getEjbName(mdb, beanClass.get());
if (!isValidEjbAnnotationUsage(MessageDriven.class, beanClass, ejbName, ejbModule)) {
continue;
}
MessageDrivenBean messageBean = (MessageDrivenBean) ejbJar.getEnterpriseBean(ejbName);
if (messageBean == null) {
messageBean = new MessageDrivenBean(ejbName);
ejbJar.addEnterpriseBean(messageBean);
}
if (messageBean.getEjbClass() == null) {
messageBean.setEjbClass(beanClass.get());
}
LegacyProcessor.process(beanClass.get(), messageBean);
}
AssemblyDescriptor assemblyDescriptor = ejbModule.getEjbJar().getAssemblyDescriptor();
if (assemblyDescriptor == null) {
assemblyDescriptor = new AssemblyDescriptor();
ejbModule.getEjbJar().setAssemblyDescriptor(assemblyDescriptor);
}
startupLogger.debug("Searching for annotated application exceptions (see OPENEJB-980)");
final List> appExceptions = finder.findAnnotatedClasses(ApplicationException.class);
for (final Class> exceptionClass : appExceptions) {
startupLogger.debug("...handling " + exceptionClass);
final ApplicationException annotation = exceptionClass.getAnnotation(ApplicationException.class);
if (assemblyDescriptor.getApplicationException(exceptionClass) == null) {
startupLogger.debug("...adding " + exceptionClass + " with rollback=" + annotation.rollback());
assemblyDescriptor.addApplicationException(exceptionClass, annotation.rollback(), annotation.inherited());
} else {
mergeApplicationExceptionAnnotation(assemblyDescriptor, exceptionClass, annotation);
}
}
// ejb can be rest bean and only then in standalone so scan providers here too
// adding them to app since they should be in the app classloader
if (ejbModule.getAppModule() != null) {
addJaxRsProviders(finder, ejbModule.getAppModule().getJaxRsProviders(), Provider.class);
}
if (ejbModule.getAppModule() != null) {
for (final PersistenceModule pm : ejbModule.getAppModule().getPersistenceModules()) {
for (final org.apache.openejb.jee.jpa.unit.PersistenceUnit pu : pm.getPersistence().getPersistenceUnit()) {
if ((pu.isExcludeUnlistedClasses() == null || !pu.isExcludeUnlistedClasses())
&& "true".equalsIgnoreCase(pu.getProperties().getProperty(OPENEJB_JPA_AUTO_SCAN))) {
final String packageName = pu.getProperties().getProperty(OPENEJB_JPA_AUTO_SCAN_PACKAGE);
String[] packageNames = null;
if (packageName != null) {
packageNames = packageName.split(",");
}
// no need of meta currently since JPA providers doesn't support it
final List> classes = new ArrayList>();
classes.addAll(finder.findAnnotatedClasses(Entity.class));
classes.addAll(finder.findAnnotatedClasses(Embeddable.class));
classes.addAll(finder.findAnnotatedClasses(MappedSuperclass.class));
final List existingClasses = pu.getClazz();
for (final Class> clazz : classes) {
final String name = clazz.getName();
if (existingClasses.contains(name)) {
continue;
}
if (packageNames == null) {
pu.getClazz().add(name);
} else {
for (final String pack : packageNames) {
if (name.startsWith(pack)) {
pu.getClazz().add(name);
}
}
}
}
pu.setScanned(true);
}
}
}
}
return ejbModule;
}
private SessionType getSessionType(final Class> clazz) {
if (clazz.isAnnotationPresent(Stateful.class)) {
return SessionType.STATEFUL;
}
if (clazz.isAnnotationPresent(Stateless.class)) {
return SessionType.STATELESS;
}
if (clazz.isAnnotationPresent(Singleton.class)) {
return SessionType.SINGLETON;
}
if (clazz.isAnnotationPresent(ManagedBean.class)) {
return SessionType.MANAGED;
}
return null;
}
private String getEjbName(final EnterpriseBean bean, final Class> clazz) {
if (bean instanceof SessionBean) {
final SessionBean sessionBean = (SessionBean) bean;
switch (sessionBean.getSessionType()) {
case STATEFUL: {
final Stateful annotation = clazz.getAnnotation(Stateful.class);
if (annotation != null && specified(annotation.name())) {
return annotation.name();
}
}
case STATELESS: {
final Stateless annotation = clazz.getAnnotation(Stateless.class);
if (annotation != null && specified(annotation.name())) {
return annotation.name();
}
}
case SINGLETON: {
final Singleton annotation = clazz.getAnnotation(Singleton.class);
if (annotation != null && specified(annotation.name())) {
return annotation.name();
}
}
}
}
if (bean instanceof MessageDrivenBean) {
final MessageDriven annotation = clazz.getAnnotation(MessageDriven.class);
if (annotation != null && specified(annotation.name())) {
return annotation.name();
}
}
return clazz.getSimpleName();
}
private static boolean specified(final String name) {
return name != null && name.length() != 0;
}
private List getBeanClasses(final IAnnotationFinder finder) {
// What we're hoping in this method is to get lucky and find
// that our 'finder' instances is an AnnotationFinder that is
// holding an AggregatedArchive so we can get the classes that
// that pertain to each URL for CDI purposes.
//
// If not we call finder.getAnnotatedClassNames() which may return
// more classes than actually apply to CDI. This can "pollute"
// the CDI class space and break injection points
// force cast otherwise we would be broken
final IAnnotationFinder delegate = FinderFactory.ModuleLimitedFinder.class.isInstance(finder) ?
FinderFactory.ModuleLimitedFinder.class.cast(finder).getDelegate() : finder;
final AnnotationFinder annotationFinder = AnnotationFinder.class.cast(delegate);
final Archive archive = annotationFinder.getArchive();
final List classes = new ArrayList(500);
if (!WebappAggregatedArchive.class.isInstance(archive)) {
return annotationFinder.getAnnotatedClassNames();
}
final WebappAggregatedArchive aggregatedArchive = (WebappAggregatedArchive) archive;
final Map> map = aggregatedArchive.getClassesMap();
for (final Map.Entry> entry : map.entrySet()) {
final URL beansXml = hasBeansXml(entry.getKey());
if (beansXml != null) {
classes.addAll(entry.getValue());
}
}
return classes;
}
public static URL hasBeansXml(final URL url) {
if (url.getPath().endsWith("WEB-INF/classes/")) {
{
final File file = new File(URLs.toFile(url).getParent(), "beans.xml");
if (file.exists()) {
try {
return file.toURI().toURL();
} catch (final MalformedURLException e) {
return url;
}
}
}
{
final File file = new File(URLs.toFile(url), "classes/beans.xml");
if (file.exists()) {
try {
return file.toURI().toURL();
} catch (final MalformedURLException e) {
return url;
}
}
}
return url;
}
if (url.getPath().endsWith("!/META-INF/beans.xml")) {
return url;
}
try {
final URLClassLoader loader = new URLClassLoader(new URL[]{url}, new EmptyResourcesClassLoader());
final String[] paths = {
"META-INF/beans.xml",
"WEB-INF/beans.xml",
"/WEB-INF/beans.xml",
"/META-INF/beans.xml",
};
for (final String path : paths) {
final URL resource = loader.findResource(path);
if (resource != null) {
return resource;
}
}
} catch (final Exception e) {
// no-op
}
return null;
}
private String getEjbName(final MessageDriven mdb, final Class> beanClass) {
return mdb.name().isEmpty() ? beanClass.getSimpleName() : mdb.name();
}
private String getEjbName(final Stateful stateful, final Class> beanClass) {
return stateful.name().isEmpty() ? beanClass.getSimpleName() : stateful.name();
}
private String getEjbName(final Stateless stateless, final Class> beanClass) {
return stateless.name().isEmpty() ? beanClass.getSimpleName() : stateless.name();
}
private String getEjbName(final Singleton singleton, final Class> beanClass) {
return singleton.name().isEmpty() ? beanClass.getSimpleName() : singleton.name();
}
private String getEjbName(final ManagedBean managed, final Class> beanClass) {
return managed.value().isEmpty() ? beanClass.getSimpleName() : managed.value();
}
private boolean isValidEjbAnnotationUsage(final Class annotationClass, final Annotated> beanClass, final String ejbName, final EjbModule ejbModule) {
final List> annotations = new ArrayList(asList(Singleton.class, Stateless.class, Stateful.class, MessageDriven.class));
annotations.remove(annotationClass);
final boolean b = true;
for (final Class extends Annotation> secondAnnotation : annotations) {
final Annotation annotation = beanClass.getAnnotation(secondAnnotation);
if (annotation == null) {
continue;
}
String secondEjbName = null;
if (annotation instanceof Stateful) {
secondEjbName = getEjbName((Stateful) annotation, beanClass.get());
} else if (annotation instanceof Stateless) {
secondEjbName = getEjbName((Stateless) annotation, beanClass.get());
} else if (annotation instanceof Singleton) {
secondEjbName = getEjbName((Singleton) annotation, beanClass.get());
} else if (annotation instanceof MessageDriven) {
secondEjbName = getEjbName((MessageDriven) annotation, beanClass.get());
}
if (ejbName.equals(secondEjbName)) {
ejbModule.getValidation().fail(ejbName, "multiplyAnnotatedAsBean", annotationClass.getSimpleName(), secondAnnotation.getSimpleName(), ejbName, beanClass.get().getName());
}
}
if (beanClass.get().isInterface()) {
if (!CheckClasses.isAbstractAllowed(beanClass.get())) {
ejbModule.getValidation().fail(ejbName, "interfaceAnnotatedAsBean", annotationClass.getSimpleName(), beanClass.get().getName());
return false;
}
} else if (Modifier.isAbstract(beanClass.get().getModifiers())) {
if (!CheckClasses.isAbstractAllowed(beanClass.get())) {
ejbModule.getValidation().fail(ejbName, "abstractAnnotatedAsBean", annotationClass.getSimpleName(), beanClass.get().getName());
return false;
}
}
return b;
}
}
@SuppressWarnings({"JavaDoc", "unchecked"})
public static class ProcessAnnotatedBeans implements DynamicDeployer {
public static final String STRICT_INTERFACE_DECLARATION = "openejb.strict.interface.declaration";
private final boolean webserviceAsRemote;
public ProcessAnnotatedBeans(final boolean wsAsRemote) {
webserviceAsRemote = wsAsRemote;
}
public void deploy(final CdiBeanInfo beanInfo) throws OpenEJBException {
final AnnotationFinder annotationFinder = createFinder(beanInfo.getBeanClass());
/*
* @EJB
* @Resource
* @WebServiceRef
* @PersistenceUnit
* @PersistenceContext
*/
buildAnnotatedRefs(beanInfo, annotationFinder, beanInfo.getClassLoader());
processWebServiceClientHandlers(beanInfo, annotationFinder, beanInfo.getClassLoader());
}
public AppModule deploy(final AppModule appModule) throws OpenEJBException {
for (final EjbModule ejbModule : appModule.getEjbModules()) {
setModule(ejbModule);
try {
deploy(ejbModule);
} finally {
removeModule();
}
}
for (final ClientModule clientModule : appModule.getClientModules()) {
setModule(clientModule);
try {
deploy(clientModule);
} finally {
removeModule();
}
}
for (final ConnectorModule connectorModule : appModule.getConnectorModules()) {
setModule(connectorModule);
try {
deploy(connectorModule);
} finally {
removeModule();
}
}
for (final WebModule webModule : appModule.getWebModules()) {
setModule(webModule);
try {
deploy(webModule);
} finally {
removeModule();
}
}
return appModule;
}
public ClientModule deploy(final ClientModule clientModule) throws OpenEJBException {
if (clientModule.getApplicationClient() != null && clientModule.getApplicationClient().isMetadataComplete()) {
return clientModule;
}
final ClassLoader classLoader = clientModule.getClassLoader();
ApplicationClient client = clientModule.getApplicationClient();
if (client == null) {
client = new ApplicationClient();
}
final Set remoteClients = new HashSet();
if (clientModule.getMainClass() != null) {
final String className = realClassName(clientModule.getMainClass());
// OPENEJB-1063: a Main-Class should use "." instead of "/"
// it wasn't check before jdk 1.5 so we can get old module with
// bad format http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4986512
// replace all "/" by "."
if (clientModule.getMainClass().contains("/")) { // className can't be null here
clientModule.setMainClass(className);
}
final Class clazz;
try {
clazz = classLoader.loadClass(className);
remoteClients.add(clazz);
final AnnotationFinder annotationFinder = createFinder(clazz);
buildAnnotatedRefs(client, annotationFinder, classLoader);
} catch (final ClassNotFoundException e) {
/**
* Some ClientModule are discovered only because the jar uses a Main-Class
* entry in the MANIFEST.MF file. Lots of jars do this that are not used as
* java ee application clients, so lets not make this a failure unless it
* has a META-INF/application-client.xml which tells us it is in fact
* expected to be a ClientModule and not just some random jar.
*/
if (clientModule.getAltDDs().containsKey("application-client.xml")) {
getValidationContext().fail("client", "client.missingMainClass", className);
} else {
getValidationContext().warn("client", "client.missingMainClass", className);
}
}
}
for (final String rawClassName : clientModule.getRemoteClients()) {
final String className = realClassName(rawClassName);
final Class clazz;
try {
clazz = classLoader.loadClass(className);
remoteClients.add(clazz);
} catch (final ClassNotFoundException e) {
throw new OpenEJBException("Unable to load RemoteClient class: " + className, e);
}
final AnnotationFinder annotationFinder = createFinder(clazz);
buildAnnotatedRefs(client, annotationFinder, classLoader);
}
for (final String rawClassName : clientModule.getLocalClients()) {
final String className = realClassName(rawClassName);
final Class clazz;
try {
clazz = classLoader.loadClass(className);
} catch (final ClassNotFoundException e) {
throw new OpenEJBException("Unable to load LocalClient class: " + className, e);
}
final AnnotationFinder annotationFinder = createFinder(clazz);
buildAnnotatedRefs(client, annotationFinder, classLoader);
}
validateRemoteClientRefs(classLoader, client, remoteClients);
final IAnnotationFinder finder = clientModule.getFinder();
if (!AnnotationFinder.class.isInstance(finder) && finder != null) {
final Class>[] loadedClasses = new Class>[finder.getAnnotatedClassNames().size()];
int i = 0;
for (final String s : finder.getAnnotatedClassNames()) {
try {
loadedClasses[i++] = classLoader.loadClass(s);
} catch (final ClassNotFoundException e) {
// no-op
}
}
clientModule.getFinderReference().set(new FinderFactory.OpenEJBAnnotationFinder(new ClassesArchive(loadedClasses)));
}
processWebServiceClientHandlers(client, AnnotationFinder.class.cast(clientModule.getFinder()), classLoader);
return clientModule;
}
private void validateRemoteClientRefs(final ClassLoader classLoader, final ApplicationClient client, final Set remoteClients) {
for (final EjbLocalRef ref : client.getEjbLocalRef()) {
for (final InjectionTarget target : ref.getInjectionTarget()) {
try {
final Class> targetClass = classLoader.loadClass(realClassName(target.getInjectionTargetClass()));
for (final Class remoteClient : remoteClients) {
if (targetClass.isAssignableFrom(remoteClient)) {
fail(remoteClient.getName(), "remoteClient.ejbLocalRef", target.getInjectionTargetClass(), target.getInjectionTargetName());
}
}
} catch (final ClassNotFoundException ignore) {
// no-op
}
}
}
for (final PersistenceContextRef ref : client.getPersistenceContextRef()) {
for (final InjectionTarget target : ref.getInjectionTarget()) {
try {
final Class> targetClass = classLoader.loadClass(realClassName(target.getInjectionTargetClass()));
for (final Class remoteClient : remoteClients) {
if (targetClass.isAssignableFrom(remoteClient)) {
fail(remoteClient.getName(), "remoteClient.persistenceContextRef", target.getInjectionTargetClass(), target.getInjectionTargetName());
}
}
} catch (final ClassNotFoundException ignore) {
// no-op
}
}
}
/* TODO: still useful?
List unusableTypes = new ArrayList(knownResourceEnvTypes);
unusableTypes.remove("javax.jms.Topic");
unusableTypes.remove("javax.jms.Queue");
for (ResourceEnvRef ref : client.getResourceEnvRef()) {
if (!unusableTypes.contains(ref.getType())) continue;
for (InjectionTarget target : ref.getInjectionTarget()) {
try {
Class> targetClass = classLoader.loadClass(target.getInjectionTargetClass());
for (Class remoteClient : remoteClients) {
if (targetClass.isAssignableFrom(remoteClient)) {
fail(remoteClient.getName(), "remoteClient.resourceEnvRef", target.getInjectionTargetClass(), target.getInjectionTargetName(), ref.getType());
}
}
} catch (ClassNotFoundException ignore) {
}
}
}
*/
}
public ConnectorModule deploy(final ConnectorModule connectorModule) throws OpenEJBException {
// resource modules currently don't have any annotations
return connectorModule;
}
/**
* Collects a list of all webapp related classes that are eligible for
* annotation processing then scans them and fills out the web.xml with
* the xml version of the annotations.
*
* @param webModule
* @return
* @throws OpenEJBException
*/
public WebModule deploy(final WebModule webModule) throws OpenEJBException {
final WebApp webApp = webModule.getWebApp();
if (webApp != null && webApp.isMetadataComplete()) {
return webModule;
}
/*
* Classes added to this set will be scanned for annotations
*/
final Set classes = new HashSet();
final ClassLoader classLoader = webModule.getClassLoader();
final String webXmlApplication = webApp.contextParamsAsMap().get("javax.ws.rs.Application");
if (webXmlApplication != null) {
webModule.getRestApplications().clear();
webModule.getRestApplications().add(webXmlApplication);
}
final Collection restApp = webModule.getRestApplications();
if (restApp.isEmpty()) {
addRestClassesToScannedClasses(webModule, classes, classLoader);
} else {
for (final String rawClassName : restApp) {
final String application = realClassName(rawClassName);
if (application != null) {
final Class> clazz;
try {
clazz = classLoader.loadClass(application);
classes.add(clazz);
} catch (final ClassNotFoundException e) {
throw new OpenEJBException("Unable to load Application class: " + application, e);
}
if (Modifier.isAbstract(clazz.getModifiers())) {
continue;
}
try {
final Application app = Application.class.cast(clazz.newInstance());
try {
final Set> appClasses = app.getClasses();
if (!appClasses.isEmpty()) {
classes.addAll(appClasses);
} else {
addRestClassesToScannedClasses(webModule, classes, classLoader);
}
} catch (final RuntimeException npe) {
if (app == null) {
throw npe;
}
// if app depends on cdi no need to do it
}
} catch (final InstantiationException e) {
throw new OpenEJBException("Unable to instantiate Application class: " + application, e);
} catch (final IllegalAccessException e) {
throw new OpenEJBException("Unable to access Application class: " + application, e);
}
}
}
}
/*
* Servlet classes are scanned
*/
for (final Servlet servlet : webApp.getServlet()) {
final String servletName = servlet.getServletName();
if ("javax.ws.rs.core.Application".equals(servletName)) {
servlet.setServletName(ProvidedJAXRSApplication.class.getName());
webModule.getRestApplications().add(ProvidedJAXRSApplication.class.getName());
for (final ServletMapping mapping : webApp.getServletMapping()) {
if (servletName.equals(mapping.getServletName())) {
mapping.setServletName(ProvidedJAXRSApplication.class.getName());
}
}
continue;
}
String servletClass = realClassName(servlet.getServletClass());
if (servletClass == null) { // try with servlet name, @see org.apache.openejb.arquillian.tests.jaxrs.basicapp.BasicApplication
servletClass = realClassName(servletName);
}
if (servletClass != null && servlet.getJspFile() == null) { // jaxrs application doesn't have a jsp file
if (!"org.apache.openejb.server.rest.OpenEJBRestServlet".equals(servletClass)) {
try {
final Class clazz = classLoader.loadClass(servletClass);
classes.add(clazz);
if (servlet.getServletClass() == null) {
servlet.setServletClass(servletClass);
}
} catch (final ClassNotFoundException e) {
if (servlet.getServletClass() != null) {
throw new OpenEJBException("Unable to load servlet class: " + servletClass, e);
} else {
logger.error("servlet " + servletName + " has no servlet-class defined and is not a subclass of Application");
}
}
}
// if the servlet is a rest init servlet don't deploy rest classes automatically
for (final ParamValue param : servlet.getInitParam()) {
if (param.getParamName().equals(Application.class.getName()) || param.getParamName().equals("javax.ws.rs.Application")) {
webModule.getRestApplications().clear();
webModule.getRestApplications().add(param.getParamValue());
break;
}
}
}
}
/*
* Filter classes are scanned
*/
for (final Filter filter : webApp.getFilter()) {
final String filterClass = realClassName(filter.getFilterClass());
if (filterClass != null) {
try {
final Class clazz = classLoader.loadClass(filterClass);
classes.add(clazz);
} catch (final ClassNotFoundException e) {
throw new OpenEJBException("Unable to load servlet filter class: " + filterClass, e);
}
}
}
/*
* Listener classes are scanned
*/
for (final Listener listener : webApp.getListener()) {
final String listenerClass = realClassName(listener.getListenerClass());
if (listenerClass != null) {
try {
final Class clazz = classLoader.loadClass(listenerClass);
classes.add(clazz);
} catch (final ClassNotFoundException e) {
throw new OpenEJBException("Unable to load servlet listener class: " + listenerClass, e);
}
}
}
for (final TldTaglib taglib : webModule.getTaglibs()) {
/*
* TagLib Listener classes are scanned
*/
for (final Listener listener : taglib.getListener()) {
final String listenerClass = realClassName(listener.getListenerClass());
if (listenerClass != null) {
try {
final Class clazz = classLoader.loadClass(listenerClass);
classes.add(clazz);
} catch (final ClassNotFoundException e) {
logger.error("Unable to load tag library servlet listener class: " + listenerClass);
}
}
}
/*
* TagLib Tag classes are scanned
*/
for (final Tag tag : taglib.getTag()) {
final String tagClass = realClassName(tag.getTagClass());
if (tagClass != null) {
try {
final Class clazz = classLoader.loadClass(tagClass);
classes.add(clazz);
} catch (final ClassNotFoundException e) {
logger.error("Unable to load tag library tag class: " + tagClass);
}
}
}
}
/*
* WebService HandlerChain classes are scanned
*/
if (webModule.getWebservices() != null) {
for (final WebserviceDescription webservice : webModule.getWebservices().getWebserviceDescription()) {
for (final PortComponent port : webservice.getPortComponent()) {
// skip ejb port defs
if (port.getServiceImplBean().getEjbLink() != null) {
continue;
}
if (port.getHandlerChains() == null) {
continue;
}
for (final org.apache.openejb.jee.HandlerChain handlerChain : port.getHandlerChains().getHandlerChain()) {
for (final Handler handler : handlerChain.getHandler()) {
final String handlerClass = realClassName(handler.getHandlerClass());
if (handlerClass != null) {
try {
final Class clazz = classLoader.loadClass(handlerClass);
classes.add(clazz);
} catch (final ClassNotFoundException e) {
throw new OpenEJBException("Unable to load webservice handler class: " + handlerClass, e);
}
}
}
}
}
}
}
/*
* JSF ManagedBean classes are scanned
*/
for (final FacesConfig facesConfig : webModule.getFacesConfigs()) {
for (final FacesManagedBean bean : facesConfig.getManagedBean()) {
final String managedBeanClass = realClassName(bean.getManagedBeanClass().trim());
if (managedBeanClass != null) {
try {
final Class clazz = classLoader.loadClass(managedBeanClass);
classes.add(clazz);
} catch (final ClassNotFoundException e) {
logger.error("Unable to load JSF managed bean class: " + managedBeanClass);
}
}
}
}
final IAnnotationFinder finder = webModule.getFinder();
if (finder != null) {
for (final String apiClassName : API_CLASSES) {
final Class extends Annotation> clazz;
try {
clazz = (Class extends Annotation>) classLoader.loadClass(apiClassName);
} catch (final ClassNotFoundException e) {
continue;
}
if (clazz.isAnnotation()) {
classes.addAll(metaToClass(finder.findMetaAnnotatedClasses(clazz)));
} else if (Modifier.isAbstract(clazz.getModifiers())) {
classes.addAll(finder.findSubclasses(clazz));
} else {
classes.addAll(finder.findImplementations(clazz));
}
}
}
final AnnotationFinder annotationFinder = createFinder(classes.toArray(new Class>[classes.size()]));
/*
* @EJB
* @Resource
* @WebServiceRef
* @PersistenceUnit
* @PersistenceContext
*/
buildAnnotatedRefs(webApp, annotationFinder, classLoader);
processWebServiceClientHandlers(webApp, annotationFinder, classLoader);
return webModule;
}
public EjbModule deploy(final EjbModule ejbModule) throws OpenEJBException {
if (ejbModule.getEjbJar() != null && ejbModule.getEjbJar().isMetadataComplete()) {
return ejbModule;
}
// Map deployments = ejbModule.getOpenejbJar().getDeploymentsByEjbName();
final ClassLoader classLoader = ejbModule.getClassLoader();
final EnterpriseBean[] enterpriseBeans = ejbModule.getEjbJar().getEnterpriseBeans();
for (final EnterpriseBean bean : enterpriseBeans) {
final String ejbName = bean.getEjbName();
final String ejbClassName = realClassName(bean.getEjbClass());
if (ejbClassName == null) {
final List others = new ArrayList();
for (final EnterpriseBean otherBean : enterpriseBeans) {
others.add(otherBean.getEjbName());
}
fail(ejbName, "xml.noEjbClass", ejbName, Join.join(", ", others));
}
final Class> clazz;
try {
clazz = classLoader.loadClass(ejbClassName);
} catch (final ClassNotFoundException e) {
// Handled in CheckClasses.java along with other missing classes
continue;
}
final MetaAnnotatedClass> metaClass = new MetaAnnotatedClass(clazz);
final boolean dynamicBean = DynamicProxyImplFactory.isKnownDynamicallyImplemented(metaClass, clazz);
AnnotationFinder finder = null; // created lazily since not always needed
final AnnotationFinder annotationFinder;
if (ejbModule.getFinder() instanceof AnnotationFinder) {
final AnnotationFinder af = (AnnotationFinder) ejbModule.getFinder();
final List> ancestors = Classes.ancestors(clazz);
ancestors.addAll(asList(clazz.getInterfaces()));
if (dynamicBean) {
final Proxy p = metaClass.getAnnotation(Proxy.class);
if (p != null) {
ancestors.add(p.value());
}
}
final String[] names = new String[ancestors.size()];
int i = 0;
for (final Class> ancestor : ancestors) {
names[i++] = ancestor.getName();
}
annotationFinder = af.select(names);
} else { // shouldn't occur
if (!dynamicBean) {
annotationFinder = createFinder(clazz);
} else {
final Class>[] classes;
final Proxy proxy = metaClass.getAnnotation(Proxy.class);
if (proxy == null) {
classes = new Class>[]{clazz};
} else {
classes = new Class>[]{clazz, proxy.value()};
}
annotationFinder = createFinder(classes);
}
}
/*
* @PostConstruct
* @PreDestroy
* @AroundInvoke
* @Timeout
* @PostActivate
* @PrePassivate
* @Init
* @Remove
* @AroundTimeout
* @AfterBegin
* @BeforeCompletion
* @AfterCompletion
*/
processCallbacks(bean, annotationFinder);
/*
* @TransactionManagement
*/
if (bean.getTransactionType() == null) {
final TransactionManagement tx = getInheritableAnnotation(clazz, TransactionManagement.class);
TransactionManagementType transactionType = TransactionManagementType.CONTAINER;
if (tx != null) {
transactionType = tx.value();
}
switch (transactionType) {
case BEAN:
bean.setTransactionType(TransactionType.BEAN);
break;
case CONTAINER:
bean.setTransactionType(TransactionType.CONTAINER);
break;
}
}
final AssemblyDescriptor assemblyDescriptor = ejbModule.getEjbJar().getAssemblyDescriptor();
/*
* @ApplicationException
*/
processApplicationExceptions(clazz, assemblyDescriptor);
/*
* TransactionAttribute
*/
if (bean.getTransactionType() == TransactionType.CONTAINER) {
processAttributes(new TransactionAttributeHandler(assemblyDescriptor, ejbName), clazz, annotationFinder);
} else {
if (finder == null) {
finder = annotationFinder.select(clazz.getName());
}
checkAttributes(new TransactionAttributeHandler(assemblyDescriptor, ejbName), ejbName, ejbModule, finder, "invalidTransactionAttribute");
}
/*
* @RolesAllowed
* @PermitAll
* @DenyAll
* @RunAs
* @DeclareRoles
*/
processSecurityAnnotations(clazz, ejbName, ejbModule, annotationFinder, bean);
/*
* @Schedule
* @Schedules
*/
processSchedules(bean, annotationFinder);
/*
* Add any interceptors they may have referenced in xml but did not declare
*/
for (final InterceptorBinding binding : assemblyDescriptor.getInterceptorBinding()) {
final EjbJar ejbJar = ejbModule.getEjbJar();
final List list = new ArrayList(binding.getInterceptorClass());
if (binding.getInterceptorOrder() != null) {
list.clear();
list.addAll(binding.getInterceptorOrder().getInterceptorClass());
}
for (final String interceptor : list) {
if (ejbJar.getInterceptor(interceptor) == null) {
logger.debug("Adding '' entry for undeclared interceptor " + interceptor);
ejbJar.addInterceptor(new Interceptor(interceptor));
}
}
}
/*
* @Interceptors
*/
final List>> annotatedClasses = sortClasses(annotationFinder.findMetaAnnotatedClasses(Interceptors.class));
for (final Annotated> interceptorsAnnotatedClass : annotatedClasses) {
final Interceptors interceptors = interceptorsAnnotatedClass.getAnnotation(Interceptors.class);
final EjbJar ejbJar = ejbModule.getEjbJar();
for (final Class interceptor : interceptors.value()) {
if (ejbJar.getInterceptor(interceptor.getName()) == null) {
ejbJar.addInterceptor(new Interceptor(interceptor.getName()));
}
}
final InterceptorBinding binding = new InterceptorBinding(bean);
assemblyDescriptor.getInterceptorBinding().add(0, binding);
for (final Class interceptor : interceptors.value()) {
binding.getInterceptorClass().add(interceptor.getName());
}
}
final List> annotatedMethods = sortMethods(annotationFinder.findMetaAnnotatedMethods(Interceptors.class));
for (final Annotated method : annotatedMethods) {
final Interceptors interceptors = method.getAnnotation(Interceptors.class);
if (interceptors != null) {
final EjbJar ejbJar = ejbModule.getEjbJar();
for (final Class interceptor : interceptors.value()) {
if (ejbJar.getInterceptor(interceptor.getName()) == null) {
ejbJar.addInterceptor(new Interceptor(interceptor.getName()));
}
}
final InterceptorBinding binding = new InterceptorBinding(bean);
assemblyDescriptor.getInterceptorBinding().add(0, binding);
for (final Class interceptor : interceptors.value()) {
binding.getInterceptorClass().add(interceptor.getName());
}
binding.setMethod(new NamedMethod(method.get()));
}
}
/*
* @ExcludeDefaultInterceptors
*/
final ExcludeDefaultInterceptors excludeDefaultInterceptors = clazz.getAnnotation(ExcludeDefaultInterceptors.class);
if (excludeDefaultInterceptors != null) {
final InterceptorBinding binding = assemblyDescriptor.addInterceptorBinding(new InterceptorBinding(bean));
binding.setExcludeDefaultInterceptors(true);
}
for (final Annotated method : annotationFinder.findMetaAnnotatedMethods(ExcludeDefaultInterceptors.class)) {
final InterceptorBinding binding = assemblyDescriptor.addInterceptorBinding(new InterceptorBinding(bean));
binding.setExcludeDefaultInterceptors(true);
binding.setMethod(new NamedMethod(method.get()));
}
for (final Annotated method : sortMethods(annotationFinder.findMetaAnnotatedMethods(ExcludeClassInterceptors.class))) {
final InterceptorBinding binding = assemblyDescriptor.addInterceptorBinding(new InterceptorBinding(bean));
binding.setExcludeClassInterceptors(true);
binding.setMethod(new NamedMethod(method.get()));
}
/**
* All beans except MDBs have remoting capabilities (busines or legacy interfaces)
*/
if (bean instanceof RemoteBean) {
final RemoteBean remoteBean = (RemoteBean) bean;
/*
* @RemoteHome
*/
if (remoteBean.getHome() == null) {
final RemoteHome remoteHome = getInheritableAnnotation(clazz, RemoteHome.class);
if (remoteHome != null) {
final Class> homeClass = remoteHome.value();
try {
Method create = null;
for (final Method method : homeClass.getMethods()) {
if (method.getName().startsWith("create")) {
create = method;
break;
}
}
if (create == null) {
throw new NoSuchMethodException("create");
}
final Class> remoteClass = create.getReturnType();
remoteBean.setHome(homeClass.getName());
remoteBean.setRemote(remoteClass.getName());
} catch (final NoSuchMethodException e) {
logger.error("Class annotated as a RemoteHome has no 'create()' method. Unable to determine remote interface type. Bean class: " + clazz.getName() + ", Home class: " + homeClass.getName());
}
}
}
/*
* @LocalHome
*/
if (remoteBean.getLocalHome() == null) {
final LocalHome localHome = getInheritableAnnotation(clazz, LocalHome.class);
if (localHome != null) {
final Class> homeClass = localHome.value();
try {
Method create = null;
for (final Method method : homeClass.getMethods()) {
if (method.getName().startsWith("create")) {
create = method;
break;
}
}
if (create == null) {
throw new NoSuchMethodException("create");
}
final Class> remoteClass = create.getReturnType();
remoteBean.setLocalHome(homeClass.getName());
remoteBean.setLocal(remoteClass.getName());
} catch (final NoSuchMethodException e) {
logger.error("Class annotated as a LocalHome has no 'create()' method. Unable to determine remote interface type. Bean class: " + clazz.getName() + ", Home class: " + homeClass.getName());
}
}
}
/*
* Annotations specific to @Stateless, @Stateful and @Singleton beans
*/
if (remoteBean instanceof SessionBean) {
final SessionBean sessionBean = (SessionBean) remoteBean;
// add parents
sessionBean.getParents().add(clazz.getName());
if (!clazz.isInterface()) {
for (Class> current = clazz.getSuperclass(); !current.equals(Object.class); current = current.getSuperclass()) {
sessionBean.getParents().add(current.getName());
}
}
/*
* @Remote
* @Local
* @WebService
* @WebServiceProvider
*/
processSessionInterfaces(sessionBean, clazz, ejbModule);
/*
* @Asynchronous
*/
processAsynchronous(bean, annotationFinder);
/*
* Allow for all session bean types
* @DependsOn
*/
if (sessionBean.getDependsOn() == null) {
final DependsOn dependsOn = getInheritableAnnotation(clazz, DependsOn.class);
if (dependsOn != null) {
sessionBean.setDependsOn(dependsOn.value());
} else {
sessionBean.setDependsOn(Collections.EMPTY_LIST);
}
}
/**
* Annotations for singletons and stateless
*/
if (sessionBean.getSessionType() != SessionType.STATEFUL) {
// REST can be fun
if (annotationFinder.isAnnotationPresent(Path.class)) {
sessionBean.setRestService(true);
}
}
/*
* Annotations specific to @Singleton beans
*/
if (sessionBean.getSessionType() == SessionType.SINGLETON) {
/*
* @ConcurrencyManagement
*/
if (sessionBean.getConcurrencyManagementType() == null) {
final ConcurrencyManagement tx = getInheritableAnnotation(clazz, ConcurrencyManagement.class);
javax.ejb.ConcurrencyManagementType concurrencyType = javax.ejb.ConcurrencyManagementType.CONTAINER;
if (tx != null) {
concurrencyType = tx.value();
}
switch (concurrencyType) {
case BEAN:
sessionBean.setConcurrencyManagementType(ConcurrencyManagementType.BEAN);
break;
case CONTAINER:
sessionBean.setConcurrencyManagementType(ConcurrencyManagementType.CONTAINER);
break;
}
}
/*
* @Lock
*/
final LockHandler lockHandler = new LockHandler(assemblyDescriptor, sessionBean);
if (sessionBean.getConcurrencyManagementType() == ConcurrencyManagementType.CONTAINER) {
processAttributes(lockHandler, clazz, annotationFinder);
} else {
checkAttributes(lockHandler, ejbName, ejbModule, annotationFinder, "invalidConcurrencyAttribute");
}
/*
* @AccessTimeout
*/
final AccessTimeoutHandler accessTimeoutHandler =
new AccessTimeoutHandler(assemblyDescriptor, sessionBean, lockHandler.getContainerConcurrency());
processAttributes(accessTimeoutHandler, clazz, annotationFinder);
/*
* @Startup
*/
if (!sessionBean.hasInitOnStartup()) {
final Startup startup = getInheritableAnnotation(clazz, Startup.class);
sessionBean.setInitOnStartup(startup != null);
}
} else if (sessionBean.getSessionType() == SessionType.STATEFUL) {
/*
* Annotations specific to @Stateful beans
*/
/*
* @StatefulTimeout
*/
if (sessionBean.getStatefulTimeout() == null) {
final StatefulTimeout annotation = getInheritableAnnotation(clazz, StatefulTimeout.class);
if (annotation != null) {
final Timeout timeout = new Timeout();
timeout.setTimeout(annotation.value());
timeout.setUnit(annotation.unit());
sessionBean.setStatefulTimeout(timeout);
}
}
/*
* @AccessTimeout
*/
final AccessTimeoutHandler accessTimeoutHandler = new AccessTimeoutHandler(assemblyDescriptor, sessionBean);
processAttributes(accessTimeoutHandler, clazz, annotationFinder);
}
}
}
if (bean instanceof MessageDrivenBean) {
/*
* @ActivationConfigProperty
*/
final MessageDrivenBean mdb = (MessageDrivenBean) bean;
final MessageDriven messageDriven = clazz.getAnnotation(MessageDriven.class);
if (messageDriven != null) {
ActivationConfig activationConfig = mdb.getActivationConfig();
if (activationConfig == null) {
activationConfig = new ActivationConfig();
}
if (!messageDriven.mappedName().isEmpty()) {
if (mdb.getActivationConfig() == null) {
mdb.setActivationConfig(activationConfig);
}
if (!activationConfig.toProperties().containsKey("destinationType")) {
activationConfig.addProperty("destinationType", Queue.class.getName());
}
activationConfig.addProperty("destination", messageDriven.mappedName());
}
final ActivationConfigProperty[] configProperties = messageDriven.activationConfig();
if (configProperties != null) {
if (mdb.getActivationConfig() == null) {
mdb.setActivationConfig(activationConfig);
}
final Properties properties = activationConfig.toProperties();
for (final ActivationConfigProperty property : configProperties) {
if (!properties.containsKey(property.propertyName())) {
activationConfig.addProperty(property.propertyName(), property.propertyValue());
}
}
}
if (mdb.getMessagingType() == null) {
final Class> interfce = messageDriven.messageListenerInterface();
if (interfce != null && !interfce.equals(Object.class)) {
if (!interfce.isInterface()) {
// TODO: Move this check to o.a.o.c.rules.CheckClasses and do it for all MDBs, annotated or not
throw new OpenEJBException("MessageListenerInterface property of @MessageDriven is not an interface");
}
mdb.setMessagingType(interfce.getName());
}
}
}
/*
* Determine the MessageListener interface
*/
if (mdb.getMessagingType() == null) {
final List> interfaces = new ArrayList>();
for (final Class> intf : clazz.getInterfaces()) {
final String name = intf.getName();
if (!name.equals("java.io.Serializable") &&
!name.equals("java.io.Externalizable") &&
!name.startsWith("javax.ejb.") &&
!intf.isSynthetic()) {
interfaces.add(intf);
}
}
if (interfaces.size() != 1) {
String msg = "When annotating a bean class as @MessageDriven without declaring messageListenerInterface, the bean must implement exactly one interface, no more and no less. beanClass=" + clazz.getName() + " interfaces=";
for (final Class> intf : interfaces) {
msg += intf.getName() + ", ";
}
// TODO: Make this a validation failure, not an exception
throw new IllegalStateException(msg);
}
mdb.setMessagingType(interfaces.get(0).getName());
}
}
buildAnnotatedRefs(bean, annotationFinder, classLoader);
processWebServiceHandlers(ejbModule, bean, annotationFinder);
processWebServiceClientHandlers(bean, annotationFinder, classLoader);
try {
if (BeanContext.Comp.class.getName().equals(bean.getEjbClass())) {
buildAnnotatedRefs(bean, ejbModule.getFinder(), classLoader);
}
} catch (final OpenEJBException e) {
logger.error("Processing of @Resource, @EJB, and other references failed for CDI managed beans", e);
}
}
for (final Interceptor interceptor : ejbModule.getEjbJar().getInterceptors()) {
final Class> clazz;
try {
clazz = classLoader.loadClass(realClassName(interceptor.getInterceptorClass()));
} catch (final ClassNotFoundException e) {
throw new OpenEJBException("Unable to load interceptor class: " + interceptor.getInterceptorClass(), e);
}
final AnnotationFinder annotationFinder = createFinder(clazz);
/*
* @PostConstruct
* @PreDestroy
* @AroundInvoke
* @Timeout
* @PostActivate
* @PrePassivate
* @Init
* @Remove
*/
processCallbacks(interceptor, annotationFinder);
/*
* @ApplicationException
*/
processApplicationExceptions(clazz, ejbModule.getEjbJar().getAssemblyDescriptor());
/*
* @EJB
* @Resource
* @WebServiceRef
* @PersistenceUnit
* @PersistenceContext
*/
buildAnnotatedRefs(interceptor, annotationFinder, classLoader);
processWebServiceClientHandlers(interceptor, annotationFinder, classLoader);
/**
* Interceptors do not have their own section in ejb-jar.xml for resource references
* so we add them to the references of each ejb. A bit backwards but more or less
* mandated by the design of the spec.
*/
for (final EnterpriseBean bean : enterpriseBeans) {
// Just simply merge the injection targets of the interceptors to enterprise beans
mergeJndiReferences(interceptor.getEnvEntryMap(), bean.getEnvEntryMap());
mergeJndiReferences(interceptor.getEjbRefMap(), bean.getEjbRefMap());
mergeJndiReferences(interceptor.getEjbLocalRefMap(), bean.getEjbLocalRefMap());
mergeJndiReferences(interceptor.getResourceRefMap(), bean.getResourceRefMap());
mergeJndiReferences(interceptor.getResourceEnvRefMap(), bean.getResourceEnvRefMap());
mergeJndiReferences(interceptor.getPersistenceContextRefMap(), bean.getPersistenceContextRefMap());
mergeJndiReferences(interceptor.getPersistenceUnitRefMap(), bean.getPersistenceUnitRefMap());
mergeJndiReferences(interceptor.getMessageDestinationRefMap(), bean.getMessageDestinationRefMap());
mergeJndiReferences(interceptor.getServiceRefMap(), bean.getServiceRefMap());
}
}
return ejbModule;
}
private void processAsynchronous(final EnterpriseBean bean, final AnnotationFinder annotationFinder) {
if (!(bean instanceof SessionBean)) {
return;
}
final SessionBean sessionBean = (SessionBean) bean;
for (final Annotated method : annotationFinder.findMetaAnnotatedMethods(Asynchronous.class)) {
sessionBean.getAsyncMethod().add(new AsyncMethod(method.get()));
}
//Spec 4.5.1 @Asynchronous could be used at the class level of a bean-class ( or superclass ).
//Seems that it should not be used on the any interface view
for (final Annotated> clazz : annotationFinder.findMetaAnnotatedClasses(Asynchronous.class)) {
if (!clazz.get().isInterface()) {
sessionBean.getAsynchronousClasses().add(clazz.get().getName());
}
}
}
private void mergeJndiReferences(final Map from, final Map to) {
for (final Map.Entry entry : from.entrySet()) {
final Injectable injectable = to.get(entry.getKey());
if (injectable == null) {
to.put(entry.getKey(), entry.getValue());
} else {
injectable.getInjectionTarget().addAll(entry.getValue().getInjectionTarget());
}
}
}
//TODO why is this necessary, we scan for exceptions with this annotation elsewhere.
private void processApplicationExceptions(final Class> clazz, final AssemblyDescriptor assemblyDescriptor) {
/*
* @ApplicationException
*/
for (final Method method : clazz.getMethods()) {
for (final Class> exception : method.getExceptionTypes()) {
final ApplicationException annotation = exception.getAnnotation(ApplicationException.class);
if (annotation == null) {
continue;
}
if (assemblyDescriptor.getApplicationException(exception) != null) {
mergeApplicationExceptionAnnotation(assemblyDescriptor, exception, annotation);
} else {
logger.debug("Found previously undetected application exception {0} listed on a method {1} with annotation {2}", method, exception, annotation);
assemblyDescriptor.addApplicationException(exception, annotation.rollback(), annotation.inherited());
}
}
}
}
private void processSessionInterfaces(final SessionBean sessionBean, final Class> beanClass, final EjbModule ejbModule) {
final ValidationContext validation = ejbModule.getValidation();
final String ejbName = sessionBean.getEjbName();
final boolean strict = getProperty(STRICT_INTERFACE_DECLARATION, "false").equalsIgnoreCase("true");
/*
* Collect all interfaces explicitly declared via xml.
* We will subtract these from the interfaces implemented
* by the bean and do annotation scanning on the remainder.
*/
final List descriptor = new ArrayList();
descriptor.add(sessionBean.getHome());
descriptor.add(sessionBean.getRemote());
descriptor.add(sessionBean.getLocalHome());
descriptor.add(sessionBean.getLocal());
descriptor.addAll(sessionBean.getBusinessLocal());
descriptor.addAll(sessionBean.getBusinessRemote());
descriptor.add(sessionBean.getServiceEndpoint());
final BusinessInterfaces xml = new BusinessInterfaces();
xml.addLocals(sessionBean.getBusinessLocal(), ejbModule.getClassLoader());
xml.addRemotes(sessionBean.getBusinessRemote(), ejbModule.getClassLoader());
if (beanClass.getAnnotation(LocalBean.class) != null) {
sessionBean.setLocalBean(new Empty());
}
/**
* Anything declared as both and is invalid in strict mode
*/
if (strict) {
for (final Class interfce : xml.local) {
if (xml.remote.contains(interfce)) {
validation.fail(ejbName, "xml.localRemote.conflict", interfce.getName());
}
}
}
/**
* Merge the xml declared business interfaces into the complete set
*/
final BusinessInterfaces all = new BusinessInterfaces();
all.local.addAll(xml.local);
all.remote.addAll(xml.remote);
final List> classes = strict ? new ArrayList(asList(beanClass)) : Classes.ancestors(beanClass);
for (final Class> clazz : classes) {
/*
* @WebService
* @WebServiceProvider
*/
Class> webServiceItf = null;
if (sessionBean.getServiceEndpoint() == null) {
Class defaultEndpoint = BeanContext.ServiceEndpoint.class;
for (final Class interfce : clazz.getInterfaces()) {
if (interfce.isAnnotationPresent(WebService.class)) {
defaultEndpoint = interfce;
webServiceItf = interfce;
}
}
final WebService webService = clazz.getAnnotation(WebService.class);
if (webService != null) {
final String className = webService.endpointInterface();
if (!className.equals("")) {
sessionBean.setServiceEndpoint(className);
} else {
sessionBean.setServiceEndpoint(defaultEndpoint.getName());
}
} else if (clazz.isAnnotationPresent(WebServiceProvider.class)) {
sessionBean.setServiceEndpoint(defaultEndpoint.getName());
} else if (!defaultEndpoint.equals(BeanContext.ServiceEndpoint.class)) {
sessionBean.setServiceEndpoint(defaultEndpoint.getName());
}
}
/*
* These interface types are not eligable to be business interfaces.
* java.io.Serializable
* java.io.Externalizable
* javax.ejb.*
*/
final List> interfaces = new ArrayList>();
if (!clazz.isInterface()) { // dynamic proxy implementation
for (final Class> interfce : clazz.getInterfaces()) {
final String name = interfce.getName();
if (!name.equals("scala.ScalaObject") &&
!name.equals("groovy.lang.GroovyObject") &&
!name.equals("java.io.Serializable") &&
!name.equals("java.io.Externalizable") &&
!(name.equals(InvocationHandler.class.getName()) && DynamicSubclass.isDynamic(beanClass)) &&
!name.startsWith("javax.ejb.") &&
!descriptor.contains(interfce.getName()) &&
!interfce.isSynthetic() &&
!"net.sourceforge.cobertura.coveragedata.HasBeenInstrumented".equals(name) &&
!name.startsWith("org.scalatest.")) {
interfaces.add(interfce);
}
}
}
/**
* Anything discovered and delcared in a previous loop
* or at the beginning in the deployment descriptor is
* not eligable to be redefined.
*/
interfaces.removeAll(all.local);
interfaces.removeAll(all.remote);
/**
* OK, now start checking the class metadata
*/
final Local local = clazz.getAnnotation(Local.class);
final Remote remote = clazz.getAnnotation(Remote.class);
final boolean impliedLocal = local != null && local.value().length == 0;
final boolean impliedRemote = remote != null && remote.value().length == 0;
/**
* This set holds the values of @Local and @Remote
* when applied to the bean class itself
*
* These declarations override any similar declaration
* on the interface.
*/
final BusinessInterfaces bean = new BusinessInterfaces();
if (local != null) {
bean.local.addAll(asList(local.value()));
}
if (remote != null) {
bean.remote.addAll(asList(remote.value()));
}
if (strict) {
for (final Class interfce : bean.local) {
if (bean.remote.contains(interfce)) {
validation.fail(ejbName, "ann.localRemote.conflict", interfce.getName());
}
}
}
/**
* Anything listed explicitly via @Local or @Remote
* on the bean class does not need to be investigated.
* We do not need to check these interfaces for @Local or @Remote
*/
interfaces.removeAll(bean.local);
interfaces.removeAll(bean.remote);
if (impliedLocal || impliedRemote) {
if (interfaces.size() != 1) {
/**
* Cannot imply either @Local or @Remote and list multiple interfaces
*/
// Need to extract the class names and append .class to them to show proper validation level 3 message
final List interfaceNames = new ArrayList();
for (final Class> intrfce : interfaces) {
interfaceNames.add(intrfce.getName() + ".class");
}
// just warn for @Local since Glassfish supports it even if it is weird
// still fail for @Remote!
if (impliedLocal && local.value().length == 0 && interfaces.size() == 0 && !strict) {
validation.warn(ejbName, "ann.local.forLocalBean", Join.join(", ", interfaceNames));
// we don't go out to let be deployed
} else if (impliedLocal) {
validation.fail(ejbName, "ann.local.noAttributes", Join.join(", ", interfaceNames));
/**
* This bean is invalid, so do not bother looking at the other interfaces or the superclass
*/
return;
}
if (impliedRemote) {
validation.fail(ejbName, "ann.remote.noAttributes", Join.join(", ", interfaceNames));
/**
* This bean is invalid, so do not bother looking at the other interfaces or the superclass
*/
return;
}
} else if (strict && impliedLocal && impliedRemote) {
final Class> interfce = interfaces.remove(0);
/**
* Cannot imply @Local and @Remote at the same time with strict mode on
*/
validation.fail(ejbName, "ann.localRemote.ambiguous", interfce.getName());
} else {
if (impliedLocal) {
bean.local.addAll(interfaces);
}
if (impliedRemote) {
bean.remote.addAll(interfaces);
}
interfaces.clear();
}
}
/**
* OK, now start checking the metadata of the interfaces implemented by this class
*/
/**
* This set holds the list of interfaces that the bean implements
* that are annotated either as @Local or @Remote
*
* If the interface is annotated to the contrary in the bean class
* the bean class meta data wins, therefore we track these separately
*
* Ultimately, the deployment descriptor wins over all, so we have tracked
* those declarations separately as well.
*/
final BusinessInterfaces implemented = new BusinessInterfaces();
for (final Class interfce : interfaces) {
final boolean isLocal = interfce.isAnnotationPresent(Local.class);
final boolean isRemote = interfce.isAnnotationPresent(Remote.class);
if (strict && isLocal && isRemote) {
validation.fail(ejbName, "ann.localRemote.conflict", interfce.getName());
} else {
final Class[] superInterface = interfce.getInterfaces();
if (isLocal) {
if (strict) {
for (final Class si : superInterface) {
final boolean present = si.isAnnotationPresent(Remote.class);
if (present) {
validation.fail(ejbName, "ann.remoteOrLocal.converse.parent", interfce.getName(), "Local", si.getName(), "Remote");
}
}
}
implemented.local.add(interfce);
}
if (isRemote) {
if (strict) {
for (final Class si : superInterface) {
final boolean present = si.isAnnotationPresent(Local.class);
if (present) {
validation.fail(ejbName, "ann.remoteOrLocal.converse.parent", interfce.getName(), "Remote", si.getName(), "Local");
}
}
}
implemented.remote.add(interfce);
}
}
}
interfaces.removeAll(implemented.local);
interfaces.removeAll(implemented.remote);
/**
* Merge in class-level metadata.
*
* We've already merged in the xml metadata, so that
* metadata will win over this metadata.
*/
// remove anything we've already seen
bean.local.removeAll(all.local);
bean.local.removeAll(all.remote);
bean.remote.removeAll(all.remote);
bean.remote.removeAll(all.local);
// validate the things we are going to add
for (final Class interfce : bean.local) {
validateLocalInterface(interfce, validation, ejbName);
}
for (final Class interfce : bean.remote) {
validateRemoteInterface(interfce, validation, ejbName);
}
// add finally, add them
all.local.addAll(bean.local);
all.remote.addAll(bean.remote);
/**
* Merge in interface-level metadata
*
* We've already merged in the xml metadata *and* class metadata,
* so both of those will win over this metadata.
*/
// remove anything we've already seen
implemented.local.removeAll(all.local);
implemented.local.removeAll(all.remote);
implemented.remote.removeAll(all.remote);
implemented.remote.removeAll(all.local);
// validate the things we are going to add
for (final Class interfce : implemented.local) {
validateLocalInterface(interfce, validation, ejbName);
}
for (final Class interfce : implemented.remote) {
validateRemoteInterface(interfce, validation, ejbName);
}
// add the rest
all.local.addAll(implemented.local);
all.remote.addAll(implemented.remote);
// We only consider the top-most class (the bean class itself) when evaluating
// the case of absolutely no metadata at all and attempting to figure out the
// default view which will be implied as either @LocalBean or @Local
if (clazz == beanClass
&& sessionBean.getLocalBean() == null
&& sessionBean.getBusinessLocal().isEmpty()
&& sessionBean.getBusinessRemote().isEmpty()
&& sessionBean.getHome() == null
&& sessionBean.getRemote() == null
&& sessionBean.getLocalHome() == null
&& sessionBean.getLocal() == null
&& all.local.isEmpty()
&& all.remote.isEmpty()
) {
if (interfaces.size() == 0 || DynamicProxyImplFactory.isKnownDynamicallyImplemented(new MetaAnnotatedClass(clazz), clazz)) {
// No interfaces? Then @LocalBean
sessionBean.setLocalBean(new Empty());
} else if (interfaces.size() == 1) {
// One interface? Then @Local
all.local.add(interfaces.remove(0));
} else {
// Multiple interfaces? Illegal
validation.fail(ejbName, "too.many.interfaces", ejbName, interfaces.toString().replace("interface ", ""));
return;
}
}
// do it here to not loose the @Local handling (if (interfaces.size() == 1))
if (webserviceAsRemote
&& webServiceItf != null
&& all.remote.isEmpty()) {
all.remote.add(webServiceItf);
}
//alway set Local View for ManagedBean
if (beanClass.isAnnotationPresent(ManagedBean.class)) {
sessionBean.setLocalBean(new Empty());
}
}
// Finally, add all the business interfaces we found
for (final Class interfce : all.local) {
sessionBean.addBusinessLocal(interfce);
}
for (final Class interfce : all.remote) {
sessionBean.addBusinessRemote(interfce);
}
}
private static class BusinessInterfaces {
private final Set local = new LinkedHashSet();
private final Set remote = new LinkedHashSet();
public void addLocals(final Collection names, final ClassLoader loader) {
add(loader, names, local);
}
public void addRemotes(final Collection names, final ClassLoader loader) {
add(loader, names, remote);
}
private void add(final ClassLoader loader, final Collection names, final Set classes) {
for (final String className : names) {
try {
classes.add(loader.loadClass(realClassName(className)));
} catch (final Throwable t) {
// handled in validation
}
}
}
}
private String getProperty(final String key, final String defaultValue) {
String value = SystemInstance.get().getOptions().get(key, defaultValue);
final DeploymentModule module = getModule();
if (module instanceof EjbModule) {
final EjbModule ejbModule = (EjbModule) module;
final OpenejbJar openejbJar = ejbModule.getOpenejbJar();
if (openejbJar != null && openejbJar.getProperties() != null) {
value = openejbJar.getProperties().getProperty(key, value);
}
}
return value;
}
private void processSecurityAnnotations(final Class> beanClass, final String ejbName, final EjbModule ejbModule, final AnnotationFinder annotationFinder, final EnterpriseBean bean) {
final AssemblyDescriptor assemblyDescriptor = ejbModule.getEjbJar().getAssemblyDescriptor();
final List classPermissions = getDeclaredClassPermissions(assemblyDescriptor, ejbName);
for (final Class> clazzz : Classes.ancestors(beanClass)) {
final MetaAnnotatedClass> clazz = new MetaAnnotatedClass(clazzz);
/*
* Process annotations at the class level
*/
if (!classPermissions.contains("*") || !classPermissions.contains(clazz.getName())) {
final RolesAllowed rolesAllowed = clazz.getAnnotation(RolesAllowed.class);
final PermitAll permitAll = clazz.getAnnotation(PermitAll.class);
final DenyAll denyAll = clazz.getAnnotation(DenyAll.class);
/*
* @RolesAllowed
*/
if ((rolesAllowed != null && permitAll != null)
|| (rolesAllowed != null && denyAll != null)
|| (permitAll != null && denyAll != null)) {
ejbModule.getValidation().fail(ejbName, "permitAllAndRolesAllowedOnClass", clazz.getName());
}
if (rolesAllowed != null) {
final MethodPermission methodPermission = new MethodPermission();
methodPermission.getRoleName().addAll(asList(rolesAllowed.value()));
methodPermission.getMethod().add(new org.apache.openejb.jee.Method(ejbName, clazz.getName(), "*"));
assemblyDescriptor.getMethodPermission().add(methodPermission);
// Automatically add a role ref for any role listed in RolesAllowed
if (RemoteBean.class.isInstance(bean)) {
final RemoteBean remoteBean = RemoteBean.class.cast(bean);
final List securityRoleRefs = remoteBean.getSecurityRoleRef();
for (final String role : rolesAllowed.value()) {
securityRoleRefs.add(new SecurityRoleRef(role));
}
}
}
/*
* @PermitAll
*/
if (permitAll != null) {
final MethodPermission methodPermission = new MethodPermission();
methodPermission.setUnchecked(true);
methodPermission.getMethod().add(new org.apache.openejb.jee.Method(ejbName, clazz.getName(), "*"));
assemblyDescriptor.getMethodPermission().add(methodPermission);
}
/**
* @DenyAll
*/
if (denyAll != null) {
assemblyDescriptor.getExcludeList()
.addMethod(new org.apache.openejb.jee.Method(ejbName, clazz.getName(), "*"));
}
}
/*
* @RunAs
*/
final RunAs runAs = clazz.getAnnotation(RunAs.class);
if (runAs != null && bean.getSecurityIdentity() == null) {
final SecurityIdentity securityIdentity = new SecurityIdentity();
securityIdentity.setRunAs(runAs.value());
bean.setSecurityIdentity(securityIdentity);
}
/*
* @DeclareRoles
*/
final DeclareRoles declareRoles = clazz.getAnnotation(DeclareRoles.class);
if (declareRoles != null && bean instanceof RemoteBean) {
final RemoteBean remoteBean = (RemoteBean) bean;
final List securityRoleRefs = remoteBean.getSecurityRoleRef();
for (final String role : declareRoles.value()) {
securityRoleRefs.add(new SecurityRoleRef(role));
}
}
}
/*
* Process annotations at the method level
*/
final List seen = new ArrayList();
/*
* @RolesAllowed
*/
for (final Annotated method : annotationFinder.findMetaAnnotatedMethods(RolesAllowed.class)) {
checkConflictingSecurityAnnotations(method, ejbName, ejbModule, seen);
final RolesAllowed rolesAllowed = method.getAnnotation(RolesAllowed.class);
final MethodPermission methodPermission = new MethodPermission();
methodPermission.getRoleName().addAll(asList(rolesAllowed.value()));
methodPermission.getMethod().add(new org.apache.openejb.jee.Method(ejbName, method.get()));
assemblyDescriptor.getMethodPermission().add(methodPermission);
// Automatically add a role ref for any role listed in RolesAllowed
if (RemoteBean.class.isInstance(bean)) {
final RemoteBean remoteBean = RemoteBean.class.cast(bean);
final List securityRoleRefs = remoteBean.getSecurityRoleRef();
for (final String role : rolesAllowed.value()) {
securityRoleRefs.add(new SecurityRoleRef(role));
}
}
}
/*
* @PermitAll
*/
for (final Annotated method : annotationFinder.findMetaAnnotatedMethods(PermitAll.class)) {
checkConflictingSecurityAnnotations(method, ejbName, ejbModule, seen);
final MethodPermission methodPermission = new MethodPermission();
methodPermission.setUnchecked(true);
methodPermission.getMethod().add(new org.apache.openejb.jee.Method(ejbName, method.get()));
assemblyDescriptor.getMethodPermission().add(methodPermission);
}
/*
* @DenyAll
*/
for (final Annotated method : annotationFinder.findMetaAnnotatedMethods(DenyAll.class)) {
checkConflictingSecurityAnnotations(method, ejbName, ejbModule, seen);
final ExcludeList excludeList = assemblyDescriptor.getExcludeList();
excludeList.addMethod(new org.apache.openejb.jee.Method(ejbName, method.get()));
}
}
/**
* Validation
*
* Conflicting use of @RolesAllowed, @PermitAll, and @DenyAll
*
* @param method
* @param ejbName
* @param ejbModule
* @param seen
*/
private void checkConflictingSecurityAnnotations(final Annotated method, final String ejbName, final EjbModule ejbModule, final List seen) {
if (seen.contains(method.get())) {
return;
} else {
seen.add(method.get());
}
final List annotations = new ArrayList();
for (final Class extends Annotation> annotation : asList(RolesAllowed.class, PermitAll.class, DenyAll.class)) {
if (method.getAnnotation(annotation) != null) {
annotations.add("@" + annotation.getSimpleName());
}
}
if (annotations.size() > 1) {
ejbModule.getValidation().fail(ejbName, "conflictingSecurityAnnotations", method.get().getName(), Join.join(" and ", annotations), method.get().getDeclaringClass());
}
}
private void processSchedules(final EnterpriseBean bean, final AnnotationFinder annotationFinder) {
if (!(bean instanceof TimerConsumer)) {
return;
}
final TimerConsumer timerConsumer = (TimerConsumer) bean;
final Set> scheduleMethods = new HashSet>();
scheduleMethods.addAll(annotationFinder.findMetaAnnotatedMethods(Schedules.class));
scheduleMethods.addAll(annotationFinder.findMetaAnnotatedMethods(Schedule.class));
final List timers = timerConsumer.getTimer();
// TODO : The NamedMethod object implements equals and hashCode, so we could rely on that rather than collecting strings
final Set methodsConfiguredInDeploymentXml = new HashSet();
for (final Timer timer : timers) {
final NamedMethod namedMethod = timer.getTimeoutMethod();
methodsConfiguredInDeploymentXml.add(namedMethod.getMethodName() + (namedMethod.getMethodParams() == null ? "" : Join.join("", namedMethod.getMethodParams().getMethodParam())));
}
for (final Annotated method : scheduleMethods) {
// Don't add the schedules from annotations if the schedules have been
// supplied for this method via xml. The xml is considered an override.
if (methodsConfiguredInDeploymentXml.contains(method.get().getName() + Join.join("", (Object[]) asStrings(method.get().getParameterTypes())))) {
continue;
}
final List scheduleAnnotationList = new ArrayList();
final Schedules schedulesAnnotation = method.getAnnotation(Schedules.class);
if (schedulesAnnotation != null) {
scheduleAnnotationList.addAll(asList(schedulesAnnotation.value()));
}
final Schedule scheduleAnnotation = method.getAnnotation(Schedule.class);
if (scheduleAnnotation != null) {
scheduleAnnotationList.add(scheduleAnnotation);
}
for (final Schedule schedule : scheduleAnnotationList) {
final Timer timer = new Timer();
timer.setPersistent(schedule.persistent());
timer.setInfo(schedule.info() == null || schedule.info().isEmpty() ? null : schedule.info());
timer.setTimezone(schedule.timezone() == null || schedule.timezone().isEmpty() ? null : schedule.timezone());
//Copy TimerSchedule
final TimerSchedule timerSchedule = new TimerSchedule();
timerSchedule.setSecond(schedule.second());
timerSchedule.setMinute(schedule.minute());
timerSchedule.setHour(schedule.hour());
timerSchedule.setDayOfWeek(schedule.dayOfWeek());
timerSchedule.setDayOfMonth(schedule.dayOfMonth());
timerSchedule.setMonth(schedule.month());
timerSchedule.setYear(schedule.year());
timer.setSchedule(timerSchedule);
//Copy Method Signature
timer.setTimeoutMethod(new NamedMethod(method.get()));
timers.add(timer);
}
}
}
private void processCallbacks(final Lifecycle bean, final AnnotationFinder annotationFinder) {
final boolean override = "true".equalsIgnoreCase(getProperty("openejb.callbacks.override", "false"));
/*
* @PostConstruct
*/
if (apply(override, bean.getPostConstruct())) {
for (final Annotated method : sortMethods(annotationFinder.findMetaAnnotatedMethods(PostConstruct.class))) {
bean.getPostConstruct().add(new LifecycleCallback(method.get()));
}
}
/*
* @PreDestroy
*/
if (apply(override, bean.getPreDestroy())) {
for (final Annotated method : sortMethods(annotationFinder.findMetaAnnotatedMethods(PreDestroy.class))) {
bean.getPreDestroy().add(new LifecycleCallback(method.get()));
}
}
if (bean instanceof Invokable) {
final Invokable invokable = (Invokable) bean;
/*
* @AroundInvoke
*/
if (apply(override, invokable.getAroundInvoke())) {
for (final Annotated method : sortMethods(annotationFinder.findMetaAnnotatedMethods(javax.interceptor.AroundInvoke.class))) {
invokable.getAroundInvoke().add(new AroundInvoke(method.get()));
}
}
/*
* @AroundTimeout
*/
if (apply(override, invokable.getAroundTimeout())) {
for (final Annotated method : sortMethods(annotationFinder.findMetaAnnotatedMethods(javax.interceptor.AroundTimeout.class))) {
invokable.getAroundTimeout().add(new AroundTimeout(method.get()));
}
}
}
/*
* @Timeout
*/
if (bean instanceof TimerConsumer) {
final TimerConsumer timerConsumer = (TimerConsumer) bean;
if (timerConsumer.getTimeoutMethod() == null) {
final List> timeoutMethods = sortMethods(annotationFinder.findMetaAnnotatedMethods(javax.ejb.Timeout.class));
//Validation Logic is moved to CheckCallback class.
if (timeoutMethods.size() >= 1) {
// Use the timeout method most near the child class because
// the timeout method in child class will override the timeout method in super classes
timerConsumer.setTimeoutMethod(new NamedMethod(timeoutMethods.get(timeoutMethods.size() - 1).get()));
}
}
}
if (bean instanceof Session) {
final Session session = (Session) bean;
/*
* @AfterBegin
*/
final LifecycleCallback afterBegin = getFirst(session.getAfterBegin());
if (afterBegin == null) {
for (final Annotated method : sortMethods(annotationFinder.findMetaAnnotatedMethods(AfterBegin.class))) {
session.getAfterBegin().add(new LifecycleCallback(method.get()));
}
}
/*
* @BeforeCompletion
*/
final LifecycleCallback beforeCompletion = getFirst(session.getBeforeCompletion());
if (beforeCompletion == null) {
for (final Annotated method : sortMethods(annotationFinder.findMetaAnnotatedMethods(BeforeCompletion.class))) {
session.getBeforeCompletion().add(new LifecycleCallback(method.get()));
}
}
/*
* @AfterCompletion
*/
final LifecycleCallback afterCompletion = getFirst(session.getAfterCompletion());
if (afterCompletion == null) {
for (final Annotated method : sortMethods(annotationFinder.findMetaAnnotatedMethods(AfterCompletion.class))) {
session.getAfterCompletion().add(new LifecycleCallback(method.get()));
}
}
/*
* @PostActivate
*/
if (apply(override, session.getPostActivate())) {
for (final Annotated method : sortMethods(annotationFinder.findMetaAnnotatedMethods(PostActivate.class))) {
session.getPostActivate().add(new LifecycleCallback(method.get()));
}
}
/*
* @PrePassivate
*/
if (apply(override, session.getPrePassivate())) {
for (final Annotated method : sortMethods(annotationFinder.findMetaAnnotatedMethods(PrePassivate.class))) {
session.getPrePassivate().add(new LifecycleCallback(method.get()));
}
}
/*
* @Init
*/
for (final Annotated method : sortMethods(annotationFinder.findMetaAnnotatedMethods(Init.class))) {
final InitMethod initMethod = new InitMethod(method.get());
final Init init = method.getAnnotation(Init.class);
if (init.value() != null && !init.value().equals("")) {
initMethod.setCreateMethod(init.value());
}
session.getInitMethod().add(initMethod);
}
/*
* @Remove
*/
final List> removeMethods = sortMethods(annotationFinder.findMetaAnnotatedMethods(Remove.class));
final Map declaredRemoveMethods = new HashMap();
for (final RemoveMethod removeMethod : session.getRemoveMethod()) {
declaredRemoveMethods.put(removeMethod.getBeanMethod(), removeMethod);
}
for (final Annotated method : removeMethods) {
final Remove remove = method.getAnnotation(Remove.class);
final RemoveMethod removeMethod = new RemoveMethod(method.get(), remove.retainIfException());
final RemoveMethod declaredRemoveMethod = declaredRemoveMethods.get(removeMethod.getBeanMethod());
if (declaredRemoveMethod == null) {
session.getRemoveMethod().add(removeMethod);
} else if (!declaredRemoveMethod.isExplicitlySet()) {
declaredRemoveMethod.setRetainIfException(remove.retainIfException());
}
}
}
}
private boolean apply(final boolean override, final List> list) {
// Compliant behavior is to always add the annotated callbacks
// into the list of xml configured callbacks
// Legacy behavior was to not apply the annotations to the list
// if there were any of the related elements specified in the xml
// if we are *not* using the legacy logic, always return true
if (!override) {
return true;
}
// if we are using that logic, then only return true if the list is empty
// i.e. we will not augment the list if callbacks have been specified in xml
return list.size() == 0;
}
public void buildAnnotatedRefs(final JndiConsumer consumer, final IAnnotationFinder annotationFinder, final ClassLoader classLoader) throws OpenEJBException {
//
// @EJB
//
final List ejbList = new ArrayList();
for (final Annotated> clazz : annotationFinder.findMetaAnnotatedClasses(EJBs.class)) {
final EJBs ejbs = clazz.getAnnotation(EJBs.class);
ejbList.addAll(asList(ejbs.value()));
}
for (final Annotated> clazz : annotationFinder.findMetaAnnotatedClasses(EJB.class)) {
final EJB e = clazz.getAnnotation(EJB.class);
ejbList.add(e);
}
for (final EJB ejb : ejbList) {
buildEjbRef(consumer, ejb, null);
}
for (final Annotated field : annotationFinder.findMetaAnnotatedFields(EJB.class)) {
final EJB ejb = field.getAnnotation(EJB.class);
final Member member = new FieldMember(field.get());
buildEjbRef(consumer, ejb, member);
}
for (final Annotated method : annotationFinder.findMetaAnnotatedMethods(EJB.class)) {
final EJB ejb = method.getAnnotation(EJB.class);
final Member member = new MethodMember(method.get());
buildEjbRef(consumer, ejb, member);
}
//
// @Resource
//
final List resourceList = new ArrayList();
for (final Annotated> clazz : annotationFinder.findMetaAnnotatedClasses(Resources.class)) {
final Resources resources = clazz.getAnnotation(Resources.class);
resourceList.addAll(asList(resources.value()));
}
for (final Annotated> clazz : annotationFinder.findMetaAnnotatedClasses(Resource.class)) {
final Resource resource = clazz.getAnnotation(Resource.class);
resourceList.add(resource);
}
for (final Resource resource : resourceList) {
buildResource(consumer, resource, null);
}
for (final Annotated field : annotationFinder.findMetaAnnotatedFields(Resource.class)) {
final Resource resource = field.getAnnotation(Resource.class);
final Member member = new FieldMember(field.get());
buildResource(consumer, resource, member);
}
for (final Annotated method : annotationFinder.findMetaAnnotatedMethods(Resource.class)) {
final Resource resource = method.getAnnotation(Resource.class);
final Member member = new MethodMember(method.get());
buildResource(consumer, resource, member);
}
//
// @Context (REST)
//
for (final Annotated field : annotationFinder.findMetaAnnotatedFields(Context.class)) {
final Member member = new FieldMember(field.get());
buildContext(consumer, member);
}
//
// @WebServiceRef
//
final List webservicerefList = new ArrayList();
for (final Annotated> clazz : annotationFinder.findMetaAnnotatedClasses(WebServiceRefs.class)) {
final WebServiceRefs webServiceRefs = clazz.getAnnotation(WebServiceRefs.class);
webservicerefList.addAll(asList(webServiceRefs.value()));
}
for (final Annotated> clazz : annotationFinder.findMetaAnnotatedClasses(WebServiceRef.class)) {
final WebServiceRef webServiceRef = clazz.getAnnotation(WebServiceRef.class);
webservicerefList.add(webServiceRef);
}
for (final WebServiceRef webserviceref : webservicerefList) {
buildWebServiceRef(consumer, webserviceref, null, null, classLoader);
}
for (final Annotated field : annotationFinder.findMetaAnnotatedFields(WebServiceRef.class)) {
final WebServiceRef webserviceref = field.getAnnotation(WebServiceRef.class);
final HandlerChain handlerChain = field.getAnnotation(HandlerChain.class);
final Member member = new FieldMember(field.get());
buildWebServiceRef(consumer, webserviceref, handlerChain, member, classLoader);
}
for (final Annotated method : annotationFinder.findMetaAnnotatedMethods(WebServiceRef.class)) {
final WebServiceRef webserviceref = method.getAnnotation(WebServiceRef.class);
final HandlerChain handlerChain = method.getAnnotation(HandlerChain.class);
final Member member = new MethodMember(method.get());
buildWebServiceRef(consumer, webserviceref, handlerChain, member, classLoader);
}
//
// @PersistenceUnit
//
final List persistenceUnitList = new ArrayList();
for (final Annotated> clazz : annotationFinder.findMetaAnnotatedClasses(PersistenceUnits.class)) {
final PersistenceUnits persistenceUnits = clazz.getAnnotation(PersistenceUnits.class);
persistenceUnitList.addAll(asList(persistenceUnits.value()));
}
for (final Annotated> clazz : annotationFinder.findMetaAnnotatedClasses(PersistenceUnit.class)) {
final PersistenceUnit persistenceUnit = clazz.getAnnotation(PersistenceUnit.class);
persistenceUnitList.add(persistenceUnit);
}
for (final PersistenceUnit pUnit : persistenceUnitList) {
buildPersistenceUnit(consumer, pUnit, null);
}
for (final Annotated field : annotationFinder.findMetaAnnotatedFields(PersistenceUnit.class)) {
final PersistenceUnit pUnit = field.getAnnotation(PersistenceUnit.class);
final Member member = new FieldMember(field.get());
buildPersistenceUnit(consumer, pUnit, member);
}
for (final Annotated method : annotationFinder.findMetaAnnotatedMethods(PersistenceUnit.class)) {
final PersistenceUnit pUnit = method.getAnnotation(PersistenceUnit.class);
final Member member = new MethodMember(method.get());
buildPersistenceUnit(consumer, pUnit, member);
}
//
// @PersistenceContext
//
final PersistenceContextAnnFactory pcFactory = new PersistenceContextAnnFactory();
final List persistenceContextList = new ArrayList();
for (final Annotated> clazz : annotationFinder.findMetaAnnotatedClasses(PersistenceContexts.class)) {
final PersistenceContexts persistenceContexts = clazz.getAnnotation(PersistenceContexts.class);
persistenceContextList.addAll(asList(persistenceContexts.value()));
pcFactory.addAnnotations(clazz.get());
}
for (final Annotated> clazz : annotationFinder.findMetaAnnotatedClasses(PersistenceContext.class)) {
final PersistenceContext persistenceContext = clazz.getAnnotation(PersistenceContext.class);
persistenceContextList.add(persistenceContext);
pcFactory.addAnnotations(clazz.get());
// dynamic proxy implementation
if (clazz.get().isInterface()) {
final Member member = new FilledMember("em", EntityManager.class, clazz.get());
buildPersistenceContext(consumer, pcFactory.create(persistenceContext, member), member);
}
}
for (final PersistenceContext pCtx : persistenceContextList) {
buildPersistenceContext(consumer, pcFactory.create(pCtx, null), null);
}
for (final Annotated field : annotationFinder.findMetaAnnotatedFields(PersistenceContext.class)) {
final PersistenceContext pCtx = field.getAnnotation(PersistenceContext.class);
final Member member = new FieldMember(field.get());
buildPersistenceContext(consumer, pcFactory.create(pCtx, member), member);
}
for (final Annotated method : annotationFinder.findMetaAnnotatedMethods(PersistenceContext.class)) {
final PersistenceContext pCtx = method.getAnnotation(PersistenceContext.class);
final Member member = new MethodMember(method.get());
buildPersistenceContext(consumer, pcFactory.create(pCtx, member), member);
}
//
// @DataSourceDefinition
//
for (final Annotated> annotated : annotationFinder.findMetaAnnotatedClasses(DataSourceDefinitions.class)) {
final DataSourceDefinitions defs = annotated.getAnnotation(DataSourceDefinitions.class);
for (final DataSourceDefinition definition : defs.value()) {
buildDataSourceDefinition(consumer, definition);
}
}
for (final Annotated> annotated : annotationFinder.findMetaAnnotatedClasses(DataSourceDefinition.class)) {
final DataSourceDefinition definition = annotated.getAnnotation(DataSourceDefinition.class);
buildDataSourceDefinition(consumer, definition);
}
}
private void buildContext(final JndiConsumer consumer, final Member member) {
final ContextRef ref = new ContextRef();
ref.setName(member.getDeclaringClass().getName() + "/" + member.getName());
ref.setResType(member.getType().getName());
final InjectionTarget target = new InjectionTarget();
target.setInjectionTargetClass(member.getDeclaringClass().getName());
target.setInjectionTargetName(member.getName());
ref.getInjectionTarget().add(target);
consumer.getResourceRef().add(ref);
}
/**
* Process @EJB into or for the specified member (field or method)
*
* @param consumer
* @param ejb
* @param member
*/
private void buildEjbRef(final JndiConsumer consumer, final EJB ejb, final Member member) {
// TODO: Looks like we aren't looking for an existing ejb-ref or ejb-local-ref
// we need to do this to support overriding.
/**
* Was @EJB used at a class level witout specifying the 'name' or 'beanInterface' attributes?
*/
final String name = consumer.getJndiConsumerName();
if (member == null) {
boolean shouldReturn = false;
if (ejb.name().equals("")) {
fail(name, "ejbAnnotation.onClassWithNoName");
shouldReturn = true;
}
if (ejb.beanInterface().equals(Object.class)) {
fail(name, "ejbAnnotation.onClassWithNoBeanInterface");
shouldReturn = true;
}
if (shouldReturn) {
return;
}
}
final EjbRef ejbRef = new EjbRef();
// This is how we deal with the fact that we don't know
// whether to use an EjbLocalRef or EjbRef (remote).
// We flag it uknown and let the linking code take care of
// figuring out what to do with it.
ejbRef.setRefType(EjbReference.Type.UNKNOWN);
// Get the ejb-ref-name
String refName = ejb.name();
if (refName.length() == 0) {
refName = member.getDeclaringClass().getName() + "/" + member.getName();
}
//TODO can refName actually be null?
ejbRef.setEjbRefName(normalize(refName));
if (member != null) {
// Set the member name where this will be injected
final InjectionTarget target = new InjectionTarget();
target.setInjectionTargetClass(member.getDeclaringClass().getName());
target.setInjectionTargetName(member.getName());
ejbRef.getInjectionTarget().add(target);
}
Class> interfce = ejb.beanInterface();
if (interfce.equals(Object.class)) {
interfce = member == null ? null : member.getType();
}
final boolean localbean = isKnownLocalBean(interfce);
final boolean dynamicallyImplemented = DynamicProxyImplFactory.isKnownDynamicallyImplemented(interfce);
if (!localbean && interfce != null && !isValidEjbInterface(name, interfce, ejbRef.getName())) {
return;
}
if (interfce != null && !interfce.equals(Object.class)) {
if (EJBHome.class.isAssignableFrom(interfce)) {
ejbRef.setHome(interfce.getName());
final Method[] methods = interfce.getMethods();
for (final Method method : methods) {
if (method.getName().startsWith("create")) {
ejbRef.setRemote(method.getReturnType().getName());
break;
}
}
ejbRef.setRefType(EjbReference.Type.REMOTE);
} else if (EJBLocalHome.class.isAssignableFrom(interfce)) {
ejbRef.setHome(interfce.getName());
final Method[] methods = interfce.getMethods();
for (final Method method : methods) {
if (method.getName().startsWith("create")) {
ejbRef.setRemote(method.getReturnType().getName());
break;
}
}
ejbRef.setRefType(EjbReference.Type.LOCAL);
} else if (localbean) {
ejbRef.setRefType(EjbReference.Type.LOCAL);
ejbRef.setRemote(interfce.getName());
} else if (dynamicallyImplemented) {
ejbRef.setRefType(EjbReference.Type.LOCAL);
ejbRef.setRemote(interfce.getName());
} else {
ejbRef.setRemote(interfce.getName());
if (interfce.getAnnotation(Local.class) != null) {
ejbRef.setRefType(EjbReference.Type.LOCAL);
} else if (interfce.getAnnotation(Remote.class) != null) {
ejbRef.setRefType(EjbReference.Type.REMOTE);
}
}
}
// Set the ejb-link, if any
String ejbName = ejb.beanName();
if (ejbName.equals("")) {
ejbName = null;
}
ejbRef.setEjbLink(ejbName);
// Set the mappedName, if any
String mappedName = ejb.mappedName();
if (mappedName.equals("")) {
mappedName = null;
}
ejbRef.setMappedName(mappedName);
// Set lookup name, if any
String lookupName = getLookupName(ejb);
if (lookupName.equals("")) {
lookupName = null;
}
ejbRef.setLookupName(lookupName);
final Map remoteRefs = consumer.getEjbRefMap();
if (remoteRefs.containsKey(ejbRef.getName())) {
final EjbRef ref = remoteRefs.get(ejbRef.getName());
if (ref.getRemote() == null) {
ref.setRemote(ejbRef.getRemote());
}
if (ref.getHome() == null) {
ref.setHome(ejbRef.getHome());
}
if (ref.getMappedName() == null) {
ref.setMappedName(ejbRef.getMappedName());
}
ref.getInjectionTarget().addAll(ejbRef.getInjectionTarget());
return;
}
final Map localRefs = consumer.getEjbLocalRefMap();
if (localRefs.containsKey(ejbRef.getName())) {
final EjbLocalRef ejbLocalRef = new EjbLocalRef(ejbRef);
final EjbLocalRef ref = localRefs.get(ejbLocalRef.getName());
if (ref.getLocal() == null) {
ref.setLocal(ejbLocalRef.getLocal());
}
if (ref.getLocalHome() == null) {
ref.setLocalHome(ejbLocalRef.getLocalHome());
}
if (ref.getMappedName() == null) {
ref.setMappedName(ejbLocalRef.getMappedName());
}
ref.getInjectionTarget().addAll(ejbLocalRef.getInjectionTarget());
return;
}
switch (ejbRef.getRefType()) {
case UNKNOWN:
case REMOTE:
consumer.getEjbRef().add(ejbRef);
break;
case LOCAL:
consumer.getEjbLocalRef().add(new EjbLocalRef(ejbRef));
break;
}
}
private String normalize(final String refName) {
if (refName.startsWith("java:")) {
return refName;
}
return "java:comp/env/" + refName;
}
private boolean isKnownLocalBean(final Class clazz) {
if (clazz.isAnnotation()) {
return false;
}
if (clazz.isArray()) {
return false;
}
if (clazz.isEnum()) {
return false;
}
if (clazz.isInterface()) {
return false;
}
if (clazz.isPrimitive()) {
return false;
}
if (Modifier.isAbstract(clazz.getModifiers())) {
return false;
}
if (Modifier.isFinal(clazz.getModifiers())) {
return false;
}
return true;
}
private boolean isValidEjbInterface(final String b, final Class clazz, final String refName) {
if (!clazz.isInterface()) {
//It is not an interface. No validation necessary.
return true;
} else if (EJBObject.class.isAssignableFrom(clazz)) {
fail(b, "ann.ejb.ejbObject", clazz.getName(), refName);
return false;
} else if (EJBLocalObject.class.isAssignableFrom(clazz)) {
fail(b, "ann.ejb.ejbLocalObject", clazz.getName(), refName);
return false;
}
return true;
}
private void fail(final String component, final String key, final Object... details) {
getValidationContext().fail(component, key, details);
}
/**
* Process @Resource into either or for the given member (field or method) or class
*
* @param consumer
* @param resource
* @param member
*/
private void buildResource(final JndiConsumer consumer, final Resource resource, final Member member) {
/**
* Was @Resource used at a class level without specifying the 'name' or 'beanInterface' attributes?
*/
if (member == null) {
if (resource.name().length() == 0) {
fail(consumer.getJndiConsumerName(), "resourceAnnotation.onClassWithNoName");
return;
}
}
// Get the ref-name
String refName = resource.name();
if (refName.equals("")) {
if (member != null) {
refName = member.getDeclaringClass().getName() + "/" + member.getName();
} else {
fail(consumer.getJndiConsumerName(), "Unable to ascertain name of resourceAnnotation");
return;
}
}
refName = normalize(refName);
JndiReference reference = consumer.getEnvEntryMap().get(refName);
if (reference == null) {
/**
* Was @Resource mistakenly used when either @PersistenceContext or @PersistenceUnit should have been used?
*/
if (member != null) { // Little quick validation for common mistake
final Class type = member.getType();
boolean shouldReturn = false;
if (EntityManager.class.isAssignableFrom(type)) {
fail(consumer.getJndiConsumerName(), "resourceRef.onEntityManager", refName);
shouldReturn = true;
} else if (EntityManagerFactory.class.isAssignableFrom(type)) {
fail(consumer.getJndiConsumerName(), "resourceRef.onEntityManagerFactory", refName);
shouldReturn = true;
}
if (shouldReturn) {
return;
}
}
final Class type;
if (member == null) {
type = resource.type();
} else {
type = member.getType();
}
if (knownResourceEnvTypes.contains(type.getName())) {
/*
* @Resource
*/
ResourceEnvRef resourceEnvRef = consumer.getResourceEnvRefMap().get(refName);
if (resourceEnvRef == null) {
resourceEnvRef = new ResourceEnvRef();
resourceEnvRef.setName(refName);
consumer.getResourceEnvRef().add(resourceEnvRef);
}
if (resourceEnvRef.getResourceEnvRefType() == null || "".equals(resourceEnvRef.getResourceEnvRefType())) {
resourceEnvRef.setResourceEnvRefType(type.getName());
}
reference = resourceEnvRef;
} else if (isKnownEnvironmentEntryType(type)) {
/*
* @Resource
*
* Add an env-entry via @Resource if 'lookup' attribute is set.
*/
final String lookupName = getLookupName(resource);
if (!lookupName.equals("")) {
final EnvEntry envEntry = new EnvEntry();
envEntry.setName(refName);
consumer.getEnvEntry().add(envEntry);
envEntry.setLookupName(lookupName);
reference = envEntry;
} else if (isShareableJNDINamespace(refName)) {
final EnvEntry envEntry = new EnvEntry();
envEntry.setName(refName);
consumer.getEnvEntry().add(envEntry);
reference = envEntry;
} else {
if (member != null) {
final String shortName = normalize(member.getName());
reference = consumer.getEnvEntryMap().get(shortName);
if (reference == null) {
final EnvEntry envEntry = new EnvEntry();
envEntry.setName(refName);
consumer.getEnvEntry().add(envEntry);
reference = envEntry;
}
} else {
logger.warning("Cannot add env-entry since @Resource.lookup is not set and it is NOT in a shareable JNDI name space");
}
}
} else {
/*
* @Resource
*/
ResourceRef resourceRef = consumer.getResourceRefMap().get(refName);
if (resourceRef == null) {
resourceRef = new ResourceRef();
resourceRef.setName(refName);
consumer.getResourceRef().add(resourceRef);
}
if (member != null) {
resourceRef.setOrigin(member.getDeclaringClass() + "#" + member.getName());
} // TODO: else @Resource on a class
if (resourceRef.getResAuth() == null) {
if (resource.authenticationType() == Resource.AuthenticationType.APPLICATION) {
resourceRef.setResAuth(ResAuth.APPLICATION);
} else {
resourceRef.setResAuth(ResAuth.CONTAINER);
}
}
if (resourceRef.getResType() == null || "".equals(resourceRef.getResType())) {
resourceRef.setResType(type.getName());
}
if (resourceRef.getResSharingScope() == null) {
if (resource.shareable()) {
resourceRef.setResSharingScope(ResSharingScope.SHAREABLE);
} else {
resourceRef.setResSharingScope(ResSharingScope.UNSHAREABLE);
}
}
reference = resourceRef;
}
}
/*
* Fill in the injection information
*/
if (member != null) {
// Set the member name where this will be injected
final InjectionTarget target = new InjectionTarget();
target.setInjectionTargetClass(member.getDeclaringClass().getName());
target.setInjectionTargetName(member.getName());
reference.getInjectionTarget().add(target);
}
// Override the mapped name if not set
if (reference != null) {
if (reference.getMappedName() == null && !resource.mappedName().equals("")) {
reference.setMappedName(resource.mappedName());
}
// Override the lookup name if not set
if (reference.getLookupName() == null) {
final String lookupName = getLookupName(resource);
if (!lookupName.equals("")) {
reference.setLookupName(lookupName);
}
}
}
}
private static Method getLookupMethod(final Class cls) {
final String name = cls.getName();
if (!lookupMissing.contains(name)) {
try {
return cls.getMethod("lookup", (Class[]) null);
} catch (final NoSuchMethodException e) {
lookupMissing.add(name);
final String exists = getSourceIfExists(cls);
logger.warning("Method 'lookup' is not available for '" + name + "'"
+ (null != exists ? ". The old API '" + exists + "' was found on the classpath." : ". Probably using an older Runtime."));
}
}
return null;
}
private static String getSourceIfExists(final Class> cls) {
if (cls.getProtectionDomain() != null && cls.getProtectionDomain().getCodeSource() != null
&& cls.getProtectionDomain().getCodeSource().getLocation() != null) {
return cls.getProtectionDomain().getCodeSource().getLocation().toString();
}
return null;
}
private static String getLookupName(final Resource resource) {
String value = "";
final Method lookupMethod = getLookupMethod(Resource.class);
if (lookupMethod != null) {
try {
value = (String) lookupMethod.invoke(resource, (Object[]) null);
} catch (final Exception e) {
// ignore
}
}
return value;
}
private static String getLookupName(final EJB ejb) {
String value = "";
final Method lookupMethod = getLookupMethod(EJB.class);
if (lookupMethod != null) {
try {
value = (String) lookupMethod.invoke(ejb, (Object[]) null);
} catch (final Exception e) {
// ignore
}
}
return value;
}
/**
* Process @PersistenceUnit into for the specified member (field or method)
*
* @param consumer JndiConsumer
* @param persistenceUnit PersistenceUnit
* @param member Member
* @throws OpenEJBException
*/
private void buildPersistenceUnit(final JndiConsumer consumer, final PersistenceUnit persistenceUnit, final Member member) throws OpenEJBException {
String refName = persistenceUnit.name();
// Get the ref-name
if (refName.length() == 0) {
/**
* Was @PersistenceUnit used at a class level without specifying the 'name' attribute?
*/
if (member == null) {
fail(consumer.getJndiConsumerName(), "persistenceUnitAnnotation.onClassWithNoName", persistenceUnit.unitName());
return;
}
refName = member.getDeclaringClass().getName() + "/" + member.getName();
}
refName = normalize(refName);
PersistenceUnitRef persistenceUnitRef = consumer.getPersistenceUnitRefMap().get(refName);
if (persistenceUnitRef == null) {
persistenceUnitRef = new PersistenceUnitRef();
persistenceUnitRef.setPersistenceUnitName(persistenceUnit.unitName());
persistenceUnitRef.setPersistenceUnitRefName(refName);
consumer.getPersistenceUnitRef().add(persistenceUnitRef);
}
if (member != null) {
final Class type = member.getType();
if (EntityManager.class.isAssignableFrom(type)) {
/**
* Was @PersistenceUnit mistakenly used when @PersistenceContext should have been used?
*/
final ValidationContext validationContext = getValidationContext();
final String jndiConsumerName = consumer.getJndiConsumerName();
final String name = persistenceUnitRef.getName();
validationContext.fail(jndiConsumerName, "persistenceUnitAnnotation.onEntityManager", name);
} else if (!EntityManagerFactory.class.isAssignableFrom(type)) {
/**
* Was @PersistenceUnit mistakenly used for something that isn't an EntityManagerFactory?
*/
fail(consumer.getJndiConsumerName(), "persistenceUnitAnnotation.onNonEntityManagerFactory", persistenceUnitRef.getName());
} else {
// Set the member name where this will be injected
final InjectionTarget target = new InjectionTarget();
target.setInjectionTargetClass(member.getDeclaringClass().getName());
target.setInjectionTargetName(member.getName());
persistenceUnitRef.getInjectionTarget().add(target);
}
}
if (persistenceUnitRef.getPersistenceUnitName() == null && !persistenceUnit.unitName().equals("")) {
persistenceUnitRef.setPersistenceUnitName(persistenceUnit.unitName());
}
}
/**
* Process @PersistenceContext into for the specified member (field or method)
*
* Refer 16.11.2.1 Overriding Rules of EJB Core Spec for overriding rules
*
* @param consumer
* @param persistenceContext
* @param member
* @throws OpenEJBException
*/
private void buildPersistenceContext(final JndiConsumer consumer, final PersistenceContextAnn persistenceContext, final Member member) throws OpenEJBException {
AppModule module = null;
if (currentModule.get() instanceof AppModule) {
module = (AppModule) currentModule.get();
} else if (currentModule.get() instanceof Module) {
module = ((Module) currentModule.get()).getAppModule();
}
if (module != null
&& org.apache.openejb.jee.jpa.unit.TransactionType.RESOURCE_LOCAL.equals(module.getTransactionType(persistenceContext.unitName()))) {
// should it be in warn level?
// IMO no since with CDI it is tempting to do so
String name = persistenceContext.unitName();
if (name == null || name.isEmpty()) { // search for it
try { // get the first one
name = module.getPersistenceModules().iterator().next()
.getPersistence()
.getPersistenceUnit().iterator().next().getName();
} catch (final Exception e) {
name = "?";
}
}
logger.info("PersistenceUnit '" + name + "' is a RESOURCE_LOCAL one, " +
"you'll have to manage @PersistenceContext yourself.");
return;
}
String refName = persistenceContext.name();
if (refName.length() == 0) {
/**
* Was @PersistenceContext used at a class level without specifying the 'name' attribute?
*/
if (member == null) {
fail(consumer.getJndiConsumerName(), "persistenceContextAnnotation.onClassWithNoName", persistenceContext.unitName());
return;
}
refName = member.getDeclaringClass().getName() + "/" + member.getName();
}
refName = normalize(refName);
PersistenceContextRef persistenceContextRef = consumer.getPersistenceContextRefMap().get(refName);
if (persistenceContextRef == null) {
persistenceContextRef = new PersistenceContextRef();
persistenceContextRef.setPersistenceUnitName(persistenceContext.unitName());
persistenceContextRef.setPersistenceContextRefName(refName);
if ("EXTENDED".equalsIgnoreCase(persistenceContext.type())) {
persistenceContextRef.setPersistenceContextType(PersistenceContextType.EXTENDED);
} else {
persistenceContextRef.setPersistenceContextType(PersistenceContextType.TRANSACTION);
}
consumer.getPersistenceContextRef().add(persistenceContextRef);
} else {
if (persistenceContextRef.getPersistenceUnitName() == null || "".equals(persistenceContextRef.getPersistenceUnitName())) {
persistenceContextRef.setPersistenceUnitName(persistenceContext.unitName());
}
if (persistenceContextRef.getPersistenceContextType() == null) {
if ("EXTENDED".equalsIgnoreCase(persistenceContext.type())) {
persistenceContextRef.setPersistenceContextType(PersistenceContextType.EXTENDED);
} else {
persistenceContextRef.setPersistenceContextType(PersistenceContextType.TRANSACTION);
}
}
}
List persistenceProperties = persistenceContextRef.getPersistenceProperty();
if (persistenceProperties == null) {
persistenceProperties = new ArrayList();
persistenceContextRef.setPersistenceProperty(persistenceProperties);
}
for (final Map.Entry persistenceProperty : persistenceContext.properties().entrySet()) {
boolean flag = true;
for (final Property prpty : persistenceProperties) {
if (prpty.getName().equals(persistenceProperty.getKey())) {
flag = false;
break;
}
}
if (flag) {
final Property property = new Property();
property.setName(persistenceProperty.getKey());
property.setValue(persistenceProperty.getValue());
persistenceProperties.add(property);
}
}
if (member != null) {
final Class type = member.getType();
if (EntityManagerFactory.class.isAssignableFrom(type)) {
/**
* Was @PersistenceContext mistakenly used when @PersistenceUnit should have been used?
*/
fail(consumer.getJndiConsumerName(), "persistenceContextAnnotation.onEntityManagerFactory", persistenceContextRef.getName());
} else if (!EntityManager.class.isAssignableFrom(type)) {
/**
* Was @PersistenceContext mistakenly used for something that isn't an EntityManager?
*/
fail(consumer.getJndiConsumerName(), "persistenceContextAnnotation.onNonEntityManager", persistenceContextRef.getName());
} else {
// Set the member name where this will be injected
final InjectionTarget target = new InjectionTarget();
target.setInjectionTargetClass(member.getDeclaringClass().getName());
target.setInjectionTargetName(member.getName());
persistenceContextRef.getInjectionTarget().add(target);
}
}
}
private void buildDataSourceDefinition(final JndiConsumer consumer, final DataSourceDefinition d) {
final DataSource dataSource = new DataSource();
dataSource.setName(d.name());
dataSource.setClassName(d.className());
dataSource.setTransactional(d.transactional());
final DataSource existing = consumer.getDataSourceMap().get(dataSource.getKey());
if (existing != null) {
return;
}
// Optional properties
if (!d.databaseName().isEmpty()) {
dataSource.setDatabaseName(d.databaseName());
}
if (d.initialPoolSize() != -1) {
dataSource.setInitialPoolSize(d.initialPoolSize());
}
if (d.isolationLevel() != -1) {
dataSource.setIsolationLevel(IsolationLevel.fromFlag(d.isolationLevel()));
}
if (d.loginTimeout() != 0) {
dataSource.setLoginTimeout(d.loginTimeout());
}
if (d.maxIdleTime() != -1) {
dataSource.setMaxIdleTime(d.maxIdleTime());
}
if (d.maxPoolSize() != -1) {
dataSource.setMaxPoolSize(d.maxPoolSize());
}
if (d.maxStatements() != -1) {
dataSource.setMaxStatements(d.maxStatements());
}
if (d.minPoolSize() != -1) {
dataSource.setMinPoolSize(d.minPoolSize());
}
if (!d.password().isEmpty()) {
dataSource.setPassword(d.password());
}
if (d.portNumber() != -1) {
dataSource.setPortNumber(d.portNumber());
}
if (!"localhost".equals(d.serverName())) {
dataSource.setServerName(d.serverName());
}
if (!d.url().isEmpty()) {
dataSource.setUrl(d.url());
}
if (!d.user().isEmpty()) {
dataSource.setUser(d.user());
}
for (final String s : d.properties()) {
final int equal = s.indexOf('=');
if (equal < s.length() - 1) {
final SuperProperties props = new SuperProperties();
try {
props.load(new ByteArrayInputStream(s.getBytes()));
for (final String key : props.stringPropertyNames()) {
if (!key.isEmpty()) {
dataSource.property(key, props.getProperty(key));
}
}
} catch (final IOException e) {
final String key = s.substring(0, equal).trim();
final String value = s.substring(equal + 1).trim();
dataSource.property(key, value);
}
} else {
dataSource.property(s.trim(), "");
}
}
consumer.getDataSource().add(dataSource);
}
/**
* Process @WebServiceRef and @HandlerChain for the given member (field or method)
*
* @param consumer
* @param webService
* @param handlerChain
* @param member
* @param classLoader
* @throws OpenEJBException
*/
private void buildWebServiceRef(final JndiConsumer consumer, final WebServiceRef webService, final HandlerChain handlerChain, final Member member, final ClassLoader classLoader) throws OpenEJBException {
ServiceRef serviceRef;
String refName = webService.name();
if (refName.equals("")) {
if (member == null) {
//TODO fail
return;
}
refName = member.getDeclaringClass().getName() + "/" + member.getName();
}
refName = normalize(refName);
serviceRef = consumer.getServiceRefMap().get(refName);
if (serviceRef == null) {
serviceRef = new ServiceRef();
serviceRef.setServiceRefName(refName);
consumer.getServiceRef().add(serviceRef);
}
if (member != null) {
// Set the member name where this will be injected
final InjectionTarget target = new InjectionTarget();
target.setInjectionTargetClass(member.getDeclaringClass().getName());
target.setInjectionTargetName(member.getName());
serviceRef.getInjectionTarget().add(target);
}
// Set service interface
Class> serviceInterface = null;
if (serviceRef.getServiceInterface() == null) {
serviceInterface = webService.type();
if (serviceInterface.equals(Object.class)) {
serviceInterface = webService.value();
if ((Service.class.equals(serviceInterface) || Object.class.equals(serviceInterface)) && member != null) {
serviceInterface = member.getType();
}
}
}
if (serviceInterface == null || !Service.class.isAssignableFrom(serviceInterface)) {
serviceInterface = Service.class;
}
serviceRef.setServiceInterface(serviceInterface.getName());
// reference type
if (serviceRef.getServiceRefType() == null || "".equals(serviceRef.getServiceRefType())) {
if (webService.type() != Object.class) {
serviceRef.setServiceRefType(webService.type().getName());
} else {
if (member != null) {
serviceRef.setServiceRefType(member.getType().getName());
}
}
}
Class> refType = null;
try {
refType = classLoader.loadClass(realClassName(serviceRef.getType()));
} catch (final ClassNotFoundException e) {
// no-op
}
// Set the mappedName
if (serviceRef.getMappedName() == null) {
String mappedName = webService.mappedName();
if (mappedName.equals("")) {
mappedName = null;
}
serviceRef.setMappedName(mappedName);
}
// wsdl file
if (serviceRef.getWsdlFile() == null) {
final String wsdlLocation = webService.wsdlLocation();
if (!wsdlLocation.equals("")) {
serviceRef.setWsdlFile(wsdlLocation);
}
}
if (SystemInstance.get().hasProperty("openejb.geronimo")) {
return;
}
if (serviceRef.getWsdlFile() == null && refType != null) {
serviceRef.setWsdlFile(JaxWsUtils.getServiceWsdlLocation(refType, classLoader));
}
if (serviceRef.getWsdlFile() == null) {
serviceRef.setWsdlFile(JaxWsUtils.getServiceWsdlLocation(serviceInterface, classLoader));
}
// service qname
if (serviceRef.getServiceQname() == null && refType != null) {
serviceRef.setServiceQname(JaxWsUtils.getServiceQName(refType));
}
if (serviceRef.getServiceQname() == null) {
serviceRef.setServiceQname(JaxWsUtils.getServiceQName(serviceInterface));
}
// handlers
if (serviceRef.getHandlerChains() == null && null != handlerChain && null != member) {
try {
final URL handlerFileURL = member.getDeclaringClass().getResource(handlerChain.file());
final HandlerChains handlerChains = ReadDescriptors.readHandlerChains(handlerFileURL);
serviceRef.setHandlerChains(handlerChains);
} catch (final Throwable e) {
throw new OpenEJBException("Unable to load handler chain file: " + handlerChain.file(), e);
}
}
}
/**
* Scan for @EJB, @Resource, @WebServiceRef, @PersistenceUnit, and @PersistenceContext on WebService HandlerChain classes
*/
private void processWebServiceHandlers(final EjbModule ejbModule, final EnterpriseBean bean, final AnnotationFinder finder) throws OpenEJBException {
// add webservice handler classes to the class finder used in annotation processing
final Set classes = new HashSet();
if (ejbModule.getWebservices() != null) {
for (final WebserviceDescription webservice : ejbModule.getWebservices().getWebserviceDescription()) {
for (final PortComponent port : webservice.getPortComponent()) {
// only process port definitions for this ejb
if (!bean.getEjbName().equals(port.getServiceImplBean().getEjbLink())) {
continue;
}
if (port.getHandlerChains() == null) {
continue;
}
for (final org.apache.openejb.jee.HandlerChain handlerChain : port.getHandlerChains().getHandlerChain()) {
for (final Handler handler : handlerChain.getHandler()) {
final String handlerClass = realClassName(handler.getHandlerClass());
if (handlerClass != null) {
classes.add(handlerClass);
}
}
}
}
}
}
// classes.add(bean.getEjbClass());
final AnnotationFinder handlersFinder = finder.select(classes);
buildAnnotatedRefs(bean, handlersFinder, ejbModule.getClassLoader());
}
/**
* Scan for @EJB, @Resource, @WebServiceRef, @PersistenceUnit, and @PersistenceContext on WebService HandlerChain classes
*
* @param consumer
* @param classLoader
* @throws OpenEJBException
*/
private void processWebServiceClientHandlers(final JndiConsumer consumer, final AnnotationFinder finder, final ClassLoader classLoader) throws OpenEJBException {
if (SystemInstance.get().hasProperty("openejb.geronimo")) {
return;
}
final Set processedClasses = new HashSet();
final Set handlerClasses = new HashSet();
do {
// get unprocessed handler classes
handlerClasses.clear();
for (final ServiceRef serviceRef : consumer.getServiceRef()) {
final HandlerChains chains = serviceRef.getAllHandlers();
if (chains == null) {
continue;
}
for (final org.apache.openejb.jee.HandlerChain handlerChain : chains.getHandlerChain()) {
for (final Handler handler : handlerChain.getHandler()) {
if (handler.getHandlerClass() != null) {
handlerClasses.add(realClassName(handler.getHandlerClass()));
}
}
}
}
handlerClasses.removeAll(processedClasses);
if (handlerClasses.isEmpty()) {
continue;
}
// process handler classes
final AnnotationFinder handlerAnnotationFinder = finder != null ? finder.select(handlerClasses) :
new FinderFactory.OpenEJBAnnotationFinder(new FinderFactory.DoLoadClassesArchive(classLoader, handlerClasses));
/*
* @EJB
* @Resource
* @WebServiceRef
* @PersistenceUnit
* @PersistenceContext
*/
buildAnnotatedRefs(consumer, handlerAnnotationFinder, classLoader);
processedClasses.addAll(handlerClasses);
} while (!handlerClasses.isEmpty());
}
// ----------------------------------------------------------------------
//
// Utility methods and classes
//
// ----------------------------------------------------------------------
private List getDeclaredClassPermissions(final AssemblyDescriptor assemblyDescriptor, final String ejbName) {
final List permissions = assemblyDescriptor.getMethodPermission();
final List classPermissions = new ArrayList();
for (final MethodPermission permission : permissions) {
for (final org.apache.openejb.jee.Method method : permission.getMethod()) {
if (!method.getEjbName().equals(ejbName)) {
continue;
}
if (!"*".equals(method.getMethodName())) {
continue;
}
String className = method.getClassName();
if (className == null) {
className = "*";
}
classPermissions.add(className);
}
}
return classPermissions;
}
public interface AnnotationHandler {
Class getAnnotationClass();
Map> getExistingDeclarations();
void addClassLevelDeclaration(A annotation, Class clazz);
void addMethodLevelDeclaration(A annotation, Method method);
}
public static class TransactionAttributeHandler implements AnnotationHandler {
private final AssemblyDescriptor assemblyDescriptor;
private final String ejbName;
public TransactionAttributeHandler(final AssemblyDescriptor assemblyDescriptor, final String ejbName) {
this.assemblyDescriptor = assemblyDescriptor;
this.ejbName = ejbName;
}
public Map> getExistingDeclarations() {
return assemblyDescriptor.getMethodTransactionMap(ejbName);
}
public void addClassLevelDeclaration(final TransactionAttribute attribute, final Class type) {
final ContainerTransaction ctx = new ContainerTransaction(cast(attribute.value()), type.getName(), ejbName, "*");
assemblyDescriptor.getContainerTransaction().add(ctx);
}
public void addMethodLevelDeclaration(final TransactionAttribute attribute, final Method method) {
final ContainerTransaction ctx = new ContainerTransaction(cast(attribute.value()), ejbName, method);
assemblyDescriptor.getContainerTransaction().add(ctx);
}
public Class getAnnotationClass() {
return TransactionAttribute.class;
}
private TransAttribute cast(final TransactionAttributeType transactionAttributeType) {
return TransAttribute.valueOf(transactionAttributeType.toString());
}
}
private static class ConcurrentMethodHandler {
protected final AssemblyDescriptor assemblyDescriptor;
protected final SessionBean bean;
protected final Map