/*
 * 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.ContainerInfo;
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.event.BeforeAppInfoBuilderEvent;
import org.apache.openejb.config.sys.Container;
import org.apache.openejb.config.sys.Resource;
import org.apache.openejb.config.sys.Service;
import org.apache.openejb.config.sys.ServiceProvider;
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.SessionConfig;
import org.apache.openejb.jee.TransactionSupportType;
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.SystemInstance;
import org.apache.openejb.persistence.PersistenceBootstrap;
import org.apache.openejb.util.CircularReferencesException;
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.References;

import java.io.File;
import java.io.IOException;
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 javax.xml.bind.JAXBException;

import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
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 boolean USE_EAR_AS_CONTEXT_ROOT_BASE = SystemInstance.get().getOptions().get("openejb.ear.use-as-webcontext-base", false);

    private final ConfigurationFactory configFactory;

    private final EjbJarInfoBuilder ejbJarInfoBuilder = new EjbJarInfoBuilder();

    public AppInfoBuilder(final ConfigurationFactory configFactory) {
        this.configFactory = configFactory;
    }

    public AppInfo build(final AppModule appModule) throws OpenEJBException {
        // send an event so that it becomes pretty easy at this step to dynamically change the module description
        // before going into the info tree. Pretty easy to hack on portability issues.
        SystemInstance.get().fireEvent(new BeforeAppInfoBuilderEvent(appModule));

        final AppInfo appInfo = new AppInfo();
        appInfo.appId = appModule.getModuleId();
        appInfo.path = appModule.getJarLocation();
        appInfo.standaloneModule = appModule.isStandaloneModule() || appModule.isWebapp();
        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.buildAppContainers(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);
            }
        }

        for (final ContainerInfo containerInfo : appInfo.containers) {
            containerIds.add(containerInfo.id);
        }

        //
        //  EJB Jars
        //
        final Map<EjbModule, EjbJarInfo> ejbJarInfos = new HashMap<>();
        for (final EjbModule ejbModule : appModule.getEjbModules()) {
            try {
                final EjbJarInfo ejbJarInfo = this.ejbJarInfoBuilder.buildInfo(ejbModule);
                ejbJarInfo.mbeans = ejbModule.getMbeans();

                final Map<String, EjbDeployment> deploymentsByEjbName = ejbModule.getOpenejbJar().getDeploymentsByEjbName();

                for (final EnterpriseBeanInfo bean : ejbJarInfo.enterpriseBeans) {
                    final EjbDeployment d = deploymentsByEjbName.get(bean.ejbName);
                    if (d.getContainerId() != null && !containerIds.contains(d.getContainerId())) {
                        for (final ContainerInfo containerInfo : appInfo.containers) {
                            if (containerInfo.id.endsWith("/" + d.getContainerId())) {
                                d.setContainerId(containerInfo.id);
                                break;
                            }
                        }
                    }

                    /*
                     * 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 = new Messages("org.apache.openejb.util.resources").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();
                ejbJarInfo.webapp = ejbModule.isWebapp();
                this.configureWebserviceSecurity(ejbJarInfo, ejbModule);

                ejbJarInfos.put(ejbModule, ejbJarInfo);

                appInfo.ejbJars.add(ejbJarInfo);


            } catch (final 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<>();
        // 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(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<>(bean.dependsOn);
                }
            });
        } catch (final 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 (final 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 (final 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<Service> services = appModule.getServices();
        for (final 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 buildAppContainers(final AppModule module, final AppInfo info) throws OpenEJBException {
        final List<ContainerInfo> containerInfos = getContainerInfos(module);
        if (containerInfos == null) { return; }

        info.containers.addAll(containerInfos);
    }

    private List<ContainerInfo> getContainerInfos(AppModule module) throws OpenEJBException {
        return ContainerUtils.getContainerInfos(module, configFactory);
    }

    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();
            }

            webAppInfo.sessionTimeout = 30;
            if (webModule.getWebApp() != null && webModule.getWebApp().getSessionConfig() != null) {
                for (final SessionConfig sessionConfig : webModule.getWebApp().getSessionConfig()) {
                    if (sessionConfig.getSessionTimeout() != null) {
                        webAppInfo.sessionTimeout = sessionConfig.getSessionTimeout();
                        break;
                    }
                }
            }

            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 (final 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 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 (final 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();

                final ServiceProvider provider = new ServiceProvider(className, id, "Resource");
                provider.getTypes().add(className);

                ServiceUtils.registerServiceProvider(appId, provider);

                final Resource resource = new Resource(id, className, appId + "#" + id);

                for (final ConfigProperty property : resourceAdapter.getConfigProperty()) {
                    final String name = property.getConfigPropertyName();
                    final String value = property.getConfigPropertyValue();
                    if (value != null) {
                        resource.getProperties().setProperty(name, value);
                    }
                }
                connectorInfo.resourceAdapter = this.configFactory.configureService(resource, ResourceInfo.class);
            }

            final OutboundResourceAdapter outbound = resourceAdapter.getOutboundResourceAdapter();
            if (outbound != null) {
                String transactionSupport = "none";
                final TransactionSupportType transactionSupportType = outbound.getTransactionSupport();
                if (transactionSupportType != null) {
                    switch (transactionSupportType) {
                        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();

                    final ServiceProvider provider = new ServiceProvider(className, id, "Resource");
                    provider.getTypes().add(type);

                    ServiceUtils.registerServiceProvider(appId, provider);

                    final Resource resource = new Resource(id, type, appId + "#" + id);
                    final Properties properties = resource.getProperties();
                    for (final ConfigProperty property : connection.getConfigProperty()) {
                        final String name = property.getConfigPropertyName();
                        final 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);
                    }

                    final ResourceInfo resourceInfo = this.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());

                    final MdbContainerInfo mdbContainerInfo = this.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();

                final ServiceProvider provider = new ServiceProvider(className, id, "Resource");
                provider.getTypes().add(type);

                ServiceUtils.registerServiceProvider(appId, provider);

                final Resource resource = new Resource(id, type, appId + "#" + id);
                final Properties properties = resource.getProperties();
                for (final ConfigProperty property : adminObject.getConfigProperty()) {
                    final String name = property.getConfigPropertyName();
                    final String value = property.getConfigPropertyValue();
                    if (value != null) {
                        properties.setProperty(name, value);
                    }
                }
                final ResourceInfo resourceInfo = this.configFactory.configureService(resource, ResourceInfo.class);
                connectorInfo.adminObject.add(resourceInfo);
            }

            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 = appModule.persistenceUnitId(rootUrl, persistenceUnit.getName());
                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, 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 = PersistenceBootstrap.DEFAULT_PROVIDER;
        public static final String FORCE_PROVIDER_ENV = "openejb.jpa.force." + PROVIDER_PROP;

        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 ECLIPSELINK_TARGET_SERVER = "eclipselink.target-server";
        private static final String PREFIX_SESSION_CUSTOMIZER = "org.apache.openejb.jpa.integration.eclipselink.PrefixSessionCustomizer";
        private static final String OPENEJB_TARGET_SERVER = "org.apache.openejb.jpa.integration.eclipselink.OpenEJBServerPlatform";

        private static final String providerEnv;
        private static final boolean forceProviderEnv;
        private static final String transactionTypeEnv;
        private static final String jtaDataSourceEnv;
        private static final String nonJtaDataSourceEnv;

        static {
            providerEnv = SystemInstance.get().getOptions().get(PROVIDER_PROP, (String) null);
            forceProviderEnv = SystemInstance.get().getOptions().get(FORCE_PROVIDER_ENV, true);
            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 appModule the app module with its config and its temp classloader, take care to only use getResource here
         * @param info        the persistence unit info
         */
        private static void apply(final AppModule appModule, final PersistenceUnitInfo info) {
            final ClassLoader classLoader = appModule.getClassLoader();
            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) || "org.hibernate.jpa.HibernatePersistenceProvider".equals(info.provider)) {

                // Apply the overrides that apply to all persistence units of this provider
                override(appModule.getProperties(), 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.3
                    String key = HIBERNATE_JTA_PLATFORM;
                    String value = MakeTxLookup.HIBERNATE_NEW_FACTORY2;

                    if (classLoader.getResource(ClassLoaderUtil.resourceName("org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform")) == null) {
                        // previous hibernate 4
                        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(appModule.getProperties(), 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(appModule.getProperties(), info, "eclipselink");

                final String className = info.properties.getProperty(ECLIPSELINK_TARGET_SERVER);

                if (className == null || className.startsWith("org.eclipse.persistence.transaction")) {
                    if (classLoader.getResource(ClassLoaderUtil.resourceName(OPENEJB_TARGET_SERVER)) != null) {
                        info.properties.setProperty(ECLIPSELINK_TARGET_SERVER, OPENEJB_TARGET_SERVER);
                        logger.debug("Adjusting PersistenceUnit(name=" + info.name + ") property to " + ECLIPSELINK_TARGET_SERVER + "=" + OPENEJB_TARGET_SERVER);
                    } else {
                        logger.debug("Can't adjusting PersistenceUnit(name=" + info.name + ") property to " + ECLIPSELINK_TARGET_SERVER + "=" + OPENEJB_TARGET_SERVER + ", 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);
                    }
                }

                for (final String key : singletonList("eclipselink.jdbc.sequence-connection-pool.non-jta-data-source")) {
                    final String ds = info.properties.getProperty(key);
                    if (ds != null && !ds.contains(":") /* java:, openejb:, other: namespace */ ) {
                        info.properties.setProperty(key, "java:openejb/Resource/" + ds);
                    }
                }
            } 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(appModule.getProperties(), 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<>(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(appModule.getProperties(), info);

            for (final String key : asList("javax.persistence.jtaDataSource", "javax.persistence.nonJtaDataSource")) {
                final String ds = info.properties.getProperty(key);
                if (ds != null && !ds.contains(":") /* java:, openejb:, other: namespace */ ) {
                    info.properties.setProperty(key, "java:openejb/Resource/" + ds);
                }
            }
        }

        private static void overrideFromSystemProp(final PersistenceUnitInfo info) {
            if (providerEnv != null && (info.provider == null || forceProviderEnv)) {
                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 Properties appProperties, final PersistenceUnitInfo info) {
            override(appProperties, info, info.name);
        }

        private static void override(final Properties appProperties, final PersistenceUnitInfo info, final String prefix) {
            final Properties propertiesToCheckForOverridings = new Properties();
            propertiesToCheckForOverridings.putAll(appProperties);
            propertiesToCheckForOverridings.putAll(JavaSecurityManagers.getSystemProperties());
            propertiesToCheckForOverridings.putAll(SystemInstance.get().getProperties());
            final Properties overrides = ConfigurationFactory.getOverrides(propertiesToCheckForOverridings, prefix, "PersistenceUnit");

            for (final Map.Entry<Object, Object> entry : overrides.entrySet()) {
                final String property = (String) (prefix.equalsIgnoreCase(info.name) ? entry.getKey() : prefix + "." + entry.getKey());
                String value = (String) entry.getValue();

                if ("openjpa.Log".equals(property) && "org.apache.openejb.openjpa.JULOpenJPALogFactory".equals(value)) { // we set a default
                    if (info.properties.containsKey("openjpa.Log")) {
                        continue;
                    }
                    if (appProperties.containsKey("openjpa.Log")) {
                        value = appProperties.getProperty(property, value);
                    } else {
                        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<>();
        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");
    }

}
