/*
 * 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.commons.lang3.tuple.ImmutablePair;
import org.apache.openejb.ClassLoaderUtil;
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.api.LocalClient;
import org.apache.openejb.api.RemoteClient;
import org.apache.openejb.cdi.CompositeBeans;
import org.apache.openejb.classloader.ClassLoaderConfigurer;
import org.apache.openejb.classloader.WebAppEnricher;
import org.apache.openejb.config.event.BeforeDeploymentEvent;
import org.apache.openejb.config.event.EnhanceScannableUrlsEvent;
import org.apache.openejb.config.sys.Resources;
import org.apache.openejb.core.EmptyResourcesClassLoader;
import org.apache.openejb.core.ParentClassLoaderFinder;
import org.apache.openejb.jee.Application;
import org.apache.openejb.jee.ApplicationClient;
import org.apache.openejb.jee.Beans;
import org.apache.openejb.jee.Connector;
import org.apache.openejb.jee.EjbJar;
import org.apache.openejb.jee.FacesConfig;
import org.apache.openejb.jee.JavaWsdlMapping;
import org.apache.openejb.jee.JspConfig;
import org.apache.openejb.jee.Module;
import org.apache.openejb.jee.Taglib;
import org.apache.openejb.jee.TldTaglib;
import org.apache.openejb.jee.WebApp;
import org.apache.openejb.jee.WebserviceDescription;
import org.apache.openejb.jee.Webservices;
import org.apache.openejb.jee.oejb3.OpenejbJar;
import org.apache.openejb.loader.FileUtils;
import org.apache.openejb.loader.IO;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.sxc.ApplicationXml;
import org.apache.openejb.util.AnnotationFinder;
import org.apache.openejb.util.JarExtractor;
import org.apache.openejb.util.JavaSecurityManagers;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.openejb.util.URLs;
import org.apache.xbean.finder.IAnnotationFinder;
import org.apache.xbean.finder.ResourceFinder;
import org.apache.xbean.finder.UrlSet;
import org.apache.xbean.finder.archive.ClassesArchive;
import org.apache.xbean.finder.filter.Filter;
import org.apache.xbean.finder.filter.Filters;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;

/**
 * @version $Revision$ $Date$
 */
public class DeploymentLoader implements DeploymentFilterable {
    public static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, "org.apache.openejb.util.resources");
    public static final String OPENEJB_ALTDD_PREFIX = "openejb.altdd.prefix";

    static final String META_INF = "META-INF/";

    public static final String EAR_WEBAPP_PERSISTENCE_XML_JARS = "ear-webapp-persistence-xml-jars";
    public static final String EAR_SCOPED_CDI_BEANS = "ear-scoped-cdi-beans_";
    public static final String RAR_URLS_KEY = "rar-urls";
    public static final String URLS_KEY = "urls";

    private static final String RESOURCES_XML = "resources.xml";
    private static final String WEB_FRAGMENT_XML = "web-fragment.xml";

    private final boolean scanManagedBeans = true;
    private static final Collection<String> KNOWN_DESCRIPTORS = Arrays.asList("app-ctx.xml", "module.properties", "application.properties", "web.xml", "ejb-jar.xml", "openejb-jar.xml", "env-entries.properties", "beans.xml", "ra.xml", "application.xml", "application-client.xml", "persistence-fragment.xml", "persistence.xml", "validation.xml", NewLoaderLogic.EXCLUSION_FILE);
    private static String ALTDD = SystemInstance.get().getOptions().get(OPENEJB_ALTDD_PREFIX, (String) null);
    private volatile List<URL> containerUrls = null;

    @Deprecated // use load(File, ExternalConfiguration)
    public AppModule load(final File jarFile) throws OpenEJBException {
        return load(jarFile, null);
    }

    /**
     * @param jarFile the app file (war, jar, ear)
     * @param config potentially some more config, mainly used when linking to another system like tomcat to enrich the conf we can guess
     * @return the loaded module
     */
    public AppModule load(final File jarFile, final ExternalConfiguration config) throws OpenEJBException {
        // verify we have a valid file
        final String jarPath;
        try {
            jarPath = jarFile.getCanonicalPath();
        } catch (final IOException e) {
            throw new OpenEJBException("Invalid application file path " + jarFile, e);
        }

        final URL baseUrl = getFileUrl(jarFile);

        // create a class loader to use for detection of module type
        // do not use this class loader for any other purposes... it is
        // non-temp class loader and usage will mess up JPA
        ClassLoader doNotUseClassLoader = null;// = ClassLoaderUtil.createClassLoader(jarPath, new URL[]{baseUrl}, OpenEJB.class.getClassLoader());

        try {
            // determine the module type
            final Class<? extends DeploymentModule> moduleClass;

            try {
                doNotUseClassLoader = ClassLoaderUtil.createClassLoader(jarPath, new URL[]{baseUrl}, getOpenEJBClassLoader());
                moduleClass = discoverModuleType(baseUrl, ClassLoaderUtil.createTempClassLoader(doNotUseClassLoader), true);
            } catch (final Exception e) {
                throw new UnknownModuleTypeException("Unable to determine module type for jar: " + baseUrl.toExternalForm(), e);
            }

            if (ResourcesModule.class.equals(moduleClass)) {
                final AppModule appModule = new AppModule(null, jarPath);
                final ResourcesModule module = new ResourcesModule();
                module.getAltDDs().put(RESOURCES_XML, baseUrl);
                ReadDescriptors.readResourcesXml(module);
                module.initAppModule(appModule);
                // here module is no more useful since everything is in the appmodule
                return appModule;
            }

            //We always load AppModule, as it somewhat likes a wrapper module
            if (AppModule.class.equals(moduleClass)) {
                return createAppModule(jarFile, jarPath);
            }

            if (EjbModule.class.equals(moduleClass)) {
                final URL[] urls = new URL[]{baseUrl};

                SystemInstance.get().fireEvent(new BeforeDeploymentEvent(urls));

                final ClassLoader classLoader = ClassLoaderUtil.createTempClassLoader(jarPath, urls, getOpenEJBClassLoader());

                final AppModule appModule;
                //final Class<? extends DeploymentModule> o = EjbModule.class;
                final EjbModule ejbModule = createEjbModule(baseUrl, jarPath, classLoader);

                // wrap the EJB Module with an Application Module
                appModule = new AppModule(ejbModule);

                addPersistenceUnits(appModule, baseUrl);

                return appModule;
            }

            if (ClientModule.class.equals(moduleClass)) {
                final String jarLocation = URLs.toFilePath(baseUrl);
                final ClientModule clientModule = createClientModule(baseUrl, jarLocation, getOpenEJBClassLoader(), null);

                // Wrap the resource module with an Application Module
                return new AppModule(clientModule);
            }

            if (ConnectorModule.class.equals(moduleClass)) {
                final String jarLocation = URLs.toFilePath(baseUrl);
                final ConnectorModule connectorModule = createConnectorModule(jarLocation, jarLocation, getOpenEJBClassLoader(), null);
                if (connectorModule != null) {
                    final List<ConnectorModule> connectorModules = new ArrayList<>();

                    // let it be able to deploy the same connector several times
                    final String id = connectorModule.getModuleId();
                    if (!"true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.connector." + id + ".skip-default", "false"))) {
                        connectorModules.add(connectorModule);
                    }

                    final String aliases = SystemInstance.get().getProperty("openejb.connector." + id + ".aliases");
                    if (aliases != null) {
                        for (final String alias : aliases.split(",")) {
                            final ConnectorModule aliasModule = createConnectorModule(jarLocation, jarLocation, getOpenEJBClassLoader(), alias);
                            connectorModules.add(aliasModule);
                        }
                    }


                    // Wrap the resource module with an Application Module
                    final AppModule appModule = new AppModule(connectorModules.toArray(new ConnectorModule[connectorModules.size()]));

                    return appModule;
                }
            }

            if (WebModule.class.equals(moduleClass)) {
                final File file = URLs.toFile(baseUrl);

                // Standalone Web Module
                final WebModule webModule = createWebModule(file.getAbsolutePath(), baseUrl, getOpenEJBClassLoader(), getContextRoot(), getModuleName(), config);
                // important to use the webapp classloader here otherwise each time we'll check something using loadclass it will fail (=== empty classloader)
                final AppModule appModule = new AppModule(webModule.getClassLoader(), file.getAbsolutePath(), new Application(), true);
                addWebModule(webModule, appModule);

                addWebModuleDescriptors(baseUrl, webModule, appModule);

                appModule.setStandloneWebModule();
                appModule.setDelegateFirst(true); // force it for webapps
                return appModule;
            }

            if (PersistenceModule.class.equals(moduleClass)) {
                final String jarLocation = URLs.toFilePath(baseUrl);
                final ClassLoader classLoader = ClassLoaderUtil.createTempClassLoader(jarPath, new URL[]{baseUrl}, getOpenEJBClassLoader());

                // wrap the EJB Module with an Application Module
                final AppModule appModule = new AppModule(classLoader, jarLocation);

                // Persistence Units
                addPersistenceUnits(appModule, baseUrl);

                return appModule;
            }

            throw new UnsupportedModuleTypeException("Unsupported module type: " + moduleClass.getSimpleName());

        } finally {
            // if the application was unpacked appId used to create this class loader will be wrong
            // We can safely destroy this class loader in either case, as it was not use by any modules
            if (null != doNotUseClassLoader) {
                ClassLoaderUtil.destroyClassLoader(doNotUseClassLoader);
            }
        }
    }

    public static void addWebModuleDescriptors(final URL baseUrl, final WebModule webModule, final AppModule appModule) throws OpenEJBException {
        final List<URL> urls = webModule.getScannableUrls();
        final ResourceFinder finder = new ResourceFinder("", urls.toArray(new URL[urls.size()]));
        final Map<String, Object> otherDD = new HashMap<>(getDescriptors(finder, false));

        // "persistence.xml" is done separately since we manage a list of url and not s single url
        try {
            final List<URL> persistenceXmls = finder.findAll(META_INF + "persistence.xml");
            if (persistenceXmls.size() >= 1) {
                final URL old = (URL) otherDD.get("persistence.xml");
                if (old != null && !persistenceXmls.contains(old)) {
                    persistenceXmls.add(old);
                }
                otherDD.put("persistence.xml", persistenceXmls);
            }
        } catch (final IOException e) {
            // ignored
        }

        addConnectorModules(appModule, webModule);

        addWebPersistenceDD("persistence.xml", otherDD, appModule);
        addWebPersistenceDD("persistence-fragment.xml", otherDD, appModule);
        addPersistenceUnits(appModule, baseUrl);
        addWebFragments(webModule, urls);
    }

    private static void addConnectorModules(final AppModule appModule, final WebModule webModule) throws OpenEJBException {
        // WEB-INF
        if (webModule.getAltDDs().containsKey("ra.xml")) {
            final String jarLocation = new File(webModule.getJarLocation(), "/WEB-INF/classes").getAbsolutePath();
            final ConnectorModule connectorModule = createConnectorModule(jarLocation, jarLocation, webModule.getClassLoader(), webModule.getModuleId() + "RA", (URL) webModule.getAltDDs().get("ra.xml"));
            if (connectorModule != null) {
                appModule.getConnectorModules().add(connectorModule);
            }
        }

        // .rar
        for (final URL url : webModule.getRarUrls()) {
            try {
                final File file = URLs.toFile(url);
                if (file.getName().endsWith(".rar")) {
                    final String jarLocation = file.getAbsolutePath();
                    final ConnectorModule connectorModule = createConnectorModule(jarLocation, jarLocation, webModule.getClassLoader(), null);
                    if (connectorModule != null) {
                        appModule.getConnectorModules().add(connectorModule);
                    }
                }
            } catch (final Exception e) {
                LOGGER.error("error processing url " + url.toExternalForm(), e);
            }
        }

        for (final URL url : webModule.getScannableUrls()) {
            try {
                final File file = URLs.toFile(url);
                if (file.getName().endsWith(".jar")) {
                    try (JarFile jarFile = new JarFile(file)) {

                        // TODO: better management of altdd
                        String name = (ALTDD != null ? ALTDD + "." : "") + "ra.xml";

                        JarEntry entry = jarFile.getJarEntry(name);
                        if (entry == null) {
                            name = "META-INF/" + name;
                            entry = jarFile.getJarEntry(name);
                        }
                        if (entry == null) {
                            continue;
                        }

                        final String jarLocation = file.getAbsolutePath();
                        final ConnectorModule connectorModule = createConnectorModule(jarLocation, jarLocation, webModule.getClassLoader(), null);
                        if (connectorModule != null) {
                            appModule.getConnectorModules().add(connectorModule);
                        }
                    }
                }
            } catch (final Exception e) {
                LOGGER.error("error processing url " + url.toExternalForm(), e);
            }
        }
    }

    protected ClassLoader getOpenEJBClassLoader() {
        return ParentClassLoaderFinder.Helper.get();
    }

    @SuppressWarnings("unchecked")
    private static void addWebPersistenceDD(final String name, final Map<String, Object> otherDD, final AppModule appModule) {
        if (otherDD.containsKey(name)) {
            List<URL> persistenceUrls = (List<URL>) appModule.getAltDDs().get(name);
            if (persistenceUrls == null) {
                persistenceUrls = new ArrayList<>();
                appModule.getAltDDs().put(name, persistenceUrls);
            }

            if (otherDD.containsKey(name)) {
                final Object otherUrl = otherDD.get(name);
                if (otherUrl instanceof URL && !persistenceUrls.contains(otherUrl)) {
                    persistenceUrls.add((URL) otherUrl);
                } else if (otherUrl instanceof List) {
                    final List<URL> otherList = (List<URL>) otherDD.get(name);
                    for (final URL url : otherList) {
                        if (!persistenceUrls.contains(url)) {
                            persistenceUrls.add(url);
                        }
                    }
                }
            }
        }
    }

    protected AppModule createAppModule(final File jarFile, final String jarPath) throws OpenEJBException {
        File appDir = unpack(jarFile);
        try {
            appDir = appDir.getCanonicalFile();
        } catch (final IOException e) {
            throw new OpenEJBException("Invalid application directory " + appDir.getAbsolutePath());
        }

        final URL appUrl = getFileUrl(appDir);

        final String appId = appDir.getAbsolutePath();
        final ClassLoader tmpClassLoader = ClassLoaderUtil.createTempClassLoader(appId, new URL[]{appUrl}, getOpenEJBClassLoader());

        final ResourceFinder finder = new ResourceFinder("", tmpClassLoader, appUrl);
        final Map<String, URL> appDescriptors = getDescriptors(finder);

        try {

            //
            // Find all the modules using either the application xml or by searching for all .jar, .war and .rar files.
            //

            final Map<String, URL> ejbModules = new LinkedHashMap<>();
            final Map<String, URL> clientModules = new LinkedHashMap<>();
            final Map<String, URL> resouceModules = new LinkedHashMap<>();
            final Map<String, URL> webModules = new LinkedHashMap<>();
            final Map<String, String> webContextRoots = new LinkedHashMap<>();

            final URL applicationXmlUrl = appDescriptors.get("application.xml");
            final List<URL> extraLibs = new ArrayList<>();

            final Application application;
            if (applicationXmlUrl != null) {

                application = unmarshal(applicationXmlUrl);
                for (final Module module : application.getModule()) {
                    try {
                        if (module.getEjb() != null) {
                            final URL url = finder.find(module.getEjb().trim());
                            ejbModules.put(module.getEjb(), url);
                        } else if (module.getJava() != null) {
                            final URL url = finder.find(module.getJava().trim());
                            clientModules.put(module.getJava(), url);
                            extraLibs.add(url);
                        } else if (module.getConnector() != null) {
                            final URL url = finder.find(module.getConnector().trim());
                            resouceModules.put(module.getConnector(), url);
                        } else if (module.getWeb() != null) {
                            final URL url = finder.find(module.getWeb().getWebUri().trim());
                            webModules.put(module.getWeb().getWebUri(), url);
                            webContextRoots.put(module.getWeb().getWebUri(), module.getWeb().getContextRoot());
                        }
                    } catch (final IOException e) {
                        throw new OpenEJBException("Invalid path to module " + e.getMessage(), e);
                    }
                }
            } else {
                application = new Application();
                final HashMap<String, URL> files = new HashMap<>();
                scanDir(appDir, files, "", false);
                files.remove("META-INF/MANIFEST.MF");

                // todo we should also filter URLs here using DeploymentsResolver.loadFromClasspath

                createApplicationFromFiles(appId, tmpClassLoader, ejbModules, clientModules, resouceModules, webModules, files);
            }

            final ClassLoaderConfigurer configurer = QuickJarsTxtParser.parse(new File(appDir, "META-INF/" + QuickJarsTxtParser.FILE_NAME));
            final Collection<URL> jarsXmlLib = new ArrayList<>();
            if (configurer != null) {
                for (final URL url : configurer.additionalURLs()) {
                    try {
                        detectAndAddModuleToApplication(appId, tmpClassLoader,
                            ejbModules, clientModules, resouceModules, webModules,
                            new ImmutablePair<>(URLs.toFile(url).getAbsolutePath(), url));
                    } catch (final Exception e) {
                        jarsXmlLib.add(url);
                    }
                }
            }

            //
            // Create a class loader for the application
            //

            // lib/*
            if (application.getLibraryDirectory() == null) {
                application.setLibraryDirectory("lib/");
            } else {
                final String dir = application.getLibraryDirectory();
                if (!dir.endsWith("/")) {
                    application.setLibraryDirectory(dir + "/");
                }
            }

            try {
                final Map<String, URL> libs = finder.getResourcesMap(application.getLibraryDirectory());
                extraLibs.addAll(libs.values());
            } catch (final IOException e) {
                LOGGER.warning("Cannot load libs from '" + application.getLibraryDirectory() + "' : " + e.getMessage(), e);
            }

            // APP-INF/lib/*
            try {
                final Map<String, URL> libs = finder.getResourcesMap("APP-INF/lib/");
                extraLibs.addAll(libs.values());
            } catch (final IOException e) {
                LOGGER.warning("Cannot load libs from 'APP-INF/lib/' : " + e.getMessage(), e);
            }

            // META-INF/lib/*
            try {
                final Map<String, URL> libs = finder.getResourcesMap("META-INF/lib/");
                extraLibs.addAll(libs.values());
            } catch (final IOException e) {
                LOGGER.warning("Cannot load libs from 'META-INF/lib/' : " + e.getMessage(), e);
            }

            // All jars nested in the Resource Adapter
            final HashMap<String, URL> rarLibs = new HashMap<>();
            for (final Map.Entry<String, URL> entry : resouceModules.entrySet()) {
                try {
                    // unpack the resource adapter archive
                    File rarFile = URLs.toFile(entry.getValue());
                    rarFile = unpack(rarFile);
                    entry.setValue(rarFile.toURI().toURL());

                    scanDir(appDir, rarLibs, "");
                } catch (final MalformedURLException e) {
                    throw new OpenEJBException("Malformed URL to app. " + e.getMessage(), e);
                }
            }
            for (final Iterator<Map.Entry<String, URL>> iterator = rarLibs.entrySet().iterator(); iterator.hasNext(); ) {
                // remove all non jars from the rarLibs
                final Map.Entry<String, URL> fileEntry = iterator.next();
                if (!fileEntry.getKey().endsWith(".jar")) {
                    continue;
                }
                iterator.remove();
            }

            final List<URL> classPath = new ArrayList<>();
            classPath.addAll(ejbModules.values());
            classPath.addAll(clientModules.values());
            classPath.addAll(rarLibs.values());
            classPath.addAll(extraLibs);
            classPath.addAll(jarsXmlLib);
            final URL[] urls = classPath.toArray(new URL[classPath.size()]);

            SystemInstance.get().fireEvent(new BeforeDeploymentEvent(urls));

            final ClassLoader appClassLoader = ClassLoaderUtil.createTempClassLoader(appId, urls, getOpenEJBClassLoader());

            //
            // Create the AppModule and all nested module objects
            //

            final AppModule appModule = new AppModule(appClassLoader, appId, application, false);
            appModule.getAdditionalLibraries().addAll(extraLibs);
            appModule.getAltDDs().putAll(appDescriptors);
            appModule.getWatchedResources().add(appId);
            if (applicationXmlUrl != null) {
                appModule.getWatchedResources().add(URLs.toFilePath(applicationXmlUrl));
            }
            if (appDescriptors.containsKey(RESOURCES_XML)) {
                final Map<String, Object> altDd = new HashMap<>(appDescriptors);
                ReadDescriptors.readResourcesXml(new org.apache.openejb.config.Module(false) {
                    @Override
                    public Map<String, Object> getAltDDs() {
                        return altDd;
                    }

                    @Override
                    public void initResources(final Resources resources) {
                        appModule.getContainers().addAll(resources.getContainer());
                        appModule.getResources().addAll(resources.getResource());
                        appModule.getServices().addAll(resources.getService());
                    }
                });
            }

            // EJB modules
            for (final Map.Entry<String, URL> stringURLEntry : ejbModules.entrySet()) {
                try {
                    URL ejbUrl = stringURLEntry.getValue();
                    // we should try to use a reference to the temp classloader
                    if (ClassLoaderUtil.isUrlCached(appModule.getJarLocation(), ejbUrl)) {
                        try {
                            ejbUrl = ClassLoaderUtil.getUrlCachedName(appModule.getJarLocation(), ejbUrl).toURI().toURL();

                        } catch (final MalformedURLException ignore) {
                            // no-op
                        }
                    }
                    final File ejbFile = URLs.toFile(ejbUrl);
                    final String absolutePath = ejbFile.getAbsolutePath();

                    final EjbModule ejbModule = createEjbModule(ejbUrl, absolutePath, appClassLoader);
                    appModule.getEjbModules().add(ejbModule);
                } catch (final OpenEJBException e) {
                    LOGGER.error("Unable to load EJBs from EAR: " + appId + ", module: " + stringURLEntry.getKey() + ". Exception: " + e.getMessage(), e);
                }
            }

            // Application Client Modules
            for (final Map.Entry<String, URL> stringURLEntry : clientModules.entrySet()) {
                try {
                    URL clientUrl = stringURLEntry.getValue();
                    // we should try to use a reference to the temp classloader
                    if (ClassLoaderUtil.isUrlCached(appModule.getJarLocation(), clientUrl)) {
                        try {
                            clientUrl = ClassLoaderUtil.getUrlCachedName(appModule.getJarLocation(), clientUrl).toURI().toURL();

                        } catch (final MalformedURLException ignore) {
                            // no-op
                        }
                    }
                    final File clientFile = URLs.toFile(clientUrl);
                    final String absolutePath = clientFile.getAbsolutePath();

                    final ClientModule clientModule = createClientModule(clientUrl, absolutePath, appClassLoader, null);

                    appModule.getClientModules().add(clientModule);
                } catch (final Exception e) {
                    LOGGER.error("Unable to load App Client from EAR: " + appId + ", module: " + stringURLEntry.getKey() + ". Exception: " + e.getMessage(), e);
                }
            }

            // Resource modules
            for (final Map.Entry<String, URL> stringURLEntry : resouceModules.entrySet()) {
                try {
                    URL rarUrl = stringURLEntry.getValue();
                    // we should try to use a reference to the temp classloader
                    if (ClassLoaderUtil.isUrlCached(appModule.getJarLocation(), rarUrl)) {
                        try {
                            rarUrl = ClassLoaderUtil.getUrlCachedName(appModule.getJarLocation(), rarUrl).toURI().toURL();

                        } catch (final MalformedURLException ignore) {
                            // no-op
                        }
                    }
                    final ConnectorModule connectorModule = createConnectorModule(appId, URLs.toFilePath(rarUrl), appClassLoader, stringURLEntry.getKey());
                    if (connectorModule != null) {
                        appModule.getConnectorModules().add(connectorModule);
                    }
                } catch (final OpenEJBException e) {
                    LOGGER.error("Unable to load RAR: " + appId + ", module: " + stringURLEntry.getKey() + ". Exception: " + e.getMessage(), e);
                }
            }

            // Web modules
            for (final Map.Entry<String, URL> stringURLEntry : webModules.entrySet()) {
                try {
                    final URL warUrl = stringURLEntry.getValue();
                    addWebModule(appModule, warUrl, appClassLoader, webContextRoots.get(stringURLEntry.getKey()), null);
                } catch (final OpenEJBException e) {
                    LOGGER.error("Unable to load WAR: " + appId + ", module: " + stringURLEntry.getKey() + ". Exception: " + e.getMessage(), e);
                }
            }


            addBeansXmls(appModule);

            // Persistence Units
            final Properties p = new Properties();
            p.put(appModule.getModuleId(), appModule.getJarLocation());
            final FileUtils base = new FileUtils(appModule.getModuleId(), appModule.getModuleId(), p);
            final List<URL> filteredUrls = new ArrayList<>();
            DeploymentsResolver.loadFromClasspath(base, filteredUrls, appModule.getClassLoader());
            addPersistenceUnits(appModule, filteredUrls.toArray(new URL[filteredUrls.size()]));

            final Object pXmls = appModule.getAltDDs().get("persistence.xml");

            for (final WebModule webModule : appModule.getWebModules()) {
                final List<URL> foundRootUrls = new ArrayList<>();
                final List<URL> scannableUrls = webModule.getScannableUrls();
                for (final URL url : scannableUrls) {
                    if (!addPersistenceUnits(appModule, url).isEmpty()) {
                        foundRootUrls.add(url);
                    }
                }

                if (pXmls != null && Collection.class.isInstance(pXmls)) {
                    final File webapp = webModule.getFile();
                    if (webapp == null) {
                        continue;
                    }
                    final String webappAbsolutePath = webapp.getAbsolutePath();

                    final Collection<URL> list = Collection.class.cast(pXmls);
                    for (final URL url : list) {
                        try {
                            final File file = URLs.toFile(url);
                            if (file.getAbsolutePath().startsWith(webappAbsolutePath)) {
                                foundRootUrls.add(url);
                            }
                        } catch (final IllegalArgumentException iae) {
                            // no-op
                        }
                    }
                }

                webModule.getAltDDs().put(EAR_WEBAPP_PERSISTENCE_XML_JARS, foundRootUrls);
            }

            for (final DeploymentModule module : appModule.getDeploymentModule()) {
                module.setStandaloneModule(false);
            }

            return appModule;

        } catch (final OpenEJBException e) {
            LOGGER.error("Unable to load EAR: " + jarPath, e);
            throw e;
        }
    }

    private void createApplicationFromFiles(final String appId, final ClassLoader tmpClassLoader, final Map<String, URL> ejbModules, final Map<String, URL> clientModules, final Map<String, URL> resouceModules, final Map<String, URL> webModules, final HashMap<String, URL> files) throws OpenEJBException {
        for (final Map.Entry<String, URL> entry : files.entrySet()) {
            // if (entry.getKey().startsWith("lib/")) continue;// will not be scanned since we don't get folder anymore
            if (!entry.getKey().matches(".*\\.(jar|war|rar|ear)")) {
                continue;
            }

            try {
                detectAndAddModuleToApplication(appId, tmpClassLoader, ejbModules, clientModules, resouceModules, webModules, entry);
            } catch (final UnsupportedOperationException | UnknownModuleTypeException e) {
                // Ignore it as per the javaee spec EE.8.4.2 section 1.d.iii
                LOGGER.info("Ignoring unknown module type: " + entry.getKey());
            } catch (final Exception e) {
                throw new OpenEJBException("Unable to determine the module type of " + entry.getKey() + ": Exception: " + e.getMessage(), e);
            }
        }
    }

    private void detectAndAddModuleToApplication(final String appId, final ClassLoader tmpClassLoader, final Map<String, URL> ejbModules, final Map<String, URL> clientModules, final Map<String, URL> resouceModules, final Map<String, URL> webModules, final Map.Entry<String, URL> entry) throws IOException, UnknownModuleTypeException {
        final ClassLoader moduleClassLoader = ClassLoaderUtil.createTempClassLoader(appId, new URL[]{entry.getValue()}, tmpClassLoader);

        final Class<? extends DeploymentModule> moduleType = discoverModuleType(entry.getValue(), moduleClassLoader, true);

        if (EjbModule.class.equals(moduleType)) {
            ejbModules.put(entry.getKey(), entry.getValue());
        } else if (ClientModule.class.equals(moduleType)) {
            clientModules.put(entry.getKey(), entry.getValue());
        } else if (ConnectorModule.class.equals(moduleType)) {
            resouceModules.put(entry.getKey(), entry.getValue());
        } else if (WebModule.class.equals(moduleType)) {
            webModules.put(entry.getKey(), entry.getValue());
        }
    }

    protected ClientModule createClientModule(final URL clientUrl, final String absolutePath, final ClassLoader appClassLoader, final String moduleName) throws OpenEJBException {
        return createClientModule(clientUrl, absolutePath, appClassLoader, moduleName, true);
    }

    protected ClientModule createClientModule(final URL clientUrl, final String absolutePath, final ClassLoader appClassLoader, final String moduleName, final boolean log) throws OpenEJBException {
        final ResourceFinder clientFinder = new ResourceFinder(clientUrl);

        URL manifestUrl = null;
        try {
            manifestUrl = clientFinder.find("META-INF/MANIFEST.MF");
        } catch (final IOException e) {
            //
        }

        String mainClass = null;
        if (manifestUrl != null) {
            try {
                final InputStream is = IO.read(manifestUrl);
                final Manifest manifest = new Manifest(is);
                mainClass = manifest.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
            } catch (final IOException e) {
                throw new OpenEJBException("Unable to determine Main-Class defined in META-INF/MANIFEST.MF file", e);
            }
        }

//        if (mainClass == null) throw new IllegalStateException("No Main-Class defined in META-INF/MANIFEST.MF file");

        final Map<String, URL> descriptors = getDescriptors(clientFinder, log);

        ApplicationClient applicationClient = null;
        final URL clientXmlUrl = descriptors.get("application-client.xml");
        if (clientXmlUrl != null) {
            applicationClient = ReadDescriptors.readApplicationClient(clientXmlUrl);
        }

        final ClientModule clientModule = new ClientModule(applicationClient, appClassLoader, absolutePath, mainClass, moduleName);

        clientModule.getAltDDs().putAll(descriptors);
        if (absolutePath != null) {
            clientModule.getWatchedResources().add(absolutePath);
        }
        if (clientXmlUrl != null && "file".equals(clientXmlUrl.getProtocol())) {
            clientModule.getWatchedResources().add(URLs.toFilePath(clientXmlUrl));
        }
        return clientModule;
    }

    protected EjbModule createEjbModule(final URL baseUrl, final String jarPath, final ClassLoader classLoader) throws OpenEJBException {
        // read the ejb-jar.xml file
        Map<String, URL> descriptors;
        if (baseUrl != null) {
            descriptors = getDescriptors(baseUrl);
        } else {
            try {
                descriptors = getDescriptors(classLoader, null);
            } catch (final IOException e) {
                descriptors = new HashMap<>();
            }
        }

        EjbJar ejbJar = null;
        final URL ejbJarXmlUrl = descriptors.get("ejb-jar.xml");
        if (ejbJarXmlUrl != null) {
            try {
                ejbJar = ReadDescriptors.readEjbJar(ejbJarXmlUrl.openStream());
            } catch (final IOException e) {
                throw new OpenEJBException(e);
            }
        }

        // create the EJB Module
        final EjbModule ejbModule = new EjbModule(classLoader, null, jarPath, ejbJar, null);
        ejbModule.getAltDDs().putAll(descriptors);
        if (jarPath != null) {
            ejbModule.getWatchedResources().add(jarPath);
        }
        if (ejbJarXmlUrl != null && "file".equals(ejbJarXmlUrl.getProtocol())) {
            ejbModule.getWatchedResources().add(URLs.toFilePath(ejbJarXmlUrl));
        }

        ejbModule.setClientModule(createClientModule(baseUrl, jarPath, classLoader, null, false));

        // load webservices descriptor
        addWebservices(ejbModule);
        return ejbModule;
    }

    private WebModule createWebModule(final String jar, final URL warUrl, final ClassLoader parentClassLoader, final String contextRoot, final String moduleName, final ExternalConfiguration config) throws OpenEJBException {
        return createWebModule(jar, URLs.toFilePath(warUrl), parentClassLoader, contextRoot, moduleName, config);
    }

    public void addWebModule(final AppModule appModule, final URL warUrl, final ClassLoader parentClassLoader, final String contextRoot, final String moduleName) throws OpenEJBException {
        final WebModule webModule = createWebModule(appModule.getJarLocation(), URLs.toFilePath(warUrl), parentClassLoader, contextRoot, moduleName, null);
        addWebModule(webModule, appModule);
    }

    public static EjbModule addWebModule(final WebModule webModule, final AppModule appModule) throws OpenEJBException {
        // create and add the WebModule
        appModule.getWebModules().add(webModule);
        if (appModule.isStandaloneModule()) {
            appModule.getAdditionalLibraries().addAll(webModule.getUrls());
        }

        {
            final Object pXml = appModule.getAltDDs().get("persistence.xml");

            List<URL> persistenceXmls = pXml == null ? null : (List.class.isInstance(pXml) ? (List<URL>) pXml :
                    new ArrayList<>(Collections.singletonList(URL.class.cast(pXml))));
            if (persistenceXmls == null) {
                persistenceXmls = new ArrayList<>();
                appModule.getAltDDs().put("persistence.xml", persistenceXmls);
            }

            final Object o = webModule.getAltDDs().get("persistence.xml");

            if (o instanceof URL) {
                final URL url = (URL) o;
                persistenceXmls.add(url);
            }

            if (o instanceof List) {
                final List<URL> urls = (List<URL>) o;
                persistenceXmls.addAll(urls);
            }
        }


        // Per the Spec version of the Collapsed EAR there
        // aren't individual EjbModules inside a war.
        // The war itself is one big EjbModule if certain
        // conditions are met.  These conditions are different
        // than an ear file, so the ear-style code we were previously
        // using doesn't exactly work anymore.
        final EjbModule webEjbModule = new EjbModule(webModule.getClassLoader(), webModule.getModuleId(), webModule.getJarLocation(), null, null);
        webEjbModule.setWebapp(true);
        webEjbModule.getAltDDs().putAll(webModule.getAltDDs());
        appModule.getEjbModules().add(webEjbModule);

        try {
            // TODO:  Put our scanning ehnancements back, here
            fillEjbJar(webModule, webEjbModule);

            if (webModule.getFinder() == null) {
                if (isMetadataComplete(webModule, webEjbModule)) {
                    final IAnnotationFinder finder = new org.apache.xbean.finder.AnnotationFinder(new ClassesArchive());
                    webModule.setFinder(finder);
                    webEjbModule.setFinder(finder);
                } else {
                    final IAnnotationFinder finder = FinderFactory.createFinder(webModule);
                    webModule.setFinder(finder);
                    webEjbModule.setFinder(finder);
                }
            } else if (webEjbModule.getFinder() == null) {
                webEjbModule.setFinder(webModule.getFinder());
            }
        } catch (final Exception e) {
            throw new OpenEJBException("Unable to create annotation scanner for web module " + webModule.getModuleId(), e);
        }

        addWebservices(webEjbModule);

        return webEjbModule;
    }

    /**
     * If the web.xml is metadata-complete and there is no ejb-jar.xml
     * then per specification we use the web.xml metadata-complete setting
     * to imply the same for EJBs.
     *
     * @param webModule WebModule
     * @param ejbModule EjbModule
     */
    private static void fillEjbJar(final WebModule webModule, final EjbModule ejbModule) {
        final Object o = webModule.getAltDDs().get("ejb-jar.xml");
        if (o != null) {
            return;
        }
        if (ejbModule.getEjbJar() != null) {
            return;
        }

        final EjbJar ejbJar = new EjbJar();
        final WebApp webApp = webModule.getWebApp();

        ejbJar.setMetadataComplete(webApp.isMetadataComplete());

        ejbModule.setEjbJar(ejbJar);
    }

    private static boolean isMetadataComplete(final WebModule webModule, final EjbModule ejbModule) {
        if (webModule.getWebApp() == null) {
            return false;
        }
        if (!webModule.getWebApp().isMetadataComplete()) {
            return false;
        }

        // At this point we know the web.xml is metadata-complete
        // We need to determine if there are cdi or ejb xml files
        if (webModule.getAltDDs().get("beans.xml") == null) {
            return true;
        }
        if (ejbModule.getEjbJar() == null) {
            return true;
        }
        return ejbModule.getEjbJar().isMetadataComplete();

    }

    public WebModule createWebModule(final String appId, final String warPath, final ClassLoader parentClassLoader, final String contextRoot, final String moduleName, final ExternalConfiguration config) throws OpenEJBException {
        File warFile = new File(warPath);
        if (!warFile.isDirectory()) {
            warFile = unpack(warFile);
        }

        // read web.xml file
        final Map<String, URL> descriptors;
        try {
            descriptors = getWebDescriptors(warFile);
        } catch (final IOException e) {
            throw new OpenEJBException("Unable to collect descriptors in web module: " + contextRoot, e);
        }

        final WebApp webApp;
        final URL webXmlUrl = descriptors.get("web.xml");
        if (webXmlUrl != null) {
            webApp = ReadDescriptors.readWebApp(webXmlUrl);
        } else {
            // no web.xml webapp - possible since Servlet 3.0
            webApp = new WebApp();
        }

        // determine war class path

        ensureContainerUrls();
        final List<URL> webUrls = new ArrayList<>(containerUrls);

        final SystemInstance systemInstance = SystemInstance.get();

        // add these urls first to ensure we load classes from here first
        final String externalRepos = systemInstance.getProperty("tomee." + warFile.getName().replace(".war", "") + ".externalRepositories");
        List<URL> externalUrls = null;
        if (externalRepos != null) {
            externalUrls = new ArrayList<>();
            for (final String additional : externalRepos.split(",")) {
                final String trim = additional.trim();
                if (!trim.isEmpty()) {
                    try {
                        externalUrls.add(new File(trim).toURI().toURL());
                    } catch (final MalformedURLException e) {
                        LOGGER.error(e.getMessage());
                    }
                }
            }
            webUrls.addAll(externalUrls);
        }

        final Map<String, URL[]> urls = getWebappUrlsAndRars(warFile);
        webUrls.addAll(Arrays.asList(urls.get(URLS_KEY)));

        final List<URL> addedUrls = new ArrayList<>();
        for (final URL url : urls.get(RAR_URLS_KEY)) { // eager unpack to be able to use it in classloader
            final File[] files = unpack(URLs.toFile(url)).listFiles();
            if (files != null) {
                for (final File f : files) {
                    if (f.getName().endsWith(".jar")) {
                        try {
                            addedUrls.add(f.toURI().toURL());
                        } catch (final MalformedURLException e) {
                            LOGGER.warning("War path bad: " + f.getAbsolutePath(), e);
                        }
                    }
                }
            }
        }
        webUrls.addAll(addedUrls);

        // context.xml can define some additional libraries
        if (config != null) { // we don't test all !=null inline to show that config will get extra params in the future and that it is hierarchic
            if (config.getClasspath() != null && config.getClasspath().length > 0) {
                final Set<URL> contextXmlUrls = new LinkedHashSet<>();
                for (final String location : config.getClasspath()) {
                    try {
                        webUrls.add(new File(location).toURI().toURL());
                    } catch (final MalformedURLException e) {
                        throw new IllegalArgumentException(e);
                    }
                }
                webUrls.addAll(contextXmlUrls);
            }
        }

        final ClassLoaderConfigurer configurer = QuickJarsTxtParser.parse(new File(warFile, "WEB-INF/" + QuickJarsTxtParser.FILE_NAME));
        if (configurer != null) {
            ClassLoaderConfigurer.Helper.configure(webUrls, configurer);
        }

        final URL[] webUrlsArray = webUrls.toArray(new URL[webUrls.size()]);

        // in TomEE this is done in init hook since we don't manage tomee webapp classloader
        // so here is not the best idea for tomee
        // if we want to manage it in a generic way
        // simply add a boolean shared between tomcat and openejb world
        // to know if we should fire it or not
        systemInstance.fireEvent(new BeforeDeploymentEvent(webUrlsArray, parentClassLoader));

        final ClassLoader warClassLoader = ClassLoaderUtil.createTempClassLoader(appId, webUrlsArray, parentClassLoader);

        // create web module
        final List<URL> scannableUrls = filterWebappUrls(webUrlsArray, config == null ? null : config.customerFilter, descriptors.get(NewLoaderLogic.EXCLUSION_FILE));
        // executable war will add war in scannable urls, we don't want it since it will surely contain tomee, cxf, ...
        if (Boolean.parseBoolean(systemInstance.getProperty("openejb.core.skip-war-in-loader", "true"))) {
            File archive = warFile;
            if (!archive.getName().endsWith(".war")) {
                archive = new File(warFile.getParentFile(), warFile.getName() + ".war");
                final String unpackDir = systemInstance.getProperty("tomee.unpack.dir");
                if (unpackDir != null && !archive.isFile()) {
                    try {
                        archive = new File(systemInstance.getBase().getDirectory(unpackDir, false), warFile.getName());
                    } catch (final IOException e) {
                        // no-op
                    }
                }
            }
            if (archive.isFile()) {
                try {
                    scannableUrls.remove(archive.toURI().toURL());
                } catch (final MalformedURLException e) {
                    // no-op
                }
            }
        }
        if (externalUrls != null) {
            for (final URL url : externalUrls) {
                if (scannableUrls.contains(url)) {
                    scannableUrls.remove(url);
                    scannableUrls.add(0, url);
                }
            }
        }

        SystemInstance.get().fireEvent(new EnhanceScannableUrlsEvent(scannableUrls));

        final WebModule webModule = new WebModule(webApp, contextRoot, warClassLoader, warFile.getAbsolutePath(), moduleName);
        webModule.setUrls(webUrls);
        webModule.setAddedUrls(addedUrls);
        webModule.setRarUrls(Arrays.asList(urls.get(RAR_URLS_KEY)));
        webModule.setScannableUrls(scannableUrls);
        webModule.getAltDDs().putAll(descriptors);
        webModule.getWatchedResources().add(warPath);
        webModule.getWatchedResources().add(warFile.getAbsolutePath());
        if (webXmlUrl != null && "file".equals(webXmlUrl.getProtocol())) {
            webModule.getWatchedResources().add(URLs.toFilePath(webXmlUrl));
        }

        //If webModule object is loaded by ejbModule or persitenceModule, no need to load tag libraries, web service and JSF related staffs.
        addTagLibraries(webModule);

        // load webservices descriptor
        addWebservices(webModule);

        // load faces configuration files
        addFacesConfigs(webModule);

        addBeansXmls(webModule);

        return webModule;
    }

    private void ensureContainerUrls() {
        if (containerUrls == null) {
            if ("true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.scan.webapp.container", "false"))) {
                synchronized (this) {
                    if (containerUrls == null) {
                        try {
                            UrlSet urlSet = new UrlSet(ParentClassLoaderFinder.Helper.get());
                            urlSet = URLs.cullSystemJars(urlSet);
                            urlSet = NewLoaderLogic.applyBuiltinExcludes(urlSet);
                            containerUrls = urlSet.getUrls();

                            final boolean skipContainerFolders = "true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.scan.webapp.container.skip-folder", "true"));
                            final Iterator<URL> it = containerUrls.iterator();
                            while (it.hasNext()) { // remove lib/
                                final File file = URLs.toFile(it.next());
                                // TODO: see if websocket should be added in default.exclusions
                                final String name = file.getName();
                                if ((skipContainerFolders && file.isDirectory())
                                        // few hardcoded exclusions, TODO: see if we should filter them in previous call of applyBuiltinExcludes()
                                        || name.endsWith("tomcat-websocket.jar")
                                        || name.startsWith("commons-jcs-")
                                        || name.startsWith("xx-arquillian-tomee")
                                        || ("lib".equals(name) && file.isDirectory() &&
                                            new File(JavaSecurityManagers.getSystemProperty("openejb.base", "-")).equals(file.getParentFile()))) {
                                    it.remove();
                                }
                            }
                        } catch (final Exception e) {
                            LOGGER.error(e.getMessage(), e);
                        }
                    }
                }
            } else {
                containerUrls = new ArrayList<>();
            }
        }
    }

    public static List<URL> filterWebappUrls(final URL[] webUrls, final Filter filter, final URL exclusions) {
        Filter excludeFilter = null;
        if (exclusions != null) {
            try {
                final String[] prefixes = NewLoaderLogic.readInputStreamList(exclusions.openStream());
                excludeFilter = Filters.prefixes(prefixes);
            } catch (final IOException e) {
                LOGGER.warning("can't read " + exclusions.toExternalForm());
            }
        }

        UrlSet urls = new UrlSet(webUrls);
        try {
            urls = NewLoaderLogic.applyBuiltinExcludes(urls, filter, excludeFilter);
        } catch (final MalformedURLException e) {
            return Arrays.asList(webUrls);
        }
        return urls.getUrls();
    }

    public static void addBeansXmls(final WebModule webModule) {
        final List<URL> urls = webModule.getScannableUrls();
        // parent returns nothing when calling getresources because we don't want here to be fooled by maven classloader
        final URLClassLoader loader = new URLClassLoader(urls.toArray(new URL[urls.size()]), new EmptyResourcesClassLoader());

        final List<URL> xmls = new LinkedList<>();
        try {
            final URL e = (URL) webModule.getAltDDs().get("beans.xml");
            if (e != null) { // first!
                xmls.add(e);
            }
            xmls.addAll(Collections.list(loader.getResources("META-INF/beans.xml")));
        } catch (final IOException e) {
            return;
        }

        final CompositeBeans complete = new CompositeBeans();
        for (final URL url : xmls) {
            if (url == null) {
                continue;
            }
            mergeBeansXml(complete, url);
        }
        if (!complete.getDiscoveryByUrl().isEmpty()) {
            complete.removeDuplicates();
        }
        webModule.getAltDDs().put("beans.xml", complete);
    }

    private static Beans mergeBeansXml(final CompositeBeans current, final URL url) {
        try {
            final Beans beans;
            try {
                beans = ReadDescriptors.readBeans(url.openStream());
            } catch (final IOException e) {
                return current;
            }

            doMerge(url, current, beans);
        } catch (final OpenEJBException e) {
            LOGGER.error("Unable to read beans.xml from: " + url.toExternalForm(), e);
        }
        return current;
    }

    public static void doMerge(final URL url, final CompositeBeans current, final Beans beans) {
        current.mergeClasses(url, beans);
        current.getScan().getExclude().addAll(beans.getScan().getExclude());

        // check is done here since later we lost the data of the origin
        ReadDescriptors.checkDuplicatedByBeansXml(beans, current);

        String beanDiscoveryMode = beans.getBeanDiscoveryMode();
        if (beanDiscoveryMode == null) {
            beanDiscoveryMode = "ALL";
        }
        else if ("ALL".equalsIgnoreCase(beanDiscoveryMode) && beans.isTrim()) {
            beanDiscoveryMode = "TRIM";
        }

        current.getDiscoveryByUrl().put(url, beanDiscoveryMode);
    }

    private void addBeansXmls(final AppModule appModule) {
        final List<URL> urls = appModule.getAdditionalLibraries();
        final URLClassLoader loader = new URLClassLoader(urls.toArray(new URL[urls.size()]));

        final ArrayList<URL> xmls;
        try {
            xmls = Collections.list(loader.getResources("META-INF/beans.xml"));
        } catch (final IOException e) {

            return;
        }

        final CompositeBeans complete = new CompositeBeans();
        for (final URL url : xmls) {
            if (url == null) {
                continue;
            }
            mergeBeansXml(complete, url);
        }

        if (complete.getDiscoveryByUrl().isEmpty()) {
            return;
        }
        complete.removeDuplicates();

        ensureContainerUrls();
        final List<URL> scannableUrls = new ArrayList<>(this.containerUrls);
        SystemInstance.get().fireEvent(new EnhanceScannableUrlsEvent(scannableUrls));
        appModule.getScannableContainerUrls().addAll(scannableUrls);

        IAnnotationFinder finder;
        try {
            finder = FinderFactory.createFinder(appModule);
        } catch (final Exception e) {
            finder = new FinderFactory.ModuleLimitedFinder(new FinderFactory.OpenEJBAnnotationFinder(new WebappAggregatedArchive(appModule.getClassLoader(), appModule.getAltDDs(), xmls)));
        }
        appModule.setEarLibFinder(finder);

        final EjbModule ejbModule = new EjbModule(appModule.getClassLoader(), EAR_SCOPED_CDI_BEANS + appModule.getModuleId(), new EjbJar(), new OpenejbJar());
        ejbModule.setBeans(complete);
        ejbModule.setFinder(finder);
        ejbModule.setEjbJar(new EmptyEjbJar());

        appModule.getEjbModules().add(ejbModule);
    }

    protected String getContextRoot() {
        return null;
    }

    protected String getModuleName() {
        return null;
    }

    public static Map<String, URL[]> getWebappUrlsAndRars(final File warFile) {
        final Set<URL> webClassPath = new HashSet<>();
        final Set<URL> webRars = new HashSet<>();
        final File webInfDir = new File(warFile, "WEB-INF");
        try {
            webClassPath.add(new File(webInfDir, "classes").toURI().toURL());
        } catch (final MalformedURLException e) {
            LOGGER.warning("War path bad: " + new File(webInfDir, "classes"), e);
        }

        final File libDir = new File(webInfDir, "lib");
        if (libDir.exists()) {
            final File[] list = libDir.listFiles();
            if (list != null) {
                for (final File file : list) {
                    final String name = file.getName();
                    if (name.endsWith(".jar") || name.endsWith(".zip")) {
                        try {
                            webClassPath.add(file.toURI().toURL());
                        } catch (final MalformedURLException e) {
                            LOGGER.warning("War path bad: " + file, e);
                        }
                    } else if (name.endsWith(".rar")) {
                        try {
                            webRars.add(file.toURI().toURL());
                        } catch (final MalformedURLException e) {
                            LOGGER.warning("War path bad: " + file, e);
                        }
                    }
                }
            }
        }

        final WebAppEnricher enricher = SystemInstance.get().getComponent(WebAppEnricher.class);
        if (enricher != null) {
            webClassPath.addAll(Arrays.asList(enricher.enrichment(null)));
        }

        // create the class loader
        final Map<String, URL[]> urls = new HashMap<>();
        urls.put(URLS_KEY, webClassPath.toArray(new URL[webClassPath.size()]));
        urls.put(RAR_URLS_KEY, webRars.toArray(new URL[webRars.size()]));
        return urls;
    }

    public static URL[] getWebappUrls(final File warFile) {
        return getWebappUrlsAndRars(warFile).get("urls");
    }

    private static void addWebservices(final WsModule wsModule) throws OpenEJBException {
        final boolean webservicesEnabled = SystemInstance.get().getOptions().get(ConfigurationFactory.WEBSERVICES_ENABLED, true);
        if (!webservicesEnabled) {
            wsModule.getAltDDs().remove("webservices.xml");
            wsModule.setWebservices(null); // should be null already, but just for good measure
            return;
        }

        // get location of webservices.xml file
        final Object webservicesObject = wsModule.getAltDDs().get("webservices.xml");
        if (webservicesObject == null || !(webservicesObject instanceof URL)) {
            return;
        }
        final URL webservicesUrl = (URL) webservicesObject;

        // determine the base url for this module (either file: or jar:)
        URL moduleUrl;
        try {
            final File jarFile = new File(wsModule.getJarLocation());
            moduleUrl = jarFile.toURI().toURL();
            if (jarFile.isFile()) {
                moduleUrl = new URL("jar", "", -1, moduleUrl + "!/");
            }
        } catch (final MalformedURLException e) {
            LOGGER.warning("Invalid module location " + wsModule.getJarLocation());
            return;
        }

        // parse the webservices.xml file
        final Map<URL, JavaWsdlMapping> jaxrpcMappingCache = new HashMap<>();
        final Webservices webservices = ReadDescriptors.readWebservices(webservicesUrl);
        wsModule.setWebservices(webservices);
        if ("file".equals(webservicesUrl.getProtocol())) {
            wsModule.getWatchedResources().add(URLs.toFilePath(webservicesUrl));
        }

        // parse any jaxrpc-mapping-files mentioned in the webservices.xml file
        for (final WebserviceDescription webserviceDescription : webservices.getWebserviceDescription()) {
            final String jaxrpcMappingFile = webserviceDescription.getJaxrpcMappingFile();
            if (jaxrpcMappingFile != null) {
                final URL jaxrpcMappingUrl;
                try {
                    jaxrpcMappingUrl = new URL(moduleUrl, jaxrpcMappingFile);
                    JavaWsdlMapping jaxrpcMapping = jaxrpcMappingCache.get(jaxrpcMappingUrl);
                    if (jaxrpcMapping == null) {
                        jaxrpcMapping = ReadDescriptors.readJaxrpcMapping(jaxrpcMappingUrl);
                        jaxrpcMappingCache.put(jaxrpcMappingUrl, jaxrpcMapping);
                    }
                    webserviceDescription.setJaxrpcMapping(jaxrpcMapping);
                    if ("file".equals(jaxrpcMappingUrl.getProtocol())) {
                        wsModule.getWatchedResources().add(URLs.toFilePath(jaxrpcMappingUrl));
                    }
                } catch (final MalformedURLException e) {
                    LOGGER.warning("Invalid jaxrpc-mapping-file location " + jaxrpcMappingFile);
                }
            }
        }

    }

    private void addTagLibraries(final WebModule webModule) throws OpenEJBException {
        final Set<URL> tldLocations = new HashSet<>();

        // web.xml contains tag lib locations in nested jsp config elements
        final File warFile = new File(webModule.getJarLocation());
        final WebApp webApp = webModule.getWebApp();
        if (webApp != null) {
            for (final JspConfig jspConfig : webApp.getJspConfig()) {
                for (final Taglib taglib : jspConfig.getTaglib()) {
                    String location = taglib.getTaglibLocation();
                    if (!location.startsWith("/")) {
                        // this reproduces a tomcat bug
                        location = "/WEB-INF/" + location;
                    }
                    try {
                        final File file = new File(warFile, location).getCanonicalFile().getAbsoluteFile();
                        tldLocations.addAll(TldScanner.scanForTagLibs(file));
                    } catch (final IOException e) {
                        LOGGER.warning("JSP tag library location bad: " + location, e);
                    }
                }
            }
        }

        // WEB-INF/**/*.tld except in WEB-INF/classes and WEB-INF/lib
        Set<URL> urls = TldScanner.scanWarForTagLibs(warFile);
        tldLocations.addAll(urls);

        // Search all libs
        final ClassLoader parentClassLoader = webModule.getClassLoader().getParent();
        urls = TldScanner.scan(parentClassLoader);
        tldLocations.addAll(urls);

        // load the tld files
        for (final URL location : tldLocations) {
            final TldTaglib taglib = ReadDescriptors.readTldTaglib(location);
            if (taglib != null && taglib != ReadDescriptors.SKIP_TAGLIB) {
                webModule.getTaglibs().add(taglib);
                if ("file".equals(location.getProtocol())) {
                    webModule.getWatchedResources().add(URLs.toFilePath(location));
                }
            }
        }

        // no more need + this classloader is a temp one in Servlet container so avoid mem leaks
        TldScanner.quickClean(parentClassLoader);
    }

    /**
     * Finds all faces configuration files and stores them in the WebModule
     *
     * @param webModule WebModule
     * @throws OpenEJBException
     */
    private void addFacesConfigs(final WebModule webModule) throws OpenEJBException {
        //*************************IMPORTANT*******************************************
        // TODO : kmalhi :: Add support to scrape META-INF/faces-config.xml in jar files
        // look at section 10.4.2 of the JSF v1.2 spec, bullet 1 for details
        final Set<URL> facesConfigLocations = new HashSet<>();

        // web.xml contains faces config locations in the context parameter javax.faces.CONFIG_FILES
        final File warFile = new File(webModule.getJarLocation());
        final WebApp webApp = webModule.getWebApp();
        if (webApp != null) {
            final String foundContextParam = webApp.contextParamsAsMap().get("javax.faces.CONFIG_FILES");
            if (foundContextParam != null) {
                // the value is a comma separated list of config files
                final String commaDelimitedListOfFiles = foundContextParam.trim();
                final String[] configFiles = commaDelimitedListOfFiles.split(",");
                // trim any extra spaces in each file
                final String[] trimmedConfigFiles = new String[configFiles.length];
                for (int i = 0; i < configFiles.length; i++) {
                    trimmedConfigFiles[i] = configFiles[i].trim();
                }
                // convert each file to a URL and add it to facesConfigLocations
                for (final String location : trimmedConfigFiles) {
                    if (!location.startsWith("/")) {
                        LOGGER.error("A faces configuration file should be context relative when specified in web.xml. Please fix the value of context parameter javax.faces.CONFIG_FILES for the file " + location);
                    }
                    try {
                        final File file = new File(warFile, location).getCanonicalFile().getAbsoluteFile();
                        final URL url = file.toURI().toURL();
                        facesConfigLocations.add(url);

                    } catch (final IOException e) {
                        LOGGER.error("Faces configuration file location bad: " + location, e);
                    }
                }
            } else {
                LOGGER.debug("faces config file is null");
            }
        }

        // Search for WEB-INF/faces-config.xml
        final File webInf = new File(warFile, "WEB-INF");
        if (webInf.isDirectory()) {
            File facesConfigFile = new File(webInf, "faces-config.xml");
            if (facesConfigFile.exists()) {
                try {
                    facesConfigFile = facesConfigFile.getCanonicalFile().getAbsoluteFile();
                    final URL url = facesConfigFile.toURI().toURL();
                    facesConfigLocations.add(url);
                } catch (final IOException e) {
                    // TODO: kmalhi:: Remove the printStackTrace after testing
                    e.printStackTrace();
                }
            }
        }
        // load the faces configuration files
        // TODO:kmalhi:: Its good to have separate FacesConfig objects for multiple configuration files, but what if there is a conflict where the same
        // managebean is declared in two different files, which one wins? -- check the jsf spec, Hopefully JSF should be able to check for this and
        // flag an error and not allow the application to be deployed.
        for (final URL location : facesConfigLocations) {
            final FacesConfig facesConfig = ReadDescriptors.readFacesConfig(location);
            webModule.getFacesConfigs().add(facesConfig);
            if ("file".equals(location.getProtocol())) {
                webModule.getWatchedResources().add(URLs.toFilePath(location));
            }
        }
    }

    protected static ConnectorModule createConnectorModule(final String appId, final String rarPath, final ClassLoader parentClassLoader, final String moduleId) throws OpenEJBException {
        return createConnectorModule(appId, rarPath, parentClassLoader, moduleId, null);
    }

    protected static ConnectorModule createConnectorModule(final String appId, final String rarPath, final ClassLoader parentClassLoader, final String moduleId, final URL raXmlUrl) throws OpenEJBException {
        final URL baseUrl;// unpack the rar file
        File rarFile = new File(rarPath);
        if (!rarFile.exists()) {
            LOGGER.warning(rarPath + " doesn't exist, skipping connector");
            return null;
        }
        rarFile = unpack(rarFile);
        baseUrl = getFileUrl(rarFile);

        // read the ra.xml file
        final Map<String, URL> descriptors = getDescriptors(baseUrl);
        Connector connector = null;
        URL rarXmlUrl = descriptors.get("ra.xml");
        if (rarXmlUrl == null && raXmlUrl != null) {
            descriptors.put("ra.xml", raXmlUrl);
            rarXmlUrl = raXmlUrl;
        }
        if (rarXmlUrl != null) {
            connector = ReadDescriptors.readConnector(rarXmlUrl);
        }

        // find the nested jar files
        final HashMap<String, URL> rarLibs = new HashMap<>();
        scanDir(rarFile, rarLibs, "");
        // remove all non jars from the rarLibs
        rarLibs.entrySet().removeIf(fileEntry -> !fileEntry.getKey().endsWith(".jar"));

        // create the class loader
        final List<URL> classPath = new ArrayList<>(rarLibs.values());

        final ClassLoaderConfigurer configurer = QuickJarsTxtParser.parse(new File(rarFile, "META-INF/" + QuickJarsTxtParser.FILE_NAME));
        if (configurer != null) {
            ClassLoaderConfigurer.Helper.configure(classPath, configurer);
        }

        final URL[] urls = classPath.toArray(new URL[classPath.size()]);
        final ClassLoader appClassLoader = ClassLoaderUtil.createTempClassLoader(appId, urls, parentClassLoader);

        // create the Resource Module
        final ConnectorModule connectorModule = new ConnectorModule(connector, appClassLoader, rarPath, moduleId);
        connectorModule.getAltDDs().putAll(descriptors);
        connectorModule.getLibraries().addAll(classPath);
        connectorModule.getWatchedResources().add(rarPath);
        connectorModule.getWatchedResources().add(rarFile.getAbsolutePath());
        if (rarXmlUrl != null && "file".equals(rarXmlUrl.getProtocol())) {
            connectorModule.getWatchedResources().add(URLs.toFilePath(rarXmlUrl));
        }

        return connectorModule;
    }

    protected static void addWebFragments(final WebModule webModule, final Collection<URL> urls) throws OpenEJBException {
        if (urls == null) {
            return;
        }

        List<URL> webFragmentUrls;
        try {
            webFragmentUrls = (List<URL>) webModule.getAltDDs().get(WEB_FRAGMENT_XML);
        } catch (final ClassCastException e) {
            final Object value = webModule.getAltDDs().get(WEB_FRAGMENT_XML);
            webFragmentUrls = new ArrayList<>();
            webFragmentUrls.add(URL.class.cast(value));
            webModule.getAltDDs().put(WEB_FRAGMENT_XML, webFragmentUrls);
        }
        if (webFragmentUrls == null) {
            webFragmentUrls = new ArrayList<>();
            webModule.getAltDDs().put(WEB_FRAGMENT_XML, webFragmentUrls);
        }


        for (final URL url : urls) {
            final ResourceFinder finder = new ResourceFinder("", webModule.getClassLoader(), url);
            final Map<String, URL> descriptors = getDescriptors(finder, false);

            if (descriptors.containsKey(WEB_FRAGMENT_XML)) {
                final URL descriptor = descriptors.get(WEB_FRAGMENT_XML);
                if (webFragmentUrls.contains(descriptor)) {
                    continue;
                }

                final String urlString = descriptor.toExternalForm();
                if (!urlString.contains("META-INF/" + WEB_FRAGMENT_XML)) {
                    LOGGER.info("AltDD persistence.xml -> " + urlString);
                }

                webFragmentUrls.add(descriptor);
            }
        }
    }

    @SuppressWarnings({"unchecked"})
    protected static Collection<URL> addPersistenceUnits(final AppModule appModule, final URL... urls) throws OpenEJBException {
        final Collection<URL> added = new ArrayList<>();

        // OPENEJB-1059: Anything in the appModule.getAltDDs() map has already been
        // processed by the altdd code, so anything in here should not cause OPENEJB-1059
        List<URL> persistenceUrls;
        try {
            persistenceUrls = (List<URL>) appModule.getAltDDs().get("persistence.xml");
        } catch (final ClassCastException e) {
            //That happens when we are trying to deploy an ear file.
            //lets try to get a single object instead
            final Object value = appModule.getAltDDs().get("persistence.xml");

            persistenceUrls = new ArrayList<>();
            persistenceUrls.add(URL.class.cast(value));
            added.add(persistenceUrls.iterator().next());

            appModule.getAltDDs().put("persistence.xml", persistenceUrls);
        }
        if (persistenceUrls == null) {
            persistenceUrls = new ArrayList<>();
            appModule.getAltDDs().put("persistence.xml", persistenceUrls);
        }

        List<URL> persistenceFragmentsUrls = (List<URL>) appModule.getAltDDs().get("persistence-fragment.xml");
        if (persistenceFragmentsUrls == null) {
            persistenceFragmentsUrls = new ArrayList<>();
            appModule.getAltDDs().put("persistence-fragment.xml", persistenceFragmentsUrls);
        }


        for (final URL url : urls) {
            // OPENEJB-1059: looking for an altdd persistence.xml file in all urls
            // delegates to xbean finder for going throughout the list
            final ResourceFinder finder = new ResourceFinder("", appModule.getClassLoader(), url);
            final Map<String, URL> descriptors = getDescriptors(finder, false);

            // if a persistence.xml has been found, just pull it to the list
            if (descriptors.containsKey("persistence.xml")) {
                final URL descriptor = descriptors.get("persistence.xml");

                // don't add it if already present
                if (persistenceUrls.contains(descriptor)) {
                    continue;
                }

                // log if it is an altdd
                final String urlString = descriptor.toExternalForm();
                if (!urlString.contains("META-INF/persistence.xml")) {
                    LOGGER.info("AltDD persistence.xml -> " + urlString);
                }

                persistenceUrls.add(descriptor);
                added.add(descriptor);
            }
        }

        // look for persistence-fragment.xml
        for (final URL url : urls) {
            // OPENEJB-1059: looking for an altdd persistence.xml file in all urls
            // delegates to xbean finder for going throughout the list
            final ResourceFinder finder = new ResourceFinder("", appModule.getClassLoader(), url);
            final Map<String, URL> descriptors = getDescriptors(finder, false);

            // if a persistence.xml has been found, just pull it to the list
            if (descriptors.containsKey("persistence-fragment.xml")) {
                final URL descriptor = descriptors.get("persistence-fragment.xml");

                if (persistenceFragmentsUrls.contains(descriptor)) {
                    continue;
                }

                // log if it is an altdd
                final String urlString = descriptor.toExternalForm();
                if (!urlString.contains("META-INF/persistence-fragment.xml")) {
                    LOGGER.info("AltDD persistence-fragment.xml -> " + urlString);
                }

                persistenceFragmentsUrls.add(descriptor);
                added.add(descriptor);
            }
        }

        return added;
    }

    public static Map<String, URL> getDescriptors(final URL moduleUrl) throws OpenEJBException {

        final ResourceFinder finder = new ResourceFinder(moduleUrl);
        return getDescriptors(finder);
    }

    private static Map<String, URL> getDescriptors(final ResourceFinder finder) throws OpenEJBException {
        return getDescriptors(finder, true);
    }

    private static Map<String, URL> getDescriptors(final ResourceFinder finder, final boolean log) throws OpenEJBException {
        try {

            return altDDSources(mapDescriptors(finder), log);

        } catch (final IOException e) {
            throw new OpenEJBException("Unable to determine descriptors in jar.", e);
        }
    }

    public static Map<String, URL> mapDescriptors(final ResourceFinder finder)
        throws IOException {
        final Map<String, URL> map = finder.getResourcesMap(META_INF);

        if (map.size() == 0) {

            for (final String descriptor : KNOWN_DESCRIPTORS) {

                final URL url = finder.getResource(META_INF + descriptor);
                if (url != null) {
                    map.put(descriptor, url);
                }
            }

        }
        return map;
    }

    /**
     * Modifies the map passed in with all the alt dd URLs found
     *
     * @param map Map
     * @param log boolean
     * @return the same map instance updated with alt dds
     */
    public static Map<String, URL> altDDSources(final Map<String, URL> map, final boolean log) {
        if (ALTDD == null || ALTDD.length() <= 0) {
            return map;
        }

        final List<String> list = new ArrayList<>(Arrays.asList(ALTDD.split(",")));
        Collections.reverse(list);

        final Map<String, URL> alts = new HashMap<>();

        for (String prefix : list) {
            prefix = prefix.trim();
            if (!prefix.matches(".*[.-]$")) {
                prefix += ".";
            }

            for (final Map.Entry<String, URL> entry : new HashMap<>(map).entrySet()) {
                String key = entry.getKey();
                final URL value = entry.getValue();
                if (key.startsWith(prefix)) {
                    key = key.substring(prefix.length());

                    alts.put(key, value);
                }
            }
        }

        for (final Map.Entry<String, URL> alt : alts.entrySet()) {
            final String key = alt.getKey();
            final URL value = alt.getValue();

            // don't add and log if the same key/value is already in the map
            if (value.equals(map.get(key))) {
                continue;
            }

            if (log) {
                LOGGER.info("AltDD " + key + " -> " + value.toExternalForm());
            }
            map.put(key, value);
        }

        return map;
    }

    public static Map<String, URL> getWebDescriptors(final File warFile) throws IOException {
        final Map<String, URL> descriptors = new TreeMap<>();

        // xbean resource finder has a bug when you use any uri but "META-INF"
        // and the jar file does not contain a directory entry for the uri

        if (warFile.isFile()) { // only to discover module type so xml file filtering is enough
            final URL jarURL = new URL("jar", "", -1, warFile.toURI().toURL() + "!/");
            try (JarFile jarFile = new JarFile(warFile)) {
                for (final JarEntry entry : Collections.list(jarFile.entries())) {
                    final String entryName = entry.getName();
                    if (!entry.isDirectory() && entryName.startsWith("WEB-INF/")
                        && (KNOWN_DESCRIPTORS.contains(entryName.substring("WEB-INF/".length())) || entryName.endsWith(".xml"))) { // + web.xml, web-fragment.xml...
                        descriptors.put(entryName, new URL(jarURL, entry.getName()));
                    }
                }
            } catch (final IOException e) {
                // most likely an invalid jar file
            }
        } else if (warFile.isDirectory()) {
            final File webInfDir = new File(warFile, "WEB-INF");
            if (webInfDir.isDirectory()) {
                final File[] files = webInfDir.listFiles();
                if (files != null) {
                    for (final File file : files) {
                        if (!file.isDirectory()) {
                            descriptors.put(file.getName(), file.toURI().toURL());
                        }
                    }
                }
            }

            // handle some few file(s) which can be in META-INF too
            final File webAppDdDir = new File(webInfDir, "classes/" + META_INF);
            if (webAppDdDir.isDirectory()) {
                final File[] files = webAppDdDir.listFiles();
                if (files != null) {
                    for (final File file : files) {
                        final String name = file.getName();
                        if (!descriptors.containsKey(name)) {
                            descriptors.put(name, file.toURI().toURL());
                        } else {
                            LOGGER.warning("Can't have a " + name + " in WEB-INF and WEB-INF/classes/META-INF, second will be ignored");
                        }
                    }
                }
            }
        }

        return descriptors;
    }

    protected File getFile(final URL warUrl) {
        if ("jar".equals(warUrl.getProtocol())) {
            String pathname = warUrl.getPath();

            // we only support file based jar urls
            if (!pathname.startsWith("file:")) {
                return null;
            }

            // strip off "file:"
            pathname = pathname.substring("file:".length());

            // file path has trailing !/ that must be stripped off
            pathname = pathname.substring(0, pathname.lastIndexOf('!'));

            try {
                pathname = URLDecoder.decode(pathname, "UTF-8");
            } catch (final Exception e) {
                //noinspection deprecation
                pathname = URLDecoder.decode(pathname);
            }
            return new File(pathname);
        } else if ("file".equals(warUrl.getProtocol())) {
            final String pathname = warUrl.getPath();
            try {
                return new File(URLDecoder.decode(pathname, "UTF-8"));
            } catch (final UnsupportedEncodingException e) {
                //noinspection deprecation
                return new File(URLDecoder.decode(pathname));
            }
        } else {
            return null;
        }
    }

    @SuppressWarnings({"unchecked"})
    public static Application unmarshal(final URL url) throws OpenEJBException {
        try {
            return ApplicationXml.unmarshal(url);
        } catch (final Exception e) {
            throw new OpenEJBException("Encountered error parsing the application.xml file: " + url.toExternalForm(), e);
        }
    }

    public static void scanDir(final File dir, final Map<String, URL> files, final String path) {
        scanDir(dir, files, path, true);
    }

    public static void scanDir(final File dir, final Map<String, URL> files, final String path, final boolean recursive) {
        final File[] dirFiles = dir.listFiles();
        if (dirFiles != null) {
            for (final File file : dirFiles) {
                if (file.isDirectory()) {
                    if (DeploymentsResolver.isExtractedDir(file)) {
                        continue;
                    }

                    if (recursive) {
                        scanDir(file, files, path + file.getName() + "/");
                    }
                } else {
                    final String name = file.getName();
                    try {
                        files.put(path + name, file.toURI().toURL());
                    } catch (final MalformedURLException e) {
                        LOGGER.warning("EAR path bad: " + path + name, e);
                    }
                }
            }
        }
    }

    public Class<? extends DeploymentModule> discoverModuleType(final URL baseUrl, final ClassLoader classLoader, final boolean searchForDescriptorlessApplications) throws IOException, UnknownModuleTypeException {
        final Set<RequireDescriptors> search = EnumSet.noneOf(RequireDescriptors.class);

        if (!searchForDescriptorlessApplications) {
            search.addAll(Arrays.asList(RequireDescriptors.values()));
        }

        return discoverModuleType(baseUrl, classLoader, search);
    }

    @SuppressWarnings("unchecked")
    public Class<? extends DeploymentModule> discoverModuleType(final URL baseUrl, final ClassLoader classLoader, final Set<RequireDescriptors> requireDescriptor) throws IOException, UnknownModuleTypeException {
        final boolean scanPotentialEjbModules = !requireDescriptor.contains(RequireDescriptors.EJB);
        final boolean scanPotentialClientModules = !requireDescriptor.contains(RequireDescriptors.CLIENT);


        URL pathToScanDescriptors = baseUrl;
        String path;
        if (baseUrl != null) {
            path = URLs.toFile(baseUrl).getAbsolutePath();
            if (baseUrl.getProtocol().equals("file") && path.endsWith("WEB-INF/classes/")) {
                //EJB found in WAR/WEB-INF/classes, scan WAR for ejb-jar.xml
                pathToScanDescriptors = new URL(path.substring(0, path.lastIndexOf("WEB-INF/classes/")));
            }
        } else {
            path = "";
        }

        final Map<String, URL> descriptors = getDescriptors(classLoader, pathToScanDescriptors);

        if (path.endsWith("/")) {
            path = path.substring(0, path.length() - 1);
        }

        if (path.endsWith(".xml") || path.endsWith(".json")) { // let say it is a resource module
            return ResourcesModule.class;
        }

        if (descriptors.containsKey("application.xml") || path.endsWith(".ear")) {
            return AppModule.class;
        }

        if (descriptors.containsKey("ra.xml") || path.endsWith(".rar")) {
            return ConnectorModule.class;
        }

        if (baseUrl != null) {
            final Map<String, URL> webDescriptors = getWebDescriptors(getFile(baseUrl));
            if (webDescriptors.containsKey("web.xml") || webDescriptors.containsKey(WEB_FRAGMENT_XML) // descriptor
                || path.endsWith(".war") || new File(path, "WEB-INF").exists()) { // webapp specific files
                return WebModule.class;
            }
        }

        if (descriptors.containsKey("ejb-jar.xml") || descriptors.containsKey("beans.xml")) {
            return EjbModule.class;
        }

        if (descriptors.containsKey("application-client.xml")) {
            return ClientModule.class;
        }

        final URL manifestUrl = descriptors.get("MANIFEST.MF");
        if (scanPotentialClientModules && manifestUrl != null) {
            // In this case scanPotentialClientModules really means "require application-client.xml"
            final InputStream is = new BufferedInputStream(manifestUrl.openStream());
            final Manifest manifest = new Manifest(is);
            final String mainClass = manifest.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
            if (mainClass != null) {
                return ClientModule.class;
            }
        }

        final Class<? extends DeploymentModule> cls = checkAnnotations(baseUrl, classLoader, scanPotentialEjbModules, scanPotentialClientModules);
        if (cls != null) {
            return cls;
        }

        if (descriptors.containsKey("persistence.xml") || descriptors.containsKey("persistence-fragment.xml")) {
            return PersistenceModule.class;
        }

        //#TOMEE-613
        final File file = URLs.toFile(baseUrl);
        if (DeploymentsResolver.isValidDirectory(file)) {

            final File[] files = file.listFiles();
            if (containsEarAssets(files)) {
                return AppModule.class;
            }
            if (containsWebAssets(files)) {
                return WebModule.class;
            }
        }

        final Class<? extends DeploymentModule> defaultType = (Class<? extends DeploymentModule>) SystemInstance.get().getOptions().get("openejb.default.deployment-module", (Class<?>) null);
        if (defaultType != null) {
            // should we do a better filtering? it seems enough for common cases.
            if (WebModule.class.equals(defaultType) && (path.endsWith(".jar!") || path.endsWith(".jar"))) {
                throw new UnknownModuleTypeException("Unknown module type: url=" + path + " which can't be a war.");
            }

            LOGGER.debug("type for '" + path + "' was not found, defaulting to " + defaultType.getSimpleName());
            return defaultType;
        }
        throw new UnknownModuleTypeException("Unknown module type: url=" + path); // baseUrl can be null
    }

    private static boolean containsWebAssets(final File[] files) {
        if (files != null) {
            for (final File file : files) {
                final String fn = file.getName().toLowerCase(Locale.ENGLISH);
                if (fn.endsWith(".jsp")) {
                    return true;
                }
                if (fn.endsWith(".html")) {
                    return true;
                }
            }
        }
        return false;
    }

    private static boolean containsEarAssets(final File[] files) {
        if (files != null) {
            for (final File file : files) {
                final String fn = file.getName().toLowerCase(Locale.ENGLISH);
                if (fn.endsWith(".jar")) {
                    return true;
                }
                if (fn.endsWith(".war")) {
                    return true;
                }
                if (fn.endsWith(".rar")) {
                    return true;
                }
            }
        }
        return false;
    }


    private Map<String, URL> getDescriptors(final ClassLoader classLoader, final URL pathToScanDescriptors)
        throws IOException {
        final ResourceFinder finder = new ResourceFinder("", classLoader, pathToScanDescriptors);

        return altDDSources(mapDescriptors(finder), false);
    }

    private Class<? extends DeploymentModule> checkAnnotations(final URL urls, final ClassLoader classLoader, final boolean scanPotentialEjbModules, final boolean scanPotentialClientModules) {
        Class<? extends DeploymentModule> cls = null;
        if (scanPotentialEjbModules || scanPotentialClientModules) {
            final AnnotationFinder classFinder = new AnnotationFinder(classLoader, urls);

            final Set<Class<? extends DeploymentModule>> otherTypes = new LinkedHashSet<>();

            final AnnotationFinder.Filter filter = new AnnotationFinder.Filter() {
                final String packageName = LocalClient.class.getName().replace("LocalClient", "");

                @Override
                public boolean accept(final String annotationName) {
                    if (scanPotentialClientModules && annotationName.startsWith(packageName)) {
                        if (LocalClient.class.getName().equals(annotationName)) {
                            otherTypes.add(ClientModule.class);
                        }
                        if (RemoteClient.class.getName().equals(annotationName)) {
                            otherTypes.add(ClientModule.class);
                        }
                    } else if (scanPotentialEjbModules) {
                        if (annotationName.startsWith("javax.ejb.")) {
                            if ("javax.ejb.Stateful".equals(annotationName)) {
                                return true;
                            }
                            if ("javax.ejb.Stateless".equals(annotationName)) {
                                return true;
                            }
                            if ("javax.ejb.Singleton".equals(annotationName)) {
                                return true;
                            }
                            if ("javax.ejb.MessageDriven".equals(annotationName)) {
                                return true;
                            }
                        } else if (scanManagedBeans && "javax.annotation.ManagedBean".equals(annotationName)) {
                            return true;
                        }
                    }
                    return false;
                }
            };

            if (classFinder.find(filter)) {
                cls = EjbModule.class;
                // if it is a war just throw an error
                try {
                    if(LOGGER.isWarningEnabled()) {
                        final File ar = URLs.toFile(urls);
                        if (!ar.isDirectory() && !ar.getName().endsWith("ar")) { // guess no archive extension, check it is not a hidden war
                            try (JarFile war = new JarFile(ar)) {
                                final ZipEntry entry = war.getEntry("WEB-INF/");
                                if (entry != null) {
                                    LOGGER.warning("you deployed " + urls.toExternalForm() + ", it seems it is a war with no extension, please rename it");
                                }
                            }
                        }
                    }
                } catch (final Exception ignored) {
                    // no-op
                }
            }

            if (otherTypes.size() > 0) {
                // We may want some ordering/sorting if we add more type scanning
                cls = otherTypes.iterator().next();
            }
        }
        return cls;
    }

    public static File unpack(final File jarFile) throws OpenEJBException {
        if (jarFile.isDirectory() || jarFile.getName().endsWith(".jar")) {
            return jarFile;
        }

        String name = jarFile.getName();
        if (name.endsWith(".ear") || name.endsWith(".zip") || name.endsWith(".war") || name.endsWith(".rar")) {
            name = name.replaceFirst("....$", "");
        } else {
            name += ".unpacked";
        }

        try {
            return JarExtractor.extract(jarFile, name);
        } catch (final Throwable e) {
            throw new OpenEJBException("Unable to extract jar. " + e.getMessage(), e);
        }
    }

    protected static URL getFileUrl(final File jarFile) throws OpenEJBException {
        final URL baseUrl;
        try {
            baseUrl = jarFile.toURI().toURL();
        } catch (final MalformedURLException e) {
            throw new OpenEJBException("Malformed URL to app. " + e.getMessage(), e);
        }
        return baseUrl;
    }

    public static void reloadAltDD() {
        ALTDD = SystemInstance.get().getOptions().get(OPENEJB_ALTDD_PREFIX, (String) null);
    }

    public static class ExternalConfiguration {
        private final String[] classpath;
        private final Filter customerFilter;

        public ExternalConfiguration(final String[] classpath, final Filter customerFilter) {
            this.classpath = classpath;
            this.customerFilter = customerFilter;
        }

        public Filter getCustomerFilter() {
            return customerFilter;
        }

        public String[] getClasspath() {
            return classpath;
        }
    }
}
