/* * 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.Extensions; import org.apache.openejb.OpenEJBException; import org.apache.openejb.Vendor; import org.apache.openejb.api.Proxy; import org.apache.openejb.api.resource.PropertiesResourceProvider; import org.apache.openejb.api.resource.Template; import org.apache.openejb.assembler.classic.AppInfo; import org.apache.openejb.assembler.classic.Assembler; import org.apache.openejb.assembler.classic.BmpEntityContainerInfo; import org.apache.openejb.assembler.classic.ClientInfo; import org.apache.openejb.assembler.classic.CmpEntityContainerInfo; import org.apache.openejb.assembler.classic.ConnectionManagerInfo; import org.apache.openejb.assembler.classic.ConnectorInfo; import org.apache.openejb.assembler.classic.ContainerInfo; import org.apache.openejb.assembler.classic.ContainerSystemInfo; import org.apache.openejb.assembler.classic.DeploymentExceptionManager; import org.apache.openejb.assembler.classic.EjbJarInfo; import org.apache.openejb.assembler.classic.FacilitiesInfo; import org.apache.openejb.assembler.classic.HandlerChainInfo; import org.apache.openejb.assembler.classic.HandlerInfo; import org.apache.openejb.assembler.classic.JndiContextInfo; import org.apache.openejb.assembler.classic.ManagedContainerInfo; import org.apache.openejb.assembler.classic.MdbContainerInfo; import org.apache.openejb.assembler.classic.OpenEjbConfiguration; import org.apache.openejb.assembler.classic.OpenEjbConfigurationFactory; import org.apache.openejb.assembler.classic.ProxyFactoryInfo; import org.apache.openejb.assembler.classic.ResourceInfo; import org.apache.openejb.assembler.classic.SecurityServiceInfo; import org.apache.openejb.assembler.classic.ServiceInfo; import org.apache.openejb.assembler.classic.SingletonSessionContainerInfo; import org.apache.openejb.assembler.classic.StatefulSessionContainerInfo; import org.apache.openejb.assembler.classic.StatelessSessionContainerInfo; import org.apache.openejb.assembler.classic.TransactionServiceInfo; import org.apache.openejb.assembler.classic.WebAppInfo; import org.apache.openejb.component.ClassLoaderEnricher; import org.apache.openejb.config.sys.AbstractService; import org.apache.openejb.config.sys.AdditionalDeployments; import org.apache.openejb.config.sys.ConnectionManager; import org.apache.openejb.config.sys.Container; import org.apache.openejb.config.sys.Deployments; import org.apache.openejb.config.sys.JaxbOpenejb; import org.apache.openejb.config.sys.JndiProvider; import org.apache.openejb.config.sys.Openejb; import org.apache.openejb.config.sys.ProxyFactory; import org.apache.openejb.config.sys.Resource; import org.apache.openejb.config.sys.SecurityService; import org.apache.openejb.config.sys.Service; import org.apache.openejb.config.sys.ServiceProvider; import org.apache.openejb.config.sys.TransactionManager; import org.apache.openejb.core.ParentClassLoaderFinder; import org.apache.openejb.jee.Application; import org.apache.openejb.jee.EjbJar; import org.apache.openejb.jee.EnterpriseBean; import org.apache.openejb.jee.EnvEntry; import org.apache.openejb.jee.Handler; import org.apache.openejb.jee.HandlerChain; import org.apache.openejb.jee.HandlerChains; import org.apache.openejb.jee.ParamValue; import org.apache.openejb.jee.SessionBean; import org.apache.openejb.loader.FileUtils; import org.apache.openejb.loader.Files; import org.apache.openejb.loader.IO; import org.apache.openejb.loader.Options; import org.apache.openejb.loader.ProvisioningUtil; import org.apache.openejb.loader.SystemInstance; import org.apache.openejb.monitoring.LocalMBeanServer; import org.apache.openejb.resource.jdbc.DataSourceFactory; import org.apache.openejb.resource.jdbc.pool.DataSourceCreator; import org.apache.openejb.resource.jdbc.pool.DefaultDataSourceCreator; import org.apache.openejb.util.JavaSecurityManagers; import org.apache.openejb.util.LogCategory; import org.apache.openejb.util.Logger; import org.apache.openejb.util.Messages; import org.apache.openejb.util.PropertyPlaceHolderHelper; import org.apache.openejb.util.References; import org.apache.openejb.util.SuperProperties; import org.apache.openejb.util.URISupport; import org.apache.openejb.util.URLs; import org.apache.openejb.util.classloader.URLClassLoaderFirst; import org.apache.openejb.util.proxy.QueryProxy; import org.apache.xbean.finder.IAnnotationFinder; import org.apache.xbean.finder.MetaAnnotatedClass; import org.apache.xbean.recipe.ObjectRecipe; import org.apache.xbean.recipe.Option; import javax.ejb.embeddable.EJBContainer; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; 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 static org.apache.openejb.config.DeploymentsResolver.DEPLOYMENTS_CLASSPATH_PROPERTY; import static org.apache.openejb.config.ServiceUtils.implies; @SuppressWarnings("UnusedDeclaration") public class ConfigurationFactory implements OpenEjbConfigurationFactory { public static final String OPENEJB_JDBC_DATASOURCE_CREATOR = "openejb.jdbc.datasource-creator"; public static final String ADDITIONAL_DEPLOYMENTS = "conf/deployments.xml"; static final String CONFIGURATION_PROPERTY = "openejb.configuration"; static final String CONF_FILE_PROPERTY = "openejb.conf.file"; private static final String DEBUGGABLE_VM_HACKERY_PROPERTY = "openejb.debuggable-vm-hackery"; protected static final String VALIDATION_SKIP_PROPERTY = "openejb.validation.skip"; private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, ConfigurationFactory.class); private static final Messages messages = new Messages(ConfigurationFactory.class); private static final String IGNORE_DEFAULT_VALUES_PROP = "IgnoreDefaultValues"; private static final boolean WSDL4J_AVAILABLE = exists("javax.wsdl.xml.WSDLLocator"); private String configLocation; private OpenEjbConfiguration sys; private Openejb openejb; private final DynamicDeployer deployer; private final DeploymentLoader deploymentLoader; private final boolean offline; private final boolean serviceTypeIsAdjustable; // offline is a bit different from this and offline could be off and this on private static final String CLASSPATH_AS_EAR = "openejb.deployments.classpath.ear"; static final String WEBSERVICES_ENABLED = "openejb.webservices.enabled"; static final String OFFLINE_PROPERTY = "openejb.offline"; public ConfigurationFactory() { this(!shouldAutoDeploy()); } private static boolean exists(final String s) { try { ConfigurationFactory.class.getClassLoader().loadClass(s); return true; } catch (final ClassNotFoundException | NoClassDefFoundError e) { return false; } } private static boolean shouldAutoDeploy() { final Options options = SystemInstance.get().getOptions(); final boolean b = options.get(ConfigurationFactory.OFFLINE_PROPERTY, false); return options.get("tomee.autoconfig", !b); } public ConfigurationFactory(final boolean offline) { this(offline, (DynamicDeployer) null); } public ConfigurationFactory(final boolean offline, final DynamicDeployer preAutoConfigDeployer) { JavaSecurityManagers.setSystemProperty("bval.in-container", JavaSecurityManagers.getSystemProperty("bval.in-container","true")); this.offline = offline; this.serviceTypeIsAdjustable = SystemInstance.get().getOptions().get("openejb.service-type-adjustement", true); this.deploymentLoader = new DeploymentLoader(); LocalMBeanServer.reset(); final Options options = SystemInstance.get().getOptions(); if (SystemInstance.get().getComponent(DataSourceCreator.class) == null) { final String creator = options.get(OPENEJB_JDBC_DATASOURCE_CREATOR, (String) null); if (creator == null) { SystemInstance.get().setComponent(DataSourceCreator.class, new DefaultDataSourceCreator()); } else { try { SystemInstance.get().setComponent(DataSourceCreator.class, DataSourceFactory.creator(creator, false)); } catch (final Exception e) { logger.error("can't load " + creator + " will use the default creator", e); SystemInstance.get().setComponent(DataSourceCreator.class, new DefaultDataSourceCreator()); } } } if (SystemInstance.get().getComponent(ClassLoaderEnricher.class) == null) { SystemInstance.get().setComponent(ClassLoaderEnricher.class, new ClassLoaderEnricher()); } SystemInstance.get().setComponent(ConfigurationFactory.class, this); // annotation deployer encapsulate some logic, to be able to push to it some config // we give the ability here to get the internal deployer to push the config values final AnnotationDeployer annotationDeployer = new AnnotationDeployer(); final BeanProperties beanProperties = new BeanProperties(); final AppContextConfigDeployer appContextConfigDeployer = new AppContextConfigDeployer(annotationDeployer.getEnvEntriesPropertiesDeployer(), beanProperties); final Chain chain = new Chain(); chain.add(new SystemPropertiesOverride()); chain.add(new GeneratedClientModules.Add()); chain.add(new ApplicationComposerDeployer()); // before read descriptors and moreover AnnotationDeploer chain.add(new ReadDescriptors()); chain.add(appContextConfigDeployer); chain.add(new ApplicationProperties()); chain.add(new ModuleProperties()); chain.add(new LegacyProcessor()); chain.add(annotationDeployer); chain.add(beanProperties); chain.add(new ConfigurationDeployer()); // after annotation deployer and read descriptors are the only constraints chain.add(new ProxyBeanClassUpdate()); chain.add(new GeneratedClientModules.Prune()); chain.add(new ClearEmptyMappedName()); //START SNIPPET: code if (!options.get(VALIDATION_SKIP_PROPERTY, false)) { chain.add(new ValidateModules()); } else { DeploymentLoader.logger.info("validationDisabled", VALIDATION_SKIP_PROPERTY); } //END SNIPPET: code chain.add(new InitEjbDeployments()); if (options.get(DEBUGGABLE_VM_HACKERY_PROPERTY, false)) { chain.add(new DebuggableVmHackery()); } if (options.get(WEBSERVICES_ENABLED, true) && WSDL4J_AVAILABLE) { chain.add(new WsDeployer()); } else { chain.add(new RemoveWebServices()); } chain.add(new CmpJpaConversion()); // By default all vendor support is enabled final Set<Vendor> support = SystemInstance.get().getOptions().getAll("openejb.vendor.config", Vendor.values()); if (support.contains(Vendor.GERONIMO) || SystemInstance.get().hasProperty("openejb.geronimo")) { chain.add(new OpenEjb2Conversion()); } if (support.contains(Vendor.GLASSFISH)) { chain.add(new SunConversion()); } if (support.contains(Vendor.WEBLOGIC)) { chain.add(new WlsConversion()); } if (SystemInstance.get().hasProperty("openejb.geronimo")) { // must be after CmpJpaConversion since it adds new persistence-context-refs chain.add(new GeronimoMappedName()); } if (null != preAutoConfigDeployer) { chain.add(preAutoConfigDeployer); } chain.add(new ConvertDataSourceDefinitions()); chain.add(new ConvertJMSConnectionFactoryDefinitions()); chain.add(new ConvertJMSDestinationDefinitions()); chain.add(new CleanEnvEntries()); chain.add(new LinkBuiltInTypes()); chain.add(new ActivationConfigPropertyOverride()); if (offline) { final AutoConfig autoConfig = new AutoConfig(this); autoConfig.autoCreateResources(false); autoConfig.autoCreateContainers(false); chain.add(autoConfig); } else { chain.add(new AutoConfig(this)); } chain.add(new ApplyOpenejbJar()); chain.add(new MappedNameBuilder()); chain.add(new OutputGeneratedDescriptors()); // chain.add(new MergeWebappJndiContext()); this.deployer = chain; } public ConfigurationFactory(final boolean offline, final OpenEjbConfiguration configuration) { this(offline, (DynamicDeployer) null, configuration); } public ConfigurationFactory(final boolean offline, final DynamicDeployer preAutoConfigDeployer, final OpenEjbConfiguration configuration) { this(offline, preAutoConfigDeployer); sys = configuration; } public ConfigurationFactory(final boolean offline, final Chain deployerChain, final OpenEjbConfiguration configuration) { this.offline = offline; this.deploymentLoader = new DeploymentLoader(); this.deployer = deployerChain; this.sys = configuration; this.serviceTypeIsAdjustable = true; } public boolean isOffline() { return offline; } public static List<HandlerChainInfo> toHandlerChainInfo(final HandlerChains chains) { final List<HandlerChainInfo> handlerChains = new ArrayList<HandlerChainInfo>(); if (chains == null) { return handlerChains; } for (final HandlerChain handlerChain : chains.getHandlerChain()) { final HandlerChainInfo handlerChainInfo = new HandlerChainInfo(); handlerChainInfo.serviceNamePattern = handlerChain.getServiceNamePattern(); handlerChainInfo.portNamePattern = handlerChain.getPortNamePattern(); handlerChainInfo.protocolBindings.addAll(handlerChain.getProtocolBindings()); for (final Handler handler : handlerChain.getHandler()) { final HandlerInfo handlerInfo = new HandlerInfo(); handlerInfo.handlerName = handler.getHandlerName(); handlerInfo.handlerClass = handler.getHandlerClass(); handlerInfo.soapHeaders.addAll(handler.getSoapHeader()); handlerInfo.soapRoles.addAll(handler.getSoapRole()); for (final ParamValue param : handler.getInitParam()) { handlerInfo.initParams.setProperty(param.getParamName(), param.getParamValue()); } handlerChainInfo.handlers.add(handlerInfo); } handlerChains.add(handlerChainInfo); } return handlerChains; } public static class ProxyBeanClassUpdate implements DynamicDeployer { @SuppressWarnings("unchecked") @Override public AppModule deploy(final AppModule appModule) throws OpenEJBException { for (final EjbModule module : appModule.getEjbModules()) { for (final EnterpriseBean eb : module.getEjbJar().getEnterpriseBeans()) { if (!(eb instanceof SessionBean)) { continue; } final SessionBean bean = (SessionBean) eb; final Class<?> ejbClass; try { ejbClass = module.getClassLoader().loadClass(bean.getEjbClass()); } catch (final ClassNotFoundException e) { logger.warning("can't load " + bean.getEjbClass()); continue; } final Class<?> proxyClass; if (ejbClass.isInterface()) { // dynamic proxy implementation bean.setLocal(ejbClass.getName()); final Proxy proxyAnnotation = (Proxy) new MetaAnnotatedClass(ejbClass).getAnnotation(Proxy.class); if (proxyAnnotation != null) { proxyClass = proxyAnnotation.value(); } else { proxyClass = QueryProxy.class; } bean.setProxy(proxyClass.getName()); } else { continue; } for (final EnvEntry entry : bean.getEnvEntry()) { if ("java:comp/env/implementingInterfaceClass".equals(entry.getName())) { entry.setEnvEntryValue(ejbClass.getName()); } } } } return appModule; } } public static class Chain implements DynamicDeployer { private final List<DynamicDeployer> chain = new ArrayList<DynamicDeployer>(); public boolean add(final DynamicDeployer o) { return chain.add(o); } @Override public AppModule deploy(AppModule appModule) throws OpenEJBException { for (final DynamicDeployer deployer : chain) { appModule = deployer.deploy(appModule); } return appModule; } } @Override public void init(final Properties props) throws OpenEJBException { configLocation = props.getProperty(CONF_FILE_PROPERTY); if (configLocation == null) { configLocation = props.getProperty(CONFIGURATION_PROPERTY); } configLocation = ConfigUtils.searchForConfiguration(configLocation); if (configLocation != null) { logger.info("TomEE configuration file is '" + configLocation + "'"); props.setProperty(CONFIGURATION_PROPERTY, configLocation); } } protected void install(final ContainerInfo serviceInfo) throws OpenEJBException { if (sys != null) { sys.containerSystem.containers.add(serviceInfo); } else if (!offline) { final Assembler assembler = SystemInstance.get().getComponent(Assembler.class); if (assembler != null) { assembler.createContainer(serviceInfo); }else{ throw new OpenEJBException("ContainerInfo: Assembler has not been defined"); } } } protected void install(final ResourceInfo serviceInfo) throws OpenEJBException { if (sys != null) { sys.facilities.resources.add(serviceInfo); } else if (!offline) { doInstall(serviceInfo); } } void doInstall(final ResourceInfo serviceInfo) throws OpenEJBException { final Assembler assembler = SystemInstance.get().getComponent(Assembler.class); if (assembler != null) { assembler.createResource(null, serviceInfo); } else { throw new OpenEJBException("ResourceInfo: Assembler has not been defined"); } } public OpenEjbConfiguration getOpenEjbConfiguration(final File configuartionFile) throws OpenEJBException { if (configuartionFile != null) { return getOpenEjbConfiguration(JaxbOpenejb.readConfig(configuartionFile.getAbsolutePath())); } else { return getOpenEjbConfiguration((Openejb) null); } } public OpenEjbConfiguration getOpenEjbConfiguration(final Openejb providedConf) throws OpenEJBException { if (sys != null) { return sys; } if (providedConf != null) { openejb = providedConf; } else if (configLocation != null) { openejb = JaxbOpenejb.readConfig(configLocation); } else { openejb = JaxbOpenejb.createOpenejb(); } for (final SystemProperty sp : openejb.getSystemProperties()) { final String name = sp.getName(); final String value = sp.getValue(); SystemInstance.get().setProperty(name, value); JavaSecurityManagers.setSystemProperty(name, value); } loadPropertiesDeclaredConfiguration(openejb); sys = new OpenEjbConfiguration(); sys.containerSystem = new ContainerSystemInfo(); sys.facilities = new FacilitiesInfo(); // listener + some config can be defined as service for (final Service service : openejb.getServices()) { final ServiceInfo info = configureService(service, ServiceInfo.class); sys.facilities.services.add(info); } for (final JndiProvider provider : openejb.getJndiProvider()) { final JndiContextInfo info = configureService(provider, JndiContextInfo.class); sys.facilities.remoteJndiContexts.add(info); } sys.facilities.securityService = configureService(openejb.getSecurityService(), SecurityServiceInfo.class); sys.facilities.transactionService = configureService(openejb.getTransactionManager(), TransactionServiceInfo.class); List<ResourceInfo> resources = new ArrayList<>(); for (final Resource resource : openejb.getResource()) { final ResourceInfo resourceInfo = configureService(resource, ResourceInfo.class); resources.add(resourceInfo); } resources = sort(resources, null); sys.facilities.resources.addAll(resources); // ConnectionManagerInfo service = configureService(openejb.getConnectionManager(), ConnectionManagerInfo.class); // sys.facilities.connectionManagers.add(service); if (openejb.getProxyFactory() != null) { sys.facilities.intraVmServer = configureService(openejb.getProxyFactory(), ProxyFactoryInfo.class); } for (final Container declaration : openejb.getContainer()) { final ContainerInfo info = createContainerInfo(declaration); sys.containerSystem.containers.add(info); } final List<File> declaredApps = getDeclaredApps(); for (final File jarFile : declaredApps) { try { final AppInfo appInfo = configureApplication(jarFile); sys.containerSystem.applications.add(appInfo); } catch (final OpenEJBException alreadyHandled) { final DeploymentExceptionManager exceptionManager = SystemInstance.get().getComponent(DeploymentExceptionManager.class); if (exceptionManager != null) { exceptionManager.pushDelpoymentException(alreadyHandled); } } } final boolean embedded = SystemInstance.get().hasProperty(EJBContainer.class.getName()); final Options options = SystemInstance.get().getOptions(); if (options.get("openejb.system.apps", false)) { try { final boolean extended = SystemApps.isExtended(); final AppInfo appInfo; if (!extended) { // do it manually, we know what we need and can skip a bunch of processing appInfo = SystemAppInfo.preComputedInfo(this); } else { appInfo = configureApplication(new AppModule(SystemApps.getSystemModule())); } // they doesn't use CDI so no need to activate it // 1) will be faster // 2) will let embedded containers (tomee-embedded mainly) not be noised by it in our singleton service appInfo.properties.put("openejb.cdi.activated", "false"); sys.containerSystem.applications.add(appInfo); } catch (final OpenEJBException e) { logger.error("Unable to load the system applications.", e); } } else if (options.get(DEPLOYMENTS_CLASSPATH_PROPERTY, !embedded)) { final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); final ArrayList<File> jarFiles = getModulesFromClassPath(declaredApps, classLoader); final String appId = "classpath.ear"; final boolean classpathAsEar = options.get(CLASSPATH_AS_EAR, true); try { if (classpathAsEar && !jarFiles.isEmpty()) { final AppInfo appInfo = configureApplication(classLoader, appId, jarFiles); sys.containerSystem.applications.add(appInfo); } else { for (final File jarFile : jarFiles) { final AppInfo appInfo = configureApplication(jarFile); sys.containerSystem.applications.add(appInfo); } } if (jarFiles.size() == 0) { logger.warning("config.noModulesFoundToDeploy"); } } catch (final OpenEJBException alreadyHandled) { logger.debug("config.alreadyHandled"); } } for (final Deployments deployments : openejb.getDeployments()) { if (deployments.isAutoDeploy()) { if (deployments.getDir() != null) { sys.containerSystem.autoDeploy.add(deployments.getDir()); } } } final OpenEjbConfiguration finished = sys; sys = null; openejb = null; return finished; } /** * Main loop that gets executed when OpenEJB starts up Reads config files and produces the basic "AST" the assembler needs to actually build the contianer system * <p/> * This method is called by the Assembler once at startup. * * @return OpenEjbConfiguration * @throws OpenEJBException */ @Override public OpenEjbConfiguration getOpenEjbConfiguration() throws OpenEJBException { return getOpenEjbConfiguration((Openejb) null); } private List<File> getDeclaredApps() { // make a copy of the list because we update it final List<Deployments> deployments = new ArrayList<Deployments>(); if (openejb != null) { deployments.addAll(openejb.getDeployments()); } Collection<Deployments> additionalDeploymentsList = Collections.emptyList(); try { final File additionalDeploymentFile = SystemInstance.get().getBase().getFile(ADDITIONAL_DEPLOYMENTS, false); if (additionalDeploymentFile.exists()) { InputStream fis = null; try { fis = IO.read(additionalDeploymentFile); final AdditionalDeployments additionalDeployments = JaxbOpenejb.unmarshal(AdditionalDeployments.class, fis); additionalDeploymentsList = additionalDeployments.getDeployments(); } catch (final Exception e) { logger.error("can't read " + ADDITIONAL_DEPLOYMENTS, e); } finally { IO.close(fis); } } } catch (final Exception e) { logger.info("No additional deployments found: " + e); } // resolve jar locations ////////////////////////////////////// BEGIN /////// final FileUtils base = SystemInstance.get().getBase(); final List<Deployments> autoDeploy = new ArrayList<Deployments>(); final List<File> declaredAppsUrls = new ArrayList<File>(); for (final Deployments deployment : deployments) { try { DeploymentsResolver.loadFrom(deployment, base, declaredAppsUrls); if (deployment.isAutoDeploy()) { autoDeploy.add(deployment); } } catch (final SecurityException se) { logger.warning("Security check failed on deployment: " + deployment.getFile(), se); } } for (final Deployments additionalDep : additionalDeploymentsList) { if (additionalDep.getFile() != null) { declaredAppsUrls.add(Files.path(base.getDirectory().getAbsoluteFile(), additionalDep.getFile())); } else if (additionalDep.getDir() != null) { declaredAppsUrls.add(Files.path(base.getDirectory().getAbsoluteFile(), additionalDep.getDir())); } if (additionalDep.isAutoDeploy()) { autoDeploy.add(additionalDep); } } if (autoDeploy.size() > 0) { final AutoDeployer autoDeployer = new AutoDeployer(this, autoDeploy); SystemInstance.get().setComponent(AutoDeployer.class, autoDeployer); SystemInstance.get().addObserver(autoDeployer); } return declaredAppsUrls; } public ArrayList<File> getModulesFromClassPath(final List<File> declaredApps, final ClassLoader classLoader) { final List<URL> classpathAppsUrls = DeploymentsResolver.loadFromClasspath(classLoader); final ArrayList<File> jarFiles = new ArrayList<File>(); for (final URL path : classpathAppsUrls) { final File file = URLs.toFile(path); if (declaredApps != null && declaredApps.contains(file)) { continue; } jarFiles.add(file); } return jarFiles; } public ContainerInfo createContainerInfo(final Container container) throws OpenEJBException { final Class<? extends ContainerInfo> infoClass = getContainerInfoType(container.getType()); if (infoClass == null) { throw new OpenEJBException(messages.format("unrecognizedContainerType", container.getType())); } return configureService(container, infoClass); } public static void loadPropertiesDeclaredConfiguration(final Openejb openejb) { final Properties sysProps = new Properties(JavaSecurityManagers.getSystemProperties()); sysProps.putAll(SystemInstance.get().getProperties()); fillOpenEjb(openejb, sysProps); } public static void fillOpenEjb(final Openejb openejb, final Properties sysProps) { for (final Map.Entry<Object, Object> entry : sysProps.entrySet()) { final Object o = entry.getValue(); if (!(o instanceof String)) { continue; } if (!((String) o).startsWith("new://")) { continue; } final String name = (String) entry.getKey(); final String value = (String) entry.getValue(); try { final Object service = toConfigDeclaration(name, value); openejb.add(service); } catch (final URISyntaxException e) { logger.error("Error declaring service '" + name + "'. Invalid Service URI '" + value + "'. java.net.URISyntaxException: " + e.getMessage()); } catch (final OpenEJBException e) { logger.error(e.getMessage()); } } } protected static Object toConfigDeclaration(final String name, String value) throws URISyntaxException, OpenEJBException { // value = value.replaceFirst("(.)#", "$1%23"); value = value.replaceFirst("(provider=[^#=&]+)#", "$1%23"); final URI uri = URLs.uri(value); return toConfigDeclaration(name, uri); } public static Object toConfigDeclaration(final String id, final URI uri) throws OpenEJBException { final String serviceType; try { serviceType = uri.getHost(); final Object object; try { object = JaxbOpenejb.create(serviceType); } catch (final Exception e) { throw new OpenEJBException("Invalid URI '" + uri + "'. " + e.getMessage()); } final Map<String, String> map; try { map = URISupport.parseParamters(uri); } catch (final URISyntaxException e) { throw new OpenEJBException("Unable to parse URI parameters '" + uri + "'. URISyntaxException: " + e.getMessage()); } if (object instanceof AbstractService) { final AbstractService service = (AbstractService) object; service.setId(id); service.setType(map.remove("type")); service.setProvider(map.remove("provider")); service.setClassName(map.remove("class-name")); service.setConstructor(map.remove("constructor")); service.setFactoryName(map.remove("factory-name")); service.setPropertiesProvider(map.remove("properties-provider")); service.setTemplate(map.remove("template")); final String cp = map.remove("classpath"); if (null != cp) { service.setClasspath(cp); } service.setClasspathAPI(map.remove("classpath-api")); if (object instanceof Resource) { final Resource resource = Resource.class.cast(object); final String aliases = map.remove("aliases"); if (aliases != null) { resource.getAliases().addAll(Arrays.asList(aliases.split(","))); } final String depOn = map.remove("depends-on"); if (depOn != null) { resource.getDependsOn().addAll(Arrays.asList(depOn.split(","))); } resource.setPostConstruct(map.remove("post-construct")); resource.setPreDestroy(map.remove("pre-destroy")); } service.getProperties().putAll(map); } else if (object instanceof Deployments) { final Deployments deployments = (Deployments) object; deployments.setDir(map.remove("dir")); deployments.setFile(map.remove("jar")); final String cp = map.remove("classpath"); if (cp != null) { final String[] paths = cp.split(File.pathSeparator); final List<URL> urls = new ArrayList<>(); for (final String path : paths) { final Set<String> values = ProvisioningUtil.realLocation(PropertyPlaceHolderHelper.value(path)); for (final String v : values) { urls.add(new File(v).toURI().normalize().toURL()); } } deployments.setClasspath(new URLClassLoaderFirst(urls.toArray(new URL[urls.size()]), ParentClassLoaderFinder.Helper.get())); } } else if (SystemProperty.class.isInstance(object)) { final SystemProperty sp = SystemProperty.class.cast(object); sp.setName(map.remove("name")); sp.setValue(map.remove("value")); } return object; } catch (final Exception e) { throw new OpenEJBException("Error declaring service '" + id + "'. Unable to create Service definition from URI '" + uri.toString() + "'", e); } } public AppInfo configureApplication(final File jarFile) throws OpenEJBException { logger.debug("Beginning load: " + jarFile.getAbsolutePath()); try { final AppModule appModule = deploymentLoader.load(jarFile, null); final AppInfo appInfo = configureApplication(appModule); // we need the finder for web scanning so push it to what sees TomcatWebAppBuilder, ie the info tree // this is clean up in Assembler for safety and TomcatWebAppBuilder when used if (!appModule.getWebModules().isEmpty()) { for (final WebAppInfo info : appInfo.webApps) { for (final EjbModule ejbModule : appModule.getEjbModules()) { if (ejbModule.getModuleId().equals(info.moduleId) && ejbModule.getFinder() != null) { appInfo.properties.put(info, ejbModule); } } } } // TODO This is temporary -- we need to do this in AppInfoBuilder appInfo.paths.add(appInfo.path); appInfo.paths.add(jarFile.getAbsolutePath()); return appInfo; } catch (final ValidationFailedException e) { logger.warning("configureApplication.loadFailed", jarFile.getAbsolutePath(), e.getMessage()); // DO not include the stacktrace in the message throw e; } catch (final OpenEJBException e) { // DO NOT REMOVE THE EXCEPTION FROM THIS LOG MESSAGE // removing this message causes NO messages to be printed when embedded logger.warning("configureApplication.loadFailed", e, jarFile.getAbsolutePath(), e.getMessage()); throw e; } } /** * embedded usage * * @param classLoader classloader * @param id id supplied from embedded properties or null * @param jarFiles list of ejb modules * @return configured AppInfo * @throws OpenEJBException on error */ public AppInfo configureApplication(final ClassLoader classLoader, final String id, final List<File> jarFiles) throws OpenEJBException { final AppModule collection = loadApplication(classLoader, id, jarFiles); final AppInfo appInfo; try { appInfo = configureApplication(collection); } catch (final ValidationFailedException e) { logger.warning("configureApplication.loadFailed", collection.getModuleId(), e.getMessage()); // DO not include the stacktrace in the message throw e; } catch (final OpenEJBException e) { // DO NOT REMOVE THE EXCEPTION FROM THIS LOG MESSAGE // removing this message causes NO messages to be printed when embedded logger.warning("configureApplication.loadFailed", e, collection.getModuleId(), e.getMessage()); throw e; } return appInfo; } @SuppressWarnings("unchecked") public AppModule loadApplication(final ClassLoader classLoader, String id, final List<File> jarFiles) throws OpenEJBException { final boolean standaloneModule = id == null; if (standaloneModule) { id = ""; } final Application application = new Application(); application.setApplicationName(id); final AppModule collection = new AppModule(classLoader, id, application, standaloneModule); final Map<String, Object> altDDs = collection.getAltDDs(); for (final File jarFile : jarFiles) { logger.info("Beginning load: " + jarFile.getAbsolutePath()); try { final AppModule module = deploymentLoader.load(jarFile, null); collection.getAdditionalLibraries().addAll(module.getAdditionalLibraries()); collection.getClientModules().addAll(module.getClientModules()); collection.getEjbModules().addAll(module.getEjbModules()); collection.addPersistenceModules(module.getPersistenceModules()); collection.getConnectorModules().addAll(module.getConnectorModules()); collection.getWebModules().addAll(module.getWebModules()); collection.getWatchedResources().addAll(module.getWatchedResources()); // Merge altDDs for (final Map.Entry<String, Object> entry : module.getAltDDs().entrySet()) { final Object existingValue = altDDs.get(entry.getKey()); if (existingValue == null) { altDDs.put(entry.getKey(), entry.getValue()); } else if (entry.getValue() instanceof Collection) { if (existingValue instanceof Collection) { final Collection values = (Collection) existingValue; values.addAll((Collection) entry.getValue()); } } else if (entry.getValue() instanceof Map) { if (existingValue instanceof Map) { final Map values = (Map) existingValue; values.putAll((Map) entry.getValue()); } } } } catch (final ValidationFailedException e) { logger.warning("configureApplication.loadFailed", jarFile.getAbsolutePath(), e.getMessage()); // DO not include the stacktrace in the message throw e; } catch (final OpenEJBException e) { // DO NOT REMOVE THE EXCEPTION FROM THIS LOG MESSAGE // removing this message causes NO messages to be printed when embedded logger.warning("configureApplication.loadFailed", e, jarFile.getAbsolutePath(), e.getMessage()); throw e; } } return collection; } public EjbJarInfo configureApplication(final EjbJar ejbJar) throws OpenEJBException { final EjbModule ejbModule = new EjbModule(ejbJar); return configureApplication(ejbModule); } public EjbJarInfo configureApplication(final EjbModule ejbModule) throws OpenEJBException { final AppInfo appInfo = configureApplication(new AppModule(ejbModule)); return appInfo.ejbJars.get(0); } public ClientInfo configureApplication(final ClientModule clientModule) throws OpenEJBException { final AppInfo appInfo = configureApplication(new AppModule(clientModule)); return appInfo.clients.get(0); } public ConnectorInfo configureApplication(final ConnectorModule connectorModule) throws OpenEJBException { final AppInfo appInfo = configureApplication(new AppModule(connectorModule)); return appInfo.connectors.get(0); } public WebAppInfo configureApplication(final WebModule webModule) throws OpenEJBException { final AppInfo appInfo = configureApplication(new AppModule(webModule)); return appInfo.webApps.get(0); } public AppInfo configureApplication(final AppModule appModule) throws OpenEJBException { try { final Collection<Class<?>> extensions = new HashSet<Class<?>>(); final Collection<String> notLoaded = new HashSet<String>(); final List<URL> libs = appModule.getAdditionalLibraries(); if (libs != null && libs.size() > 0) { final Extensions.Finder finder = new Extensions.Finder("META-INF", false, libs.toArray(new URL[libs.size()])); extensions.addAll(Extensions.findExtensions(finder)); notLoaded.addAll(finder.getResourcesNotLoaded()); } for (final EjbModule ejb : appModule.getEjbModules()) { try { final URI uri = ejb.getModuleUri(); if (uri.isAbsolute()) { final URL url = uri.toURL(); if (libs != null && !libs.contains(url)) { final Extensions.Finder finder = new Extensions.Finder("META-INF", false, url); extensions.addAll(Extensions.findExtensions(finder)); notLoaded.addAll(finder.getResourcesNotLoaded()); } } } catch (final IllegalArgumentException | MalformedURLException iae) { logger.debug("can't look for server event listener for module " + ejb.getModuleUri(), iae); } catch (final Exception e) { logger.error("can't look for server event listener for module " + ejb.getJarLocation()); } } for (final WebModule web : appModule.getWebModules()) { final List<URL> webLibs = web.getScannableUrls(); if (webLibs != null && webLibs.size() > 0) { final Extensions.Finder finder = new Extensions.Finder("META-INF", false, webLibs.toArray(new URL[webLibs.size()])); extensions.addAll(Extensions.findExtensions(finder)); notLoaded.addAll(finder.getResourcesNotLoaded()); } } // add it as early as possible, the ones needing the app classloader will be added later Extensions.addExtensions(extensions); final String location = appModule.getJarLocation(); logger.info("config.configApp", null != location ? location : appModule.getModuleId()); deployer.deploy(appModule); final AppInfoBuilder appInfoBuilder = new AppInfoBuilder(this); final AppInfo info = appInfoBuilder.build(appModule); info.eventClassesNeedingAppClassloader.addAll(notLoaded); return info; } finally { destroy(appModule.getEarLibFinder()); for (final EjbModule ejb : appModule.getEjbModules()) { destroy(ejb.getFinder()); } for (final WebModule web : appModule.getWebModules()) { destroy(web.getFinder()); } } } private static void destroy(final IAnnotationFinder finder) { if (finder == null) { return; } if (AutoCloseable.class.isInstance(finder)) { try { AutoCloseable.class.cast(finder).close(); } catch (final Exception e) { // no-op } } } private static class DefaultService { private final Class<? extends org.apache.openejb.config.Service> type; private final String id; public DefaultService(final String id, final Class<? extends org.apache.openejb.config.Service> type) { this.id = id; this.type = type; } } private static final Map<Class<? extends ServiceInfo>, DefaultService> defaultProviders = new HashMap<Class<? extends ServiceInfo>, DefaultService>(); private static final Map<Class<? extends ServiceInfo>, Class<? extends org.apache.openejb.config.Service>> types = new HashMap<Class<? extends ServiceInfo>, Class<? extends org.apache.openejb.config.Service>>(); /** * This is the magic that allows people to be really vague in their openejb.xml and not specify * the provider for one of their declared services. We look here for the default service id * * We then look in the default provider "namespace" that is setup, which will usually be either one of: * * - org.apache.openejb * - org.apache.openejb.embedded * - org.apache.openejb.tomcat * - org.apache.openejb.jetty * * As in: * * - META-INF/<provider>/service-jar.xml * */ static { defaultProviders.put(MdbContainerInfo.class, new DefaultService("MESSAGE", Container.class)); defaultProviders.put(ManagedContainerInfo.class, new DefaultService("MANAGED", Container.class)); defaultProviders.put(StatefulSessionContainerInfo.class, new DefaultService("STATEFUL", Container.class)); defaultProviders.put(StatelessSessionContainerInfo.class, new DefaultService("STATELESS", Container.class)); defaultProviders.put(SingletonSessionContainerInfo.class, new DefaultService("SINGLETON", Container.class)); defaultProviders.put(CmpEntityContainerInfo.class, new DefaultService("CMP_ENTITY", Container.class)); defaultProviders.put(BmpEntityContainerInfo.class, new DefaultService("BMP_ENTITY", Container.class)); defaultProviders.put(SecurityServiceInfo.class, new DefaultService("SecurityService", SecurityService.class)); defaultProviders.put(TransactionServiceInfo.class, new DefaultService("TransactionManager", TransactionManager.class)); defaultProviders.put(ConnectionManagerInfo.class, new DefaultService("ConnectionManager", ConnectionManager.class)); defaultProviders.put(ProxyFactoryInfo.class, new DefaultService("ProxyFactory", ProxyFactory.class)); for (final Map.Entry<Class<? extends ServiceInfo>, DefaultService> entry : defaultProviders.entrySet()) { types.put(entry.getKey(), entry.getValue().type); } types.put(ResourceInfo.class, Resource.class); } public <T extends ServiceInfo> T configureService(final Class<? extends T> type) throws OpenEJBException { return configureService((org.apache.openejb.config.Service) null, type); } private <T extends ServiceInfo> org.apache.openejb.config.Service getDefaultService(final Class<? extends T> type) throws OpenEJBException { final DefaultService defaultService = defaultProviders.get(type); if (defaultService == null) { return null; } final org.apache.openejb.config.Service service; try { service = JaxbOpenejb.create(defaultService.type); service.setType(defaultService.id); } catch (final Exception e) { final String name = defaultService.type == null ? "null" : defaultService.type.getName(); throw new OpenEJBException("Cannot instantiate class " + name, e); } return service; } /** * This is the major piece of code that configures services. * It merges the data from the <ServiceProvider> declaration * with the data from the openejb.xml file (say <Resource>) * <p/> * The end result is a canonical (i.e. flattened) ServiceInfo * The ServiceInfo will be of a specific type (ContainerInfo, ResourceInfo, etc) * * @param service Service * @param infoType Class * @param <T> infoType * @return ServiceInfo * @throws OpenEJBException On error */ public <T extends ServiceInfo> T configureService(org.apache.openejb.config.Service service, final Class<? extends T> infoType) throws OpenEJBException { try { if (infoType == null) { throw new NullPointerException("type"); } if (service == null) { service = getDefaultService(infoType); if (service == null) { throw new OpenEJBException(messages.format("configureService.noDefaultService", infoType.getName())); } } { String template = service.getTemplate(); if (template == null) { template = SystemInstance.get().getProperty(Template.class.getName()); } if (template != null) { template = unaliasPropertiesProvider(template); // don't trim them, user wants to handle it himself, let him do it final ObjectRecipe recipe = newObjectRecipe(template); recipe.setProperty("serviceId", service.getId()); // note: we can also use reflection if needed to limit the dependency Template.class.cast(recipe.create()).configure(service); } } final ServiceProvider provider = getServiceProvider(service, infoType); if (service.getId() == null) { service.setId(provider.getId()); } final Properties overrides = trim(getSystemProperties(overrideKey(service), provider.getService())); final Properties serviceProperties = service.getProperties(); trim(serviceProperties); trim(provider.getProperties()); logger.info("configureService.configuring", service.getId(), provider.getService(), provider.getId()); if (logger.isDebugEnabled()) { for (final Map.Entry<Object, Object> entry : serviceProperties.entrySet()) { final Object key = entry.getKey(); Object value = entry.getValue(); if (key instanceof String && "password".equalsIgnoreCase((String) key)) { value = "<hidden>"; } logger.debug("[" + key + "=" + value + "]"); } for (final Map.Entry<Object, Object> entry : overrides.entrySet()) { final Object key = entry.getKey(); Object value = entry.getValue(); if (key instanceof String && "password".equalsIgnoreCase((String) key)) { value = "<hidden>"; } logger.debug("Override [" + key + "=" + value + "]"); } } final Properties props = new SuperProperties().caseInsensitive(true); // weird hack but sometimes we don't want default values when we want null for instance if (serviceProperties == null || "false".equals(serviceProperties.getProperty(IGNORE_DEFAULT_VALUES_PROP, "false"))) { props.putAll(provider.getProperties()); } if (serviceProperties != null) { props.putAll(serviceProperties); } props.putAll(overrides); {// force user properties last String propertiesProvider = service.getPropertiesProvider(); if (propertiesProvider == null) { propertiesProvider = SystemInstance.get().getProperty(PropertiesResourceProvider.class.getName()); } if (propertiesProvider != null) { propertiesProvider = unaliasPropertiesProvider(propertiesProvider); // don't trim them, user wants to handle it himself, let him do it final ObjectRecipe recipe = newObjectRecipe(propertiesProvider); recipe.setFactoryMethod("provides"); recipe.setProperty("serviceId", service.getId()); recipe.setProperties(props); recipe.setProperty("properties", props); // let user get all config final Properties p = Properties.class.cast(recipe.create()); props.putAll(p); } } props.remove(IGNORE_DEFAULT_VALUES_PROP); final T info; try { info = infoType.newInstance(); } catch (final Exception e) { throw new OpenEJBException(messages.format("configureService.cannotInstantiateClass", infoType.getName()), e); } // some jndi adjustment if (service.getId().startsWith("java:/")) { service.setId(service.getId().substring("java:/".length())); } info.service = provider.getService(); info.types.addAll(provider.getTypes()); info.description = provider.getDescription(); info.displayName = provider.getDisplayName(); info.className = provider.getClassName(); info.factoryMethod = provider.getFactoryName(); info.id = service.getId(); info.properties = props; info.constructorArgs.addAll(parseConstructorArgs(provider)); if (info instanceof ResourceInfo && service instanceof Resource) { final ResourceInfo ri = ResourceInfo.class.cast(info); final Resource resource = Resource.class.cast(service); ri.jndiName = resource.getJndi(); ri.postConstruct = resource.getPostConstruct(); ri.preDestroy = resource.getPreDestroy(); ri.aliases.addAll(resource.getAliases()); ri.dependsOn.addAll(resource.getDependsOn()); } if (service.getClasspath() != null && service.getClasspath().length() > 0) { info.classpath = resolveClasspath(service.getClasspath()); } info.classpathAPI = service.getClasspathAPI(); specialProcessing(info); return info; } catch (final NoSuchProviderException e) { final String message = logger.fatal("configureService.failed", e, (null != service ? service.getId() : "")); throw new OpenEJBException(message + ": " + e.getMessage()); } catch (final Throwable e) { final String message = logger.fatal("configureService.failed", e, (null != service ? service.getId() : "")); throw new OpenEJBException(message, e); } } private <T extends ServiceInfo> ServiceProvider getServiceProvider( final org.apache.openejb.config.Service service, final Class<? extends T> infoType) throws OpenEJBException { final String providerType = getProviderType(service); final ServiceProvider provider = resolveServiceProvider(service, infoType); if (provider == null) { final List<ServiceProvider> providers = ServiceUtils.getServiceProvidersByServiceType(providerType); final StringBuilder sb = new StringBuilder(); final List<String> types = new ArrayList<String>(); for (final ServiceProvider p : providers) { for (final String type : p.getTypes()) { if (types.contains(type)) { continue; } types.add(type); sb.append(JavaSecurityManagers.getSystemProperty("line.separator")); sb.append(" <").append(p.getService()); sb.append(" id=\"").append(service.getId()).append('"'); sb.append(" type=\"").append(type).append("\"/>"); } } final String noProviderMessage = messages.format("configureService.noProviderForService", providerType, service.getId(), service.getType(), service.getProvider(), sb.toString()); throw new NoSuchProviderException(noProviderMessage); } if (!provider.getService().equals(providerType)) { throw new OpenEJBException(messages.format("configureService.wrongProviderType", service.getId(), providerType)); } return provider; } private ObjectRecipe newObjectRecipe(final String template) { final ObjectRecipe recipe = new ObjectRecipe(template); recipe.allow(Option.CASE_INSENSITIVE_PROPERTIES); recipe.allow(Option.PRIVATE_PROPERTIES); recipe.allow(Option.FIELD_INJECTION); recipe.allow(Option.NAMED_PARAMETERS); recipe.allow(Option.IGNORE_MISSING_PROPERTIES); return recipe; } private static String unaliasPropertiesProvider(final String propertiesProvider) { switch (propertiesProvider.toLowerCase(Locale.ENGLISH)) { case "heroku": return "org.apache.openejb.resource.heroku.HerokuDatabasePropertiesProvider"; case "openshift:mysql": return "org.apache.openejb.resource.openshift.OpenshiftMySQLPropertiesProvider"; case "openshift:postgresql": return "org.apache.openejb.resource.openshift.OpenshiftPostgreSQLPropertiesProvider"; default: return propertiesProvider; } } private static String unaliasTemplate(final String value) { return value; } /** * Takes a raw unparsed string expected to be in jvm classpath syntax * and parses it, producing a collection of URIs representing the absolute * file paths of the classpath to be created. * <p/> * OS specific delimiters are supported. * * @param rawstring unparsed string in "classpath" syntax * @return URI array * @throws IOException if path cannot be resolved or file referenced does not exist */ public static URI[] resolveClasspath(final String rawstring) throws IOException { final FileUtils base = SystemInstance.get().getBase(); final String[] strings = rawstring.contains("mvn:") ? rawstring.split(";") : rawstring.split(File.pathSeparator); final Collection<URI> classpath = new LinkedList<>(); for (final String string : strings) { final Set<String> locations = ProvisioningUtil.realLocation(PropertyPlaceHolderHelper.simpleValue(string)); for (final String location : locations) { final File file = base.getFile(location, false); classpath.add(file.toURI()); } } return classpath.toArray(new URI[classpath.size()]); } private String overrideKey(final org.apache.openejb.config.Service service) { final String origin = String.class.cast(service.getProperties().remove(AutoConfig.ORIGINAL_ID)); if (origin != null) { return origin; } return service.getId(); } private static String getProviderType(final org.apache.openejb.config.Service service) { Class<?> clazz = service.getClass(); if (AbstractService.class.isAssignableFrom(clazz)) { while (!clazz.getSuperclass().equals(AbstractService.class)) { clazz = clazz.getSuperclass(); } } return clazz.getSimpleName(); } private static Properties trim(final Properties properties) { for (final Map.Entry<Object, Object> entry : properties.entrySet()) { final Object o = entry.getValue(); if (o instanceof String) { final String value = (String) o; final String trimmed = value.trim(); if (value.length() != trimmed.length()) { properties.put(entry.getKey(), trimmed); } } } return properties; } private <T extends ServiceInfo> void specialProcessing(final T info) { TopicOrQueueDefaults.process(info); } @SuppressWarnings({"unchecked"}) private ServiceProvider resolveServiceProvider(final org.apache.openejb.config.Service service, final Class infoType) throws OpenEJBException { if (service.getClassName() != null) { if (service.getType() == null) { service.setType(service.getClassName()); } final ServiceProvider provider = new ServiceProvider(); provider.setId(service.getId()); provider.setService(getProviderType(service)); provider.getTypes().add(service.getType()); provider.setClassName(service.getClassName()); provider.setConstructor(service.getConstructor()); provider.setFactoryName(service.getFactoryName()); return provider; } if (service.getProvider() != null) { return ServiceUtils.getServiceProvider(service.getProvider()); } if (service.getType() == null && serviceTypeIsAdjustable) { // try to guess quickly for know type // -> DataSource // the algo is weird but works, don't try to simplify it too much // because we just have the service properties, not our defaults final Properties properties = service.getProperties(); if ((properties.containsKey("JdbcDriver") || properties.containsKey("JdbcUrl") || properties.containsKey("url")) && (properties.containsKey("JtaManaged") || properties.containsKey("UserName") || properties.containsKey("Password"))) { service.setType("javax.sql.DataSource"); } } if (service.getType() != null) { return ServiceUtils.getServiceProviderByType(getProviderType(service), service.getType()); } if (service.getId() != null) { try { return ServiceUtils.getServiceProvider(service.getId()); } catch (final NoSuchProviderException e) { logger.debug("resolveServiceProvider", e); } } if (infoType != null) { final org.apache.openejb.config.Service defaultService = getDefaultService(infoType); if (defaultService != null) { return resolveServiceProvider(defaultService, null); } } return null; } public <T extends ServiceInfo> T configureService(final String id, final Class<? extends T> type) throws OpenEJBException { return configureService(type, id, null, id, null); } /** * Resolving the provider for a particular service follows this algorithm: * <p/> * 1. Attempt to load the provider specified by the 'providerId'. * 2. If this fails, throw NoSuchProviderException * 3. If providerId is null, attempt to load the specified provider using the 'serviceId' as the 'providerId' * 4. If this fails, check the hardcoded defaults for a default providerId using the supplied 'type' * 5. If this fails, throw NoSuchProviderException * * @param type Class T * @param serviceId String * @param declaredProperties Properties * @param providerId String * @param serviceType String * @return ServiceInfo T * @throws OpenEJBException */ public <T extends ServiceInfo> T configureService(final Class<? extends T> type, final String serviceId, final Properties declaredProperties, final String providerId, final String serviceType) throws OpenEJBException { if (type == null) { throw new NullPointerException("type is null"); } final Class<? extends org.apache.openejb.config.Service> serviceClass = types.get(type); if (serviceClass == null) { throw new OpenEJBException("Unsupported service info type: " + type.getName()); } final org.apache.openejb.config.Service service; try { service = serviceClass.newInstance(); } catch (final Exception e) { throw new OpenEJBException(messages.format("configureService.cannotInstantiateClass", serviceClass.getName()), e); } service.setId(serviceId); service.setProvider(providerId); if (declaredProperties != null) { service.getProperties().putAll(declaredProperties); } return configureService(service, type); } protected static Properties getSystemProperties(final String serviceId, final String serviceType) { // Override with system properties final Properties sysProps = new Properties(JavaSecurityManagers.getSystemProperties()); sysProps.putAll(SystemInstance.get().getProperties()); return getOverrides(sysProps, serviceId, serviceType); } protected static Properties getOverrides(final Properties properties, final String serviceId, final String serviceType) { final String fullPrefix = serviceType.toUpperCase() + "." + serviceId + "."; final String fullPrefix2 = serviceType.toUpperCase() + "." + serviceId + "|"; final String shortPrefix = serviceId + "."; final String shortPrefix2 = serviceId + "|"; final Properties overrides = new Properties(); for (final Map.Entry<Object, Object> entry : properties.entrySet()) { String name = (String) entry.getKey(); for (final String prefix : Arrays.asList(fullPrefix, fullPrefix2, shortPrefix, shortPrefix2)) { if (name.toLowerCase().startsWith(prefix.toLowerCase())) { name = name.substring(prefix.length()); // TODO: Maybe use xbean-reflect to get the string value final String value = entry.getValue().toString(); overrides.setProperty(name, value); break; } } } return overrides; } private static final Map<String, Class<? extends ContainerInfo>> containerTypes = new HashMap<String, Class<? extends ContainerInfo>>(); static { containerTypes.put(BeanTypes.SINGLETON, SingletonSessionContainerInfo.class); containerTypes.put(BeanTypes.MANAGED, ManagedContainerInfo.class); containerTypes.put(BeanTypes.STATELESS, StatelessSessionContainerInfo.class); containerTypes.put(BeanTypes.STATEFUL, StatefulSessionContainerInfo.class); containerTypes.put(BeanTypes.BMP_ENTITY, BmpEntityContainerInfo.class); containerTypes.put(BeanTypes.CMP_ENTITY, CmpEntityContainerInfo.class); containerTypes.put(BeanTypes.MESSAGE, MdbContainerInfo.class); } protected static Class<? extends ContainerInfo> getContainerInfoType(final String ctype) { return containerTypes.get(ctype); } private List<String> parseConstructorArgs(final ServiceProvider service) { final String constructor = service.getConstructor(); if (constructor == null) { return Collections.emptyList(); } return Arrays.asList(constructor.split("[ ,]+")); } protected List<String> getResourceIds() { return getResourceIds(null); } protected List<String> getResourceIds(final String type) { return getResourceIds(type, null); } public List<String> getResourceIds(final String type, Properties required) { final List<String> resourceIds = new ArrayList<String>(); if (required == null) { required = new Properties(); } final OpenEjbConfiguration runningConfig = getRunningConfig(); if (runningConfig != null) { for (final ResourceInfo resourceInfo : runningConfig.facilities.resources) { if (logger.isDebugEnabled()) { logger.debug(String.format("Trying to match resource type %s with classname %s, service %s.", type, resourceInfo.className, resourceInfo.service)); } if ((type != null && type.equals(resourceInfo.className) || isResourceType(resourceInfo.service, resourceInfo.types, type)) && implies(required, resourceInfo.properties)) { resourceIds.add(resourceInfo.id); resourceIds.addAll(resourceInfo.aliases); } } } if (sys != null) { for (final ResourceInfo resourceInfo : sys.facilities.resources) { if (isResourceType(resourceInfo.service, resourceInfo.types, type) && implies(required, resourceInfo.properties)) { resourceIds.add(resourceInfo.id); resourceIds.addAll(resourceInfo.aliases); } } // The only time we'd have one of these is if we were building // the above sys instance if (openejb != null) { for (final Resource resource : openejb.getResource()) { final ArrayList<String> types = new ArrayList<String>(); if (resource.getType() != null) { types.add(resource.getType()); } if (isResourceType("Resource", types, type) && implies(required, resource.getProperties())) { resourceIds.add(resource.getId()); resourceIds.addAll(resource.getAliases()); } } } } return resourceIds; } protected ResourceInfo getResourceInfo(final String id) { final OpenEjbConfiguration runningConfig = getRunningConfig(); if (runningConfig != null) { for (final ResourceInfo resourceInfo : runningConfig.facilities.resources) { if (id.equals(resourceInfo.id)) { return resourceInfo; } for (final String alias : resourceInfo.aliases) { if (alias.equals(id)) { return resourceInfo; } } } } if (sys != null) { for (final ResourceInfo resourceInfo : sys.facilities.resources) { if (id.equals(resourceInfo.id)) { return resourceInfo; } for (final String alias : resourceInfo.aliases) { if (alias.equals(id)) { return resourceInfo; } } } } return null; } public static boolean isResourceType(final String service, final List<String> types, final String type) { return type == null || service != null && types.contains(type); } protected List<String> getContainerIds() { final List<String> containerIds = new ArrayList<String>(); final OpenEjbConfiguration runningConfig = getRunningConfig(); if (runningConfig != null) { for (final ContainerInfo containerInfo : runningConfig.containerSystem.containers) { containerIds.add(containerInfo.id); } } if (sys != null) { for (final ContainerInfo containerInfo : sys.containerSystem.containers) { containerIds.add(containerInfo.id); } // The only time we'd have one of these is if we were building // the above sys instance if (openejb != null) { for (final Container container : openejb.getContainer()) { containerIds.add(container.getId()); } } } return containerIds; } protected List<ContainerInfo> getContainerInfos() { final List<ContainerInfo> containers = new ArrayList<ContainerInfo>(); final OpenEjbConfiguration runningConfig = getRunningConfig(); if (runningConfig != null) { for (final ContainerInfo containerInfo : runningConfig.containerSystem.containers) { containers.add(containerInfo); } } if (sys != null) { for (final ContainerInfo containerInfo : sys.containerSystem.containers) { containers.add(containerInfo); } } return containers; } private OpenEjbConfiguration getRunningConfig() { return SystemInstance.get().getComponent(OpenEjbConfiguration.class); } private static class TopicOrQueueDefaults { public static void process(final ServiceInfo provider) { if (!provider.service.equals("Resource")) { return; } if (!provider.types.contains("Topic") && !provider.types.contains("Queue")) { return; } if (!provider.className.matches("org.apache.activemq.command.ActiveMQ(Topic|Queue)")) { return; } final String dest = provider.properties.getProperty("destination"); if (dest == null || dest.length() == 0) { provider.properties.setProperty("destination", provider.id); } } } public static List<ResourceInfo> sort(final List<ResourceInfo> infos, final String prefix) { final Collection<String> ids = new HashSet<>(); return References.sort(infos, new References.Visitor<ResourceInfo>() { @Override // called first so we can rely on it to ensure we have ids full before any getReferences call public String getName(final ResourceInfo resourceInfo) { final String name = prefix != null && resourceInfo.id.startsWith(prefix) ? resourceInfo.id.substring(prefix.length()) : resourceInfo.id; ids.add(name); return name; } @Override public Set<String> getReferences(final ResourceInfo resourceInfo) { final Set<String> refs = new HashSet<>(); for (final Object value : resourceInfo.properties.values()) { if (!String.class.isInstance(value)) { continue; } final String string = String.class.cast(value).trim(); if (string.isEmpty()) { continue; } if (string.contains(",")) { // multiple references for (final String s : string.split(",")) { final String trim = s.trim(); if (ids.contains(trim)) { refs.add(trim); } } } else { final String trim = String.valueOf(value).trim(); final String id = (trim.startsWith("@") || trim.startsWith("$")) && trim.length() > 1 ? trim.substring(1) : trim; if (ids.contains(id)) { refs.add(id); } } } refs.remove(getName(resourceInfo)); // can happen with serviceId for instance, avoid cicular dep issue refs.addAll(resourceInfo.dependsOn); return refs; } }); } }