blob: b32fdeaeb5c6dacd1217adf12255889f4f30f146 [file] [log] [blame]
/*
* 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.ClassLoaderUtil;
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.OpenEJBRuntimeException;
import org.apache.openejb.assembler.classic.AppInfo;
import org.apache.openejb.assembler.classic.ClassListInfo;
import org.apache.openejb.assembler.classic.ClientInfo;
import org.apache.openejb.assembler.classic.ConnectorInfo;
import org.apache.openejb.assembler.classic.EjbJarInfo;
import org.apache.openejb.assembler.classic.EnterpriseBeanInfo;
import org.apache.openejb.assembler.classic.EntityManagerFactoryCallable;
import org.apache.openejb.assembler.classic.FilterInfo;
import org.apache.openejb.assembler.classic.HandlerChainInfo;
import org.apache.openejb.assembler.classic.IdPropertiesInfo;
import org.apache.openejb.assembler.classic.JndiEncInfo;
import org.apache.openejb.assembler.classic.ListenerInfo;
import org.apache.openejb.assembler.classic.MdbContainerInfo;
import org.apache.openejb.assembler.classic.MessageDrivenBeanInfo;
import org.apache.openejb.assembler.classic.ParamValueInfo;
import org.apache.openejb.assembler.classic.PersistenceUnitInfo;
import org.apache.openejb.assembler.classic.PortInfo;
import org.apache.openejb.assembler.classic.ResourceInfo;
import org.apache.openejb.assembler.classic.ServiceInfo;
import org.apache.openejb.assembler.classic.ServletInfo;
import org.apache.openejb.assembler.classic.ValidatorBuilder;
import org.apache.openejb.assembler.classic.WebAppInfo;
import org.apache.openejb.config.sys.Container;
import org.apache.openejb.config.sys.JaxbOpenejb;
import org.apache.openejb.config.sys.Openejb;
import org.apache.openejb.config.sys.Resource;
import org.apache.openejb.config.sys.Resources;
import org.apache.openejb.config.sys.ServiceProvider;
import org.apache.openejb.config.sys.ServicesJar;
import org.apache.openejb.jee.AdminObject;
import org.apache.openejb.jee.ApplicationClient;
import org.apache.openejb.jee.ConfigProperty;
import org.apache.openejb.jee.ConnectionDefinition;
import org.apache.openejb.jee.Connector;
import org.apache.openejb.jee.EnterpriseBean;
import org.apache.openejb.jee.Filter;
import org.apache.openejb.jee.InboundResourceadapter;
import org.apache.openejb.jee.Listener;
import org.apache.openejb.jee.MessageListener;
import org.apache.openejb.jee.OutboundResourceAdapter;
import org.apache.openejb.jee.ParamValue;
import org.apache.openejb.jee.PortComponent;
import org.apache.openejb.jee.ResourceAdapter;
import org.apache.openejb.jee.ServiceImplBean;
import org.apache.openejb.jee.Servlet;
import org.apache.openejb.jee.WebApp;
import org.apache.openejb.jee.WebserviceDescription;
import org.apache.openejb.jee.Webservices;
import org.apache.openejb.jee.jpa.EntityMappings;
import org.apache.openejb.jee.jpa.JpaJaxbUtil;
import org.apache.openejb.jee.jpa.unit.Persistence;
import org.apache.openejb.jee.jpa.unit.PersistenceUnit;
import org.apache.openejb.jee.oejb3.EjbDeployment;
import org.apache.openejb.jee.oejb3.OpenejbJar;
import org.apache.openejb.jee.oejb3.PojoDeployment;
import org.apache.openejb.jpa.integration.MakeTxLookup;
import org.apache.openejb.loader.IO;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.util.CircularReferencesException;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.openejb.util.Messages;
import org.apache.openejb.util.References;
import javax.xml.bind.JAXBException;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import static org.apache.openejb.util.URLs.toFile;
/**
* @version $Rev$ $Date$
*/
class AppInfoBuilder {
private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, "org.apache.openejb.util.resources");
private static final Messages messages = new Messages("org.apache.openejb.util.resources");
private static boolean USE_EAR_AS_CONTEXT_ROOT_BASE = SystemInstance.get().getOptions().get("openejb.ear.use-as-webcontext-base", false);
private final ConfigurationFactory configFactory;
private EjbJarInfoBuilder ejbJarInfoBuilder = new EjbJarInfoBuilder();
public AppInfoBuilder(final ConfigurationFactory configFactory) {
this.configFactory = configFactory;
}
public AppInfo build(final AppModule appModule) throws OpenEJBException {
final AppInfo appInfo = new AppInfo();
appInfo.appId = appModule.getModuleId();
appInfo.path = appModule.getJarLocation();
appInfo.standaloneModule = appModule.isStandaloneModule();
appInfo.delegateFirst = appModule.isDelegateFirst();
appInfo.watchedResources.addAll(appModule.getWatchedResources());
appInfo.mbeans.addAll(appModule.getAdditionalLibMbeans());
appInfo.jaxRsProviders.addAll(appModule.getJaxRsProviders());
appInfo.properties.putAll(appModule.getProperties());
if (appInfo.appId == null) throw new IllegalArgumentException("AppInfo.appId cannot be null");
if (appInfo.path == null) appInfo.path = appInfo.appId;
this.buildPojoConfiguration(appModule, appInfo);
this.buildAppResources(appModule, appInfo);
this.buildAppServices(appModule, appInfo);
//
// J2EE Connectors
//
this.buildConnectorModules(appModule, appInfo);
//
// Persistence Units
//
this.buildPersistenceModules(appModule, appInfo);
final List<String> containerIds = this.configFactory.getContainerIds();
for (final ConnectorInfo connectorInfo : appInfo.connectors) {
for (final MdbContainerInfo containerInfo : connectorInfo.inbound) {
containerIds.add(containerInfo.id);
}
}
//
// EJB Jars
//
final Map<EjbModule, EjbJarInfo> ejbJarInfos = new HashMap<EjbModule, EjbJarInfo>();
for (final EjbModule ejbModule : appModule.getEjbModules()) {
try {
final EjbJarInfo ejbJarInfo = this.ejbJarInfoBuilder.buildInfo(ejbModule);
ejbJarInfo.mbeans = ejbModule.getMbeans();
ejbJarInfo.webapp = ejbModule.isWebapp();
final Map<String, EjbDeployment> deploymentsByEjbName = ejbModule.getOpenejbJar().getDeploymentsByEjbName();
for (final EnterpriseBeanInfo bean : ejbJarInfo.enterpriseBeans) {
final EjbDeployment d = deploymentsByEjbName.get(bean.ejbName);
/*
* JRG - there's probably a better way of handling this, but this code handles the case when:
*
* A connector with two or more inbound adapter is registered, causing two containers named with the format:
* <moduleId>-<message listener interface>
*
* This code adjusts the container id for the associated MDBs by sticking the message listener interface on the end.
*
*/
if (bean instanceof MessageDrivenBeanInfo && !containerIds.contains(d.getContainerId()) && !skipMdb(bean)) {
final MessageDrivenBeanInfo mdb = (MessageDrivenBeanInfo) bean;
final String newContainerId = d.getContainerId() + "-" + mdb.mdbInterface;
if (containerIds.contains(newContainerId)) {
d.setContainerId(newContainerId);
}
}
if (!containerIds.contains(d.getContainerId()) && !skipMdb(bean)) {
final String msg = messages.format("config.noContainerFound", d.getContainerId(), d.getEjbName());
logger.fatal(msg);
throw new OpenEJBException(msg);
}
bean.containerId = d.getContainerId();
}
for (final PojoDeployment pojoDeployment : ejbModule.getOpenejbJar().getPojoDeployment()) {
final IdPropertiesInfo info = new IdPropertiesInfo();
info.id = pojoDeployment.getClassName();
info.properties.putAll(pojoDeployment.getProperties());
ejbJarInfo.pojoConfigurations.add(info);
}
ejbJarInfo.validationInfo = ValidatorBuilder.getInfo(ejbModule.getValidationConfig());
ejbJarInfo.portInfos.addAll(this.configureWebservices(ejbModule.getWebservices()));
ejbJarInfo.uniqueId = ejbModule.getUniqueId();
this.configureWebserviceSecurity(ejbJarInfo, ejbModule);
ejbJarInfos.put(ejbModule, ejbJarInfo);
appInfo.ejbJars.add(ejbJarInfo);
} catch (OpenEJBException e) {
ConfigUtils.logger.warning("conf.0004", ejbModule.getJarLocation(), e.getMessage());
throw e;
}
}
// Create the JNDI info builder
final JndiEncInfoBuilder jndiEncInfoBuilder = new JndiEncInfoBuilder(appInfo);
if (appModule.getApplication() != null) {
//TODO figure out how to prevent adding stuff to the module and comp contexts from the application
//or maybe validate the xml so this won't happen.
jndiEncInfoBuilder.build(appModule.getApplication(), appInfo.appId, null, appModule.getModuleUri(), new JndiEncInfo(), new JndiEncInfo());
}
final List<EnterpriseBeanInfo> beans = new ArrayList<EnterpriseBeanInfo>();
// Build the JNDI tree for each ejb
for (final EjbModule ejbModule : appModule.getEjbModules()) {
final EjbJarInfo ejbJar = ejbJarInfos.get(ejbModule);
final Map<String, EnterpriseBean> beanData = ejbModule.getEjbJar().getEnterpriseBeansByEjbName();
for (final EnterpriseBeanInfo beanInfo : ejbJar.enterpriseBeans) {
beans.add(beanInfo);
// Get the ejb-jar.xml object
final EnterpriseBean enterpriseBean = beanData.get(beanInfo.ejbName);
// Build the JNDI info tree for the EJB
jndiEncInfoBuilder.build(enterpriseBean, beanInfo.ejbName, ejbJar.moduleName, ejbModule.getModuleUri(), ejbJar.moduleJndiEnc, beanInfo.jndiEnc);
jndiEncInfoBuilder.buildDependsOnRefs(ejbModule, enterpriseBean, beanInfo, ejbJar.moduleName);
}
}
// Check for circular references in Singleton @DependsOn
try {
References.sort(beans, new References.Visitor<EnterpriseBeanInfo>(){
@Override
public String getName(final EnterpriseBeanInfo bean) {
return bean.ejbDeploymentId;
}
@Override
public Set<String> getReferences(final EnterpriseBeanInfo bean) {
return new LinkedHashSet<String>(bean.dependsOn);
}
});
} catch (CircularReferencesException e) {
// List<List> circuits = e.getCircuits();
// TODO Seems we lost circular reference detection, or we do it elsewhere and don't need it here
}
//
// Application Clients
//
this.buildClientModules(appModule, appInfo, jndiEncInfoBuilder);
//
// Webapps
//
this.buildWebModules(appModule, jndiEncInfoBuilder, appInfo);
//
// Final AppInfo creation
//
final List<URL> additionalLibraries = appModule.getAdditionalLibraries();
for (final URL url : additionalLibraries) {
final File file = toFile(url);
try {
appInfo.libs.add(file.getCanonicalPath());
} catch (IOException e) {
throw new OpenEJBException("Invalid application lib path " + file.getAbsolutePath());
}
}
if (appModule.getCmpMappings() != null) {
try {
appInfo.cmpMappingsXml = JpaJaxbUtil.marshal(EntityMappings.class, appModule.getCmpMappings());
} catch (JAXBException e) {
throw new OpenEJBException("Unable to marshal cmp entity mappings", e);
}
}
final ReportValidationResults reportValidationResults = new ReportValidationResults();
reportValidationResults.deploy(appModule);
logger.info("config.appLoaded", appInfo.path);
appInfo.webAppAlone = appModule.isWebapp();
return appInfo;
}
private void buildPojoConfiguration(final AppModule appModule, final AppInfo appInfo) {
for (final Map.Entry<String, PojoConfiguration> config : appModule.getPojoConfigurations().entrySet()) {
final IdPropertiesInfo info = new IdPropertiesInfo();
info.id = config.getKey();
info.properties.putAll(config.getValue().getProperties());
appInfo.pojoConfigurations.add(info);
}
}
private void buildAppServices(final AppModule appModule, final AppInfo appInfo) throws OpenEJBException {
final Collection<org.apache.openejb.config.sys.Service> services = appModule.getServices();
for (final org.apache.openejb.config.sys.Service service : services) {
final ServiceInfo info = this.configFactory.configureService(service, ServiceInfo.class);
appInfo.services.add(info);
}
}
private void buildAppResources(final AppModule module, final AppInfo info) {
for (final Resource def : module.getResources()) {
// the resource is already deployed
// however we keep its id to be able to undeployed it later
// note: if ApplicationWide property was specified
// we want this application be managed only by the container
// once deployed = not undeployed with the app
// so we skip the undeployement skipping the id
if (!def.getProperties().containsKey("ApplicationWide")) {
info.resourceIds.add(def.getId());
info.resourceAliases.addAll(def.getAliases());
}
}
}
private void buildClientModules(final AppModule appModule, final AppInfo appInfo, final JndiEncInfoBuilder jndiEncInfoBuilder) throws OpenEJBException {
for (final ClientModule clientModule : appModule.getClientModules()) {
final ApplicationClient applicationClient = clientModule.getApplicationClient();
final ClientInfo clientInfo = new ClientInfo();
clientInfo.description = applicationClient.getDescription();
clientInfo.displayName = applicationClient.getDisplayName();
clientInfo.path = clientModule.getJarLocation();
clientInfo.mainClass = clientModule.getMainClass();
clientInfo.localClients.addAll(clientModule.getLocalClients());
clientInfo.remoteClients.addAll(clientModule.getRemoteClients());
clientInfo.callbackHandler = applicationClient.getCallbackHandler();
clientInfo.moduleId = getClientModuleId(clientModule);
clientInfo.watchedResources.addAll(clientModule.getWatchedResources());
clientInfo.validationInfo = ValidatorBuilder.getInfo(clientModule.getValidationConfig());
clientInfo.uniqueId = clientModule.getUniqueId();
jndiEncInfoBuilder.build(applicationClient, clientModule.getJarLocation(), clientInfo.moduleId, clientModule.getModuleUri(), clientInfo.jndiEnc, clientInfo.jndiEnc);
appInfo.clients.add(clientInfo);
}
}
private void buildWebModules(final AppModule appModule, final JndiEncInfoBuilder jndiEncInfoBuilder, final AppInfo appInfo) throws OpenEJBException {
for (final WebModule webModule : appModule.getWebModules()) {
final WebApp webApp = webModule.getWebApp();
final WebAppInfo webAppInfo = new WebAppInfo();
webAppInfo.description = webApp.getDescription();
webAppInfo.displayName = webApp.getDisplayName();
webAppInfo.path = webModule.getJarLocation();
webAppInfo.moduleId = webModule.getModuleId();
webAppInfo.watchedResources.addAll(webModule.getWatchedResources());
webAppInfo.validationInfo = ValidatorBuilder.getInfo(webModule.getValidationConfig());
webAppInfo.uniqueId = webModule.getUniqueId();
webAppInfo.restApplications.addAll(webModule.getRestApplications());
webAppInfo.restClass.addAll(webModule.getRestClasses());
webAppInfo.ejbWebServices.addAll(webModule.getEjbWebServices());
webAppInfo.ejbRestServices.addAll(webModule.getEjbRestServices());
webAppInfo.jaxRsProviders.addAll(webModule.getJaxrsProviders());
for (final Map.Entry<String, Set<String>> entry : webModule.getWebAnnotatedClasses().entrySet()) {
final ClassListInfo info = new ClassListInfo();
info.name = entry.getKey();
info.list.addAll(entry.getValue());
webAppInfo.webAnnotatedClasses.add(info);
}
for (final Map.Entry<String, Set<String>> entry : webModule.getJsfAnnotatedClasses().entrySet()) {
final ClassListInfo info = new ClassListInfo();
info.name = entry.getKey();
info.list.addAll(entry.getValue());
webAppInfo.jsfAnnotatedClasses.add(info);
}
webAppInfo.host = webModule.getHost();
if (!webModule.isStandaloneModule() && USE_EAR_AS_CONTEXT_ROOT_BASE) {
webAppInfo.contextRoot = appModule.getModuleId() + "/" + webModule.getContextRoot();
} else {
webAppInfo.contextRoot = webModule.getContextRoot();
}
jndiEncInfoBuilder.build(webApp, webModule.getJarLocation(), webAppInfo.moduleId, webModule.getModuleUri(), webAppInfo.jndiEnc, webAppInfo.jndiEnc);
webAppInfo.portInfos.addAll(this.configureWebservices(webModule.getWebservices()));
// configureWebserviceSecurity(webAppInfo, webModule);: was empty
for (final Servlet servlet : webModule.getWebApp().getServlet()) {
final ServletInfo servletInfo = new ServletInfo();
servletInfo.servletName = servlet.getServletName();
servletInfo.servletClass = servlet.getServletClass();
servletInfo.mappings = webModule.getWebApp().getServletMappings(servletInfo.servletName);
for (ParamValue pv : servlet.getInitParam()) {
final ParamValueInfo pvi = new ParamValueInfo();
pvi.name = pv.getParamName();
pvi.value = pv.getParamValue();
servletInfo.initParams.add(pvi);
}
webAppInfo.servlets.add(servletInfo);
}
for (final Listener listener : webModule.getWebApp().getListener()) {
final ListenerInfo listenerInfo = new ListenerInfo();
listenerInfo.classname = listener.getListenerClass();
webAppInfo.listeners.add(listenerInfo);
}
for (final Filter filter : webModule.getWebApp().getFilter()) {
final FilterInfo filterInfo = new FilterInfo();
filterInfo.name = filter.getFilterName();
filterInfo.classname = filter.getFilterClass();
filterInfo.mappings = webModule.getWebApp().getFilterMappings(filter.getFilterName());
for (final ParamValue pv : filter.getInitParam()) {
filterInfo.initParams.put(pv.getParamName(), pv.getParamValue());
}
webAppInfo.filters.add(filterInfo);
}
appInfo.webApps.add(webAppInfo);
}
}
private void buildConnectorModules(final AppModule appModule, final AppInfo appInfo) throws OpenEJBException {
final String appId = appModule.getModuleId();
for (final ConnectorModule connectorModule : appModule.getConnectorModules()) {
//
// DEVELOPERS NOTE: if you change the id generation code here, you must change
// the id generation code in AutoConfig$AppResources
//
final Resources config = new Resources();
Connector connector = connectorModule.getConnector();
final ConnectorInfo connectorInfo = new ConnectorInfo();
connectorInfo.description = connector.getDescription();
connectorInfo.displayName = connector.getDisplayName();
connectorInfo.path = connectorModule.getJarLocation();
connectorInfo.moduleId = connectorModule.getModuleId();
connectorInfo.watchedResources.addAll(connectorModule.getWatchedResources());
connectorInfo.validationInfo = ValidatorBuilder.getInfo(connectorModule.getValidationConfig());
connectorInfo.uniqueId = connectorModule.getUniqueId();
connectorInfo.mbeans = connectorModule.getMbeans();
final List<URL> libraries = connectorModule.getLibraries();
for (final URL url : libraries) {
final File file = toFile(url);
try {
connectorInfo.libs.add(file.getCanonicalPath());
} catch (IOException e) {
throw new IllegalArgumentException("Invalid application lib path " + file.getAbsolutePath());
}
}
final ResourceAdapter resourceAdapter = connector.getResourceAdapter();
if (resourceAdapter.getResourceAdapterClass() != null) {
final String id = this.getId(connectorModule);
final String className = resourceAdapter.getResourceAdapterClass();
Resource resource = new Resource(id, className);
resource.setType(className);
resource.setClassName(className);
for (final ConfigProperty property : resourceAdapter.getConfigProperty()) {
final String name = property.getConfigPropertyName();
final String value = property.getConfigPropertyValue();
if (value != null) {
resource.getProperties().setProperty(name, value);
}
}
config.getResource().add(resource);
connectorInfo.resourceAdapter = configFactory.configureService(resource, ResourceInfo.class);
}
final OutboundResourceAdapter outbound = resourceAdapter.getOutboundResourceAdapter();
if (outbound != null) {
String transactionSupport = "none";
switch (outbound.getTransactionSupport()) {
case LOCAL_TRANSACTION:
transactionSupport = "local";
break;
case NO_TRANSACTION:
transactionSupport = "none";
break;
case XA_TRANSACTION:
transactionSupport = "xa";
break;
}
for (final ConnectionDefinition connection : outbound.getConnectionDefinition()) {
final String id = this.getId(connection, outbound, connectorModule);
final String className = connection.getManagedConnectionFactoryClass();
final String type = connection.getConnectionFactoryInterface();
Resource resource = new Resource(id, type);
resource.setType(type);
resource.setClassName(className);
Properties properties = resource.getProperties();
for (ConfigProperty property : connection.getConfigProperty()) {
String name = property.getConfigPropertyName();
String value = property.getConfigPropertyValue();
if (value != null) {
properties.setProperty(name, value);
}
}
properties.setProperty("TransactionSupport", transactionSupport);
if (connectorInfo.resourceAdapter != null) {
properties.setProperty("ResourceAdapter", connectorInfo.resourceAdapter.id);
}
config.getResource().add(resource);
ResourceInfo resourceInfo = configFactory.configureService(resource, ResourceInfo.class);
connectorInfo.outbound.add(resourceInfo);
}
}
final InboundResourceadapter inbound = resourceAdapter.getInboundResourceAdapter();
if (inbound != null) {
for (final MessageListener messageListener : inbound.getMessageAdapter().getMessageListener()) {
final String id = this.getId(messageListener, inbound, connectorModule);
final Container container = new Container(id, "MESSAGE", null);
final Properties properties = container.getProperties();
properties.setProperty("ResourceAdapter", connectorInfo.resourceAdapter.id);
properties.setProperty("MessageListenerInterface", messageListener.getMessageListenerType());
properties.setProperty("ActivationSpecClass", messageListener.getActivationSpec().getActivationSpecClass());
config.getContainer().add(container);
MdbContainerInfo mdbContainerInfo = configFactory.configureService(container, MdbContainerInfo.class);
connectorInfo.inbound.add(mdbContainerInfo);
}
}
for (final AdminObject adminObject : resourceAdapter.getAdminObject()) {
final String id = this.getId(adminObject, resourceAdapter, connectorModule);
final String className = adminObject.getAdminObjectClass();
final String type = adminObject.getAdminObjectInterface();
Resource resource = new Resource(id, type);
resource.setType(type);
resource.setClassName(className);
Properties properties = resource.getProperties();
for (ConfigProperty property : adminObject.getConfigProperty()) {
String name = property.getConfigPropertyName();
String value = property.getConfigPropertyValue();
if (value != null) {
properties.setProperty(name, value);
}
}
config.getResource().add(resource);
ResourceInfo resourceInfo = configFactory.configureService(resource, ResourceInfo.class);
connectorInfo.adminObject.add(resourceInfo);
}
final File file = new File("/tmp/resources.xml");
try {
final OutputStream write = IO.write(file);
JaxbOpenejb.marshal(Resources.class, config, write);
write.flush();
write.close();
} catch (Exception e) {
e.printStackTrace();
}
appInfo.connectors.add(connectorInfo);
}
}
private String getId(final AdminObject adminObject, final ResourceAdapter resourceAdapter, final ConnectorModule connectorModule) {
final String id;
if (adminObject.getId() != null) {
id = adminObject.getId();
} else if (resourceAdapter.getAdminObject().size() == 1) {
id = connectorModule.getModuleId();
} else {
id = connectorModule.getModuleId() + "-" + adminObject.getAdminObjectInterface();
}
return id;
}
private String getId(final MessageListener messageListener, final InboundResourceadapter inbound, final ConnectorModule connectorModule) {
final String id;
if (messageListener.getId() != null) {
id = messageListener.getId();
} else if (inbound.getMessageAdapter().getMessageListener().size() == 1) {
id = connectorModule.getModuleId();
} else {
id = connectorModule.getModuleId() + "-" + messageListener.getMessageListenerType();
}
return id;
}
private String getId(final ConnectionDefinition connection, final OutboundResourceAdapter outbound, final ConnectorModule connectorModule) {
final String id;
if (connection.getId() != null) {
id = connection.getId();
} else if (outbound.getConnectionDefinition().size() == 1) {
id = connectorModule.getModuleId();
} else {
id = connectorModule.getModuleId() + "-" + connection.getConnectionFactoryInterface();
}
return id;
}
private String getId(final ConnectorModule connectorModule) {
String id = connectorModule.getConnector().getResourceAdapter().getId();
if (id == null) {
id = connectorModule.getModuleId() + "RA";
}
return id;
}
private void buildPersistenceModules(final AppModule appModule, final AppInfo appInfo) {
for (final PersistenceModule persistenceModule : appModule.getPersistenceModules()) {
final String rootUrl = persistenceModule.getRootUrl();
final Persistence persistence = persistenceModule.getPersistence();
for (final PersistenceUnit persistenceUnit : persistence.getPersistenceUnit()) {
final PersistenceUnitInfo info = new PersistenceUnitInfo();
info.id = persistenceUnit.getName() + " " + rootUrl.hashCode();
info.name = persistenceUnit.getName();
info.watchedResources.addAll(persistenceModule.getWatchedResources());
info.persistenceUnitRootUrl = rootUrl;
info.provider = persistenceUnit.getProvider();
info.transactionType = persistenceUnit.getTransactionType().toString();
info.webappName = findRelatedWebApp(appModule, rootUrl);
final Boolean excludeUnlistedClasses = persistenceUnit.isExcludeUnlistedClasses();
info.excludeUnlistedClasses = persistenceUnit.isScanned() || (excludeUnlistedClasses != null && excludeUnlistedClasses);
info.jtaDataSource = persistenceUnit.getJtaDataSource();
info.nonJtaDataSource = persistenceUnit.getNonJtaDataSource();
info.jarFiles.addAll(persistenceUnit.getJarFile());
info.classes.addAll(persistenceUnit.getClazz());
info.mappingFiles.addAll(persistenceUnit.getMappingFile());
info.persistenceXMLSchemaVersion = persistence.getVersion();
info.sharedCacheMode = persistenceUnit.getSharedCacheMode().toString();
info.validationMode = persistenceUnit.getValidationMode().toString();
// Handle Properties
info.properties.putAll(persistenceUnit.getProperties());
PersistenceProviderProperties.apply(appModule.getClassLoader(), info);
// Persistence Unit Root Url
appInfo.persistenceUnits.add(info);
}
}
}
@SuppressWarnings("unchecked")
private String findRelatedWebApp(final AppModule appModule, final String rootUrl) {
for (final WebModule webModule : appModule.getWebModules()) {
final List<URL> pXmls = (List<URL>) webModule.getAltDDs().get(DeploymentLoader.EAR_WEBAPP_PERSISTENCE_XML_JARS);
if (pXmls != null) {
for (final URL url : pXmls) {
if (url.toExternalForm().contains(rootUrl)) {
return webModule.getModuleId();
}
}
}
}
return null;
}
public static class PersistenceProviderProperties {
public static final String OPENJPA_RUNTIME_UNENHANCED_CLASSES = "openjpa.RuntimeUnenhancedClasses";
public static final String DEFAULT_RUNTIME_UNENHANCED_CLASSES = "supported";
public static final String REMOVE_DEFAULT_RUNTIME_UNENHANCED_CLASSES = "disable";
public static final String TABLE_PREFIX = "openejb.jpa.table_prefix";
public static final String OPENJPA_METADATA_REPOSITORY = "openjpa.MetaDataRepository";
public static final String PREFIX_METADATA_REPOSITORY = "org.apache.openejb.openjpa.PrefixMappingRepository";
public static final String OPENJPA_SEQUENCE = "openjpa.Sequence";
public static final String PREFIX_SEQUENCE = "org.apache.openejb.openjpa.PrefixTableJdbcSeq";
public static final String PROVIDER_PROP = "javax.persistence.provider";
public static final String TRANSACTIONTYPE_PROP = "javax.persistence.transactionType";
public static final String JTADATASOURCE_PROP = "javax.persistence.jtaDataSource";
public static final String NON_JTADATASOURCE_PROP = "javax.persistence.nonJtaDataSource";
private static final String DEFAULT_PERSISTENCE_PROVIDER = "org.apache.openjpa.persistence.PersistenceProviderImpl";
public static final String HIBERNATE_TRANSACTION_MANAGER_LOOKUP_CLASS = "hibernate.transaction.manager_lookup_class";
public static final String HIBERNATE_JTA_PLATFORM = "hibernate.transaction.jta.platform";
public static final String HIBERNATE_EJB_NAMING_STRATEGY_PROP = "hibernate.ejb.naming_strategy";
private static final String HIBERNATE_EJB_NAMING_STRATEGY = "org.apache.openejb.jpa.integration.hibernate.PrefixNamingStrategy";
private static final String ECLIPSELINK_SESSION_CUSTOMIZER = "eclipselink.session.customizer";
private static final String PREFIX_SESSION_CUSTOMIZER = "org.apache.openejb.jpa.integration.eclipselink.PrefixSessionCustomizer";
private static String providerEnv;
private static String transactionTypeEnv;
private static String jtaDataSourceEnv;
private static String nonJtaDataSourceEnv;
static {
providerEnv = SystemInstance.get().getOptions().get(PROVIDER_PROP, (String) null);
transactionTypeEnv = SystemInstance.get().getOptions().get(TRANSACTIONTYPE_PROP, (String) null);
jtaDataSourceEnv = SystemInstance.get().getOptions().get(JTADATASOURCE_PROP, (String) null);
nonJtaDataSourceEnv = SystemInstance.get().getOptions().get(NON_JTADATASOURCE_PROP, (String) null);
}
/**
* @param classLoader the temp classloader, take care to only use getResource here
* @param info the persistence unit info
*/
private static void apply(final ClassLoader classLoader, final PersistenceUnitInfo info) {
overrideFromSystemProp(info);
// The result is that OpenEJB-specific configuration can be avoided when
// using OpenEJB + Hibernate or another vendor. A second benefit is that
// if another vendor is used in production, the value will automatically
// be reset for using OpenEJB in the test environment. Ensuring the strategy
// doesn't start with "org.hibernate.transaction" allows for a custom lookup
// strategy to be used and not overridden.
// DMB: This whole block could be a map, but I left it this way just
// in case we decided we wanted to do other custom handing for the
// providers listed.
if ("org.hibernate.ejb.HibernatePersistence".equals(info.provider)){
// Apply the overrides that apply to all persistence units of this provider
override(info, "hibernate");
String className = info.properties.getProperty(HIBERNATE_JTA_PLATFORM);
if (className == null) {
className = info.properties.getProperty(HIBERNATE_TRANSACTION_MANAGER_LOOKUP_CLASS);
}
// info.persistenceUnitRootUrl = null; // to avoid HHH015010
final String prefix = info.properties.getProperty(TABLE_PREFIX);
if (prefix != null) {
if (info.properties.containsKey(HIBERNATE_EJB_NAMING_STRATEGY_PROP)) {
logger.warning("can't statisfy table prefix since you provided a " + HIBERNATE_EJB_NAMING_STRATEGY_PROP + " property");
} else {
// to pass the config to the impl
info.properties.setProperty(HIBERNATE_EJB_NAMING_STRATEGY_PROP, HIBERNATE_EJB_NAMING_STRATEGY);
}
}
if (className == null || className.startsWith("org.hibernate.transaction") || className.startsWith("org.hibernate.service.jta.platform")){
// hibernate 4
String key = HIBERNATE_JTA_PLATFORM;
String value = MakeTxLookup.HIBERNATE_NEW_FACTORY;
if (classLoader.getResource(ClassLoaderUtil.resourceName("org.hibernate.service.jta.platform.spi.JtaPlatform")) == null) {
// hibernate 3. In the worse case it is set with a hibernate 4 and hibernate will convert it.
key = HIBERNATE_TRANSACTION_MANAGER_LOOKUP_CLASS;
value = MakeTxLookup.HIBERNATE_FACTORY;
}
if (classLoader.getResource(ClassLoaderUtil.resourceName(value)) != null) {
info.properties.setProperty(key, value);
logger.debug("Adjusting PersistenceUnit(name=" + info.name + ") property to " + key + "=" + value);
} else {
logger.debug("can't adjust hibernate jta bridge to openejb one");
}
}
} else if ("oracle.toplink.essentials.PersistenceProvider".equals(info.provider) ||
"oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider".equals(info.provider) ){
// Apply the overrides that apply to all persistence units of this provider
override(info, "toplink");
final String lookupProperty = "toplink.target-server";
final String openejbLookupClass = MakeTxLookup.TOPLINK_FACTORY;
final String prefix = info.properties.getProperty(TABLE_PREFIX);
if (prefix != null) {
logger.warning("table prefix feature is not supported for toplink");
}
final String className = info.properties.getProperty(lookupProperty);
if (className == null || className.startsWith("oracle.toplink.transaction")){
info.properties.setProperty(lookupProperty, openejbLookupClass);
logger.debug("Adjusting PersistenceUnit(name="+info.name+") property to "+lookupProperty+"="+openejbLookupClass);
}
} else if ("org.eclipse.persistence.jpa.PersistenceProvider".equals(info.provider) || "org.eclipse.persistence.jpa.osgi.PersistenceProvider".equals(info.provider)){
// Apply the overrides that apply to all persistence units of this provider
override(info, "eclipselink");
final String lookupProperty = "eclipselink.target-server";
final String openejbLookupClass = MakeTxLookup.ECLIPSELINK_FACTORY;
final String className = info.properties.getProperty(lookupProperty);
if (className == null || className.startsWith("org.eclipse.persistence.transaction")){
if (classLoader.getResource(ClassLoaderUtil.resourceName(openejbLookupClass)) != null) {
info.properties.setProperty(lookupProperty, openejbLookupClass);
logger.debug("Adjusting PersistenceUnit(name="+info.name+") property to "+lookupProperty+"="+openejbLookupClass);
} else {
logger.debug("Can't adjusting PersistenceUnit(name="+info.name+") property to " + lookupProperty + "=" + openejbLookupClass + ", using default one");
}
}
final String prefix = info.properties.getProperty(TABLE_PREFIX);
if (prefix != null) {
if (info.properties.containsKey(ECLIPSELINK_SESSION_CUSTOMIZER)) {
logger.warning("can't statisfy table prefix since you provided a " + ECLIPSELINK_SESSION_CUSTOMIZER + " property, add a call to org.apache.openejb.jpa.integration.eclipselink.PrefixSessionCustomizer");
} else {
// force eager loading otherwise we'll not get the prefix in the customizer
info.properties.setProperty(EntityManagerFactoryCallable.OPENEJB_JPA_INIT_ENTITYMANAGER, "true");
// to pass the config to the impl
info.properties.setProperty(ECLIPSELINK_SESSION_CUSTOMIZER, PREFIX_SESSION_CUSTOMIZER);
}
}
} else if (info.provider == null || "org.apache.openjpa.persistence.PersistenceProviderImpl".equals(info.provider)){
// Apply the overrides that apply to all persistence units of this provider
override(info, "openjpa");
final String existing = info.properties.getProperty(OPENJPA_RUNTIME_UNENHANCED_CLASSES);
if (existing == null){
info.properties.setProperty(OPENJPA_RUNTIME_UNENHANCED_CLASSES, DEFAULT_RUNTIME_UNENHANCED_CLASSES);
logger.debug("Adjusting PersistenceUnit(name=" + info.name + ") property to "
+ OPENJPA_RUNTIME_UNENHANCED_CLASSES + "=" + DEFAULT_RUNTIME_UNENHANCED_CLASSES);
} else if (REMOVE_DEFAULT_RUNTIME_UNENHANCED_CLASSES.equals(existing.trim())) {
info.properties.remove(OPENJPA_RUNTIME_UNENHANCED_CLASSES);
logger.info("Adjusting PersistenceUnit(name=" + info.name + ") removing property "
+ OPENJPA_RUNTIME_UNENHANCED_CLASSES);
}
final String prefix = info.properties.getProperty(TABLE_PREFIX);
if (prefix != null) {
final String mapping = info.properties.getProperty(OPENJPA_METADATA_REPOSITORY);
if (mapping != null && !"org.apache.openjpa.jdbc.meta.MappingRepository".equals(mapping)) {
throw new OpenEJBRuntimeException("can't honor table prefixes since you provided a custom mapping repository: " + mapping);
}
info.properties.setProperty(OPENJPA_METADATA_REPOSITORY, PREFIX_METADATA_REPOSITORY + "(prefix=" + prefix + ")");
if (!info.properties.containsKey(OPENJPA_SEQUENCE)) {
info.properties.setProperty(OPENJPA_SEQUENCE, PREFIX_SEQUENCE + "(prefix=" + prefix + ")");
} else {
logger.warning("you configured a custom sequence so the prefix will be ignored");
}
}
final Set<String> keys = new HashSet<String>(info.properties.stringPropertyNames());
for (final String key : keys) {
if (key.matches("openjpa.Connection(DriverName|URL|UserName|Password)")) {
final Object o = info.properties.remove(key);
logger.warning("Removing PersistenceUnit(name=" + info.name + ") property " + key + "=" + o + " [not valid in a container environment]");
} else { // try to convert it if necessary
final JPAPropertyConverter.Pair pair = JPAPropertyConverter.toOpenJPAValue(key, info.properties.getProperty(key), info.properties);
if (pair != null && !info.properties.containsKey(pair.getKey())) {
logger.info("Converting PersistenceUnit(name=" + info.name + ") property "
+ key + "=" + info.properties.getProperty(key) + " to " + pair.toString());
info.properties.remove(key);
info.properties.setProperty(pair.getKey(), pair.getValue());
}
}
}
}
// Apply the overrides that apply to just this persistence unit
override(info);
}
private static void overrideFromSystemProp(final PersistenceUnitInfo info) {
if (providerEnv != null) {
info.provider = providerEnv;
}
if (info.provider == null) {
info.provider = DEFAULT_PERSISTENCE_PROVIDER;
}
if (jtaDataSourceEnv != null) {
info.jtaDataSource = jtaDataSourceEnv;
}
if (transactionTypeEnv != null) {
info.transactionType = transactionTypeEnv.toUpperCase();
}
if (nonJtaDataSourceEnv != null) {
info.nonJtaDataSource = nonJtaDataSourceEnv;
}
}
private static void override(final PersistenceUnitInfo info) {
override(info, info.name);
}
private static void override(final PersistenceUnitInfo info, final String prefix) {
final Properties overrides = ConfigurationFactory.getSystemProperties(prefix, "PersistenceUnit");
for (final Map.Entry<Object, Object> entry : overrides.entrySet()) {
final String property = (String) (prefix.equalsIgnoreCase(info.name) ? entry.getKey() : prefix + "." + entry.getKey());
final String value = (String) entry.getValue();
if ("openjpa.Log".equals(property) && info.properties.containsKey("openjpa.Log")) { // we set a default
continue;
}
if (info.properties.containsKey(property)){
logger.debug("Overriding persistence-unit "+info.name +" property " + property + "="+value);
} else {
logger.debug("Adding persistence-unit "+info.name +" property " + property + "="+value);
}
info.properties.put(property, value);
if (property.endsWith("openjpa.Specification")) {
info.persistenceXMLSchemaVersion = value.replace("JPA ", "");
}
}
}
}
private static String getClientModuleId(final ClientModule clientModule) {
return clientModule.getModuleId();
}
private List<PortInfo> configureWebservices(final Webservices webservices) {
final List<PortInfo> portMap = new ArrayList<PortInfo>();
if (webservices == null) {
return portMap;
}
for (final WebserviceDescription desc : webservices.getWebserviceDescription()) {
final String wsdlFile = desc.getWsdlFile();
final String serviceName = desc.getWebserviceDescriptionName();
for (final PortComponent port : desc.getPortComponent()) {
final PortInfo portInfo = new PortInfo();
final ServiceImplBean serviceImplBean = port.getServiceImplBean();
portInfo.serviceId = desc.getId();
portInfo.portId = port.getId();
portInfo.serviceLink = serviceImplBean.getEjbLink();
if (portInfo.serviceLink == null) {
portInfo.serviceLink = serviceImplBean.getServletLink();
}
portInfo.seiInterfaceName = port.getServiceEndpointInterface();
portInfo.portName = port.getPortComponentName();
portInfo.binding = port.getProtocolBinding();
portInfo.serviceName = serviceName;
portInfo.wsdlFile = wsdlFile;
portInfo.mtomEnabled = port.isEnableMtom();
portInfo.wsdlPort = port.getWsdlPort();
portInfo.wsdlService = port.getWsdlService();
portInfo.location = port.getLocation();
final List<HandlerChainInfo> handlerChains = ConfigurationFactory.toHandlerChainInfo(port.getHandlerChains());
portInfo.handlerChains.addAll(handlerChains);
// todo configure jaxrpc mappings here
portMap.add(portInfo);
}
}
return portMap;
}
/*
* left package-local for a unit test
*/
void configureWebserviceSecurity(final EjbJarInfo ejbJarInfo, final EjbModule ejbModule) {
final Object altDD = ejbModule.getOpenejbJar();
final List<PortInfo> infoList = ejbJarInfo.portInfos;
this.configureWebserviceScurity(infoList, altDD);
}
private void configureWebserviceScurity(final List<PortInfo> infoList, final Object altDD) {
if (altDD == null || (! (altDD instanceof OpenejbJar))) return;
final OpenejbJar openejbJar = (OpenejbJar) altDD;
final Map<String, EjbDeployment> deploymentsByEjbName = openejbJar.getDeploymentsByEjbName();
for (final PortInfo portInfo : infoList) {
final EjbDeployment deployment = deploymentsByEjbName.get(portInfo.serviceLink);
if (deployment == null) continue;
portInfo.realmName = deployment.getProperties().getProperty("webservice.security.realm");
portInfo.securityRealmName = deployment.getProperties().getProperty("webservice.security.securityRealm");
if (deployment.getProperties().getProperty("webservice.security.transportGarantee") != null) {
portInfo.transportGuarantee = deployment.getProperties().getProperty("webservice.security.transportGarantee");
} else {
portInfo.transportGuarantee = "NONE";
}
if (deployment.getProperties().getProperty("webservice.security.authMethod") != null) {
portInfo.authMethod = deployment.getProperties().getProperty("webservice.security.authMethod");
} else {
portInfo.authMethod = "NONE";
}
portInfo.properties = deployment.getProperties();
}
}
private static boolean skipMdb(final EnterpriseBeanInfo bean) {
return bean instanceof MessageDrivenBeanInfo && SystemInstance.get().hasProperty("openejb.geronimo");
}
}