/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.openejb.config;

import org.apache.openejb.config.sys.Deployments;
import org.apache.openejb.loader.FileUtils;
import org.apache.openejb.loader.Files;
import org.apache.openejb.loader.Options;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.util.Logger;
import org.apache.openejb.util.URLs;
import org.apache.xbean.finder.UrlSet;
import org.apache.xbean.finder.filter.ExcludeIncludeFilter;
import org.apache.xbean.finder.filter.Filter;
import org.apache.xbean.finder.filter.Filters;
import org.apache.xbean.finder.filter.IncludeExcludeFilter;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.apache.openejb.util.URLs.toFile;
import static org.apache.openejb.util.URLs.toFileUrl;

/**
 * @version $Rev: 1417504 $ $Date: 2012-12-05 16:18:01 +0000 (Wed, 05 Dec 2012) $
 */
public class DeploymentsResolver implements DeploymentFilterable {

    private static final String EXCLUDE_INCLUDE_ORDER = SystemInstance.get().getOptions().get("openejb.exclude-include.order", "include-exclude");
    private static final String[] ignoreDirs = SystemInstance.get().getProperty("openejb.ignore.directories", ".svn,_svn,cvs,.git,.hg").split(",");
    private static final Logger logger = DeploymentLoader.logger;
    private static File lib = null;

    static {
        try {
            lib = SystemInstance.get().getHome().getDirectory("lib", false);
        } catch (IOException e) {
            //Ignore
        }
    }

    protected static boolean isValidDirectory(final File file) {

        if (file.isDirectory() && !file.isHidden() && !file.equals(lib)) {

            final String fn = file.getName();

            for (final String dir : ignoreDirs) {
                if (fn.equalsIgnoreCase(dir)) {
                    return false;
                }
            }

            final String[] files = file.list();

            return (null != files && files.length > 0);
        }

        return false;
    }

    public static void loadFrom(final Deployments dep, final FileUtils path, final List<File> jarList) {

        if (dep.getDir() != null) {

            try {

                loadFromDir(dep, path, jarList);

            } catch (Files.FileDoesNotExistException e) {
                logger.warning("<Deployments dir=\"" + dep.getFile() + "\"> - " + e.getMessage());

            } catch (RuntimeException e) {
                final String message = "<Deployments dir=\"" + dep.getFile() + "\"> - " + e.getMessage();

                logger.error(message);
                throw new DeploymentsConfigurationException(message);
            }

        } else if (dep.getFile() != null) {

            try {

                loadFromFile(dep, path, jarList);

            } catch (RuntimeException e) {
                final String message = "<Deployments file=\"" + dep.getFile() + "\"> - " + e.getMessage();
                logger.error(message);
                throw new DeploymentsConfigurationException(message);
            }

        }
    }

    public static class DeploymentsConfigurationException extends RuntimeException {
        public DeploymentsConfigurationException(final String message) {
            super(message);
        }
    }

    private static void loadFromFile(final Deployments dep, final FileUtils path, final List<File> jarList) {
        final File file = Files.path(path.getDirectory(), dep.getFile());

        Files.exists(file);
        Files.readable(file);
        Files.file(file);

        if (!jarList.contains(file)) {
            jarList.add(file);
        }
    }

    private static void loadFromDir(final Deployments dep, final FileUtils path, final List<File> jarList) {
        final File dir = Files.path(path.getDirectory(), dep.getDir());

        Files.exists(dir);
        Files.readable(dir);
        Files.dir(dir);
        Files.notHidden(dir);

        final Map<String, File> files = new LinkedHashMap<String, java.io.File>();
        final File[] list = dir.listFiles(new FileFilter() {
            @Override
            public boolean accept(final File f) {
                if (f.isDirectory()) {
                    return DeploymentsResolver.isValidDirectory(f);
                }
                return true;
            }
        });

        if (list != null) {
            for (final File file : list) {

                files.put(file.getAbsolutePath(), file);
            }

            // Ignore any unpacked versions
            for (final File file : list) {
                if (!isArchive(file)) continue;
                final String archive = file.getAbsolutePath();
                files.remove(archive.substring(0, archive.length() - 4));
            }
        }

        for (final File file : files.values()) {
            if (!jarList.contains(file)) {
                jarList.add(file);
            }
        }
    }

    private static boolean isArchive(final File file) {
        if (!file.isFile()) return false;
        if (!file.getName().toLowerCase().endsWith("ar")) return false;

        final String name = file.getName();
        final char c = name.charAt(name.length() - 4);
        return c == '.';
    }

    /**
     * The algorithm of OpenEJB deployments class-path inclusion and exclusion is implemented as follows:
     * 1- If the string value of the resource URL matches the include class-path pattern
     * Then load this resource
     * 2- If the string value of the resource URL matches the exclude class-path pattern
     * Then ignore this resource
     * 3- If the include and exclude class-path patterns are not defined
     * Then load this resource
     * <p/>
     * The previous steps are based on the following points:
     * 1- Include class-path pattern has the highest priority
     * This helps in case both patterns are defined using the same values.
     * This appears in step 1 and 2 of the above algorithm.
     * 2- Loading the resource is the default behaviour in case of not defining a value for any class-path pattern
     * This appears in step 3 of the above algorithm.
     */
    public static void loadFromClasspath(final FileUtils base, final List<URL> jarList, final ClassLoader classLoader) {
        final Options options = SystemInstance.get().getOptions();
        final String include = options.get(CLASSPATH_INCLUDE, ".*");
        final String exclude = options.get(CLASSPATH_EXCLUDE, "");
        final Set<RequireDescriptors> requireDescriptors = options.getAll(CLASSPATH_REQUIRE_DESCRIPTOR, RequireDescriptors.CLIENT);
        final boolean filterDescriptors = options.get(CLASSPATH_FILTER_DESCRIPTORS, false);
        final boolean filterSystemApps = options.get(CLASSPATH_FILTER_SYSTEMAPPS, true);

        try {
            UrlSet urlSet = new UrlSet(classLoader);

            urlSet = URLs.cullSystemJars(urlSet);

            // save the prefiltered list of jars before excluding system apps
            // so that we can choose not to filter modules with descriptors on the full list
            final UrlSet prefiltered = urlSet;

            Filter includeFilter = Filters.patterns(include);

            // we should exclude system apps before and apply user properties after
            if (!".*".equals(include) || !"".equals(exclude)) { // if we are using default this will not do anything
                // the next line should probably replaced by:
                // final Filter filter = new ExcludeIncludeFilter(includeFilter, Filters.patterns(exclude));
                final Filter filter;
                if (EXCLUDE_INCLUDE_ORDER.startsWith("include")) { // this test should be simply enough
                    filter = new IncludeExcludeFilter(includeFilter, Filters.patterns(exclude));
                } else {
                    filter = new ExcludeIncludeFilter(includeFilter, Filters.patterns(exclude));
                }

                // filter using user parameters
                urlSet = urlSet.filter(filter);
            } else {
                includeFilter = null;
            }

            if (prefiltered.size() == urlSet.size()) {
                urlSet = NewLoaderLogic.applyBuiltinExcludes(urlSet, includeFilter);

                if (filterSystemApps) {
                    urlSet = urlSet.exclude(".*/openejb-[^/]+(.(jar|ear|war)(!/)?|/target/(test-)?classes/?)");
                }
            }

            final List<URL> urls = new ArrayList<URL>();
            final boolean isWindows = System.getProperty("os.name", "unknown").toLowerCase().startsWith("windows");

            for (final URL url : urlSet.getUrls()) {
                final String ef = (isWindows ? url.toExternalForm().toLowerCase() : url.toExternalForm());
                final URL u = new URL(ef);
                if (!urls.contains(u)) {
                    urls.add(u);
                }
            }

            final int size = urls.size();
            if (size == 0 && include.length() > 0) {
                logger.warning("No classpath URLs matched.  Current settings: " + CLASSPATH_EXCLUDE + "='" + exclude + "', " + CLASSPATH_INCLUDE + "='" + include + "'");
                return;
            } else if (size == 0 && (!filterDescriptors && prefiltered.getUrls().size() == 0)) {
                return;
            } else if (size < 20) {
                logger.debug("Inspecting classpath for applications: " + urls.size() + " urls.");
            } else {
                // Has the user allowed some module types to be discoverable via scraping?
                final boolean willScrape = requireDescriptors.size() < RequireDescriptors.values().length;

                if (size < 50 && willScrape) {
                    logger.info("Inspecting classpath for applications: " + urls.size() + " urls. Consider adjusting your exclude/include.  Current settings: " + CLASSPATH_EXCLUDE + "='" + exclude + "', " + CLASSPATH_INCLUDE + "='" + include + "'");
                } else if (willScrape) {
                    logger.warning("Inspecting classpath for applications: " + urls.size() + " urls.");
                    logger.warning("ADJUST THE EXCLUDE/INCLUDE!!!.  Current settings: " + CLASSPATH_EXCLUDE + "='" + exclude + "', " + CLASSPATH_INCLUDE + "='" + include + "'");
                }
            }

            final long begin = System.currentTimeMillis();
            processUrls(urls, classLoader, requireDescriptors, base, jarList);
            final long end = System.currentTimeMillis();
            final long time = end - begin;

            UrlSet unchecked = new UrlSet();
            if (!filterDescriptors) {
                unchecked = NewLoaderLogic.applyBuiltinExcludes(prefiltered.exclude(urlSet));
                if (filterSystemApps) {
                    unchecked = unchecked.exclude(".*/openejb-[^/]+(.(jar|ear|war)(./)?|/target/classes/?)");
                }
                processUrls(unchecked.getUrls(), classLoader, EnumSet.allOf(RequireDescriptors.class), base, jarList);
            }

            if (logger.isDebugEnabled()) {
                final int urlCount = urlSet.getUrls().size() + unchecked.getUrls().size();
                logger.debug("URLs after filtering: " + urlCount);
                for (final URL url : urlSet.getUrls()) {
                    logger.debug("Annotations path: " + url);
                }
                for (final URL url : unchecked.getUrls()) {
                    logger.debug("Descriptors path: " + url);
                }
            }

            if (urls.size() == 0) return;

            if (time < 1000) {
                logger.debug("Searched " + urls.size() + " classpath urls in " + time + " milliseconds.  Average " + (time / urls.size()) + " milliseconds per url.");
            } else if (time < 4000 || urls.size() < 3) {
                logger.info("Searched " + urls.size() + " classpath urls in " + time + " milliseconds.  Average " + (time / urls.size()) + " milliseconds per url.");
            } else if (time < 10000) {
                logger.warning("Searched " + urls.size() + " classpath urls in " + time + " milliseconds.  Average " + (time / urls.size()) + " milliseconds per url.");
                logger.warning("Consider adjusting your " + CLASSPATH_EXCLUDE + " and " + CLASSPATH_INCLUDE + " settings.  Current settings: exclude='" + exclude + "', include='" + include + "'");
            } else {
                logger.fatal("Searched " + urls.size() + " classpath urls in " + time + " milliseconds.  Average " + (time / urls.size()) + " milliseconds per url.  TOO LONG!");
                logger.fatal("ADJUST THE EXCLUDE/INCLUDE!!!.  Current settings: " + CLASSPATH_EXCLUDE + "='" + exclude + "', " + CLASSPATH_INCLUDE + "='" + include + "'");
                final List<String> list = new ArrayList<String>();
                for (final URL url : urls) {
                    list.add(url.toExternalForm());
                }
                Collections.sort(list);
                for (final String url : list) {
                    logger.info("Matched: " + url);
                }
            }
        } catch (IOException e1) {
            e1.printStackTrace();
            logger.warning("Unable to search classpath for modules: Received Exception: " + e1.getClass().getName() + " " + e1.getMessage(), e1);
        }

    }

    public static void processUrls(final List<URL> urls, final ClassLoader classLoader, final Set<RequireDescriptors> requireDescriptors, final FileUtils base, final List<URL> jarList) {
        for (final URL url : urls) {

            final String urlProtocol = url.getProtocol();
            //Currently, we only support jar and file protocol
            final boolean isValidURL = urlProtocol.equals("jar") || urlProtocol.equals("file");
            if (!isValidURL) {
                logger.warning("Unknown protocol " + urlProtocol);
                continue;
            }

            try {

                final DeploymentLoader deploymentLoader = new DeploymentLoader();

                final Class<? extends DeploymentModule> moduleType = deploymentLoader.discoverModuleType(url, classLoader, requireDescriptors);
                if (AppModule.class.isAssignableFrom(moduleType) || EjbModule.class.isAssignableFrom(moduleType) || PersistenceModule.class.isAssignableFrom(moduleType) || ConnectorModule.class.isAssignableFrom(moduleType) || ClientModule.class.isAssignableFrom(moduleType)) {

                    final URL archive = toFileUrl(url);

                    if (!jarList.contains(archive)) {
                        jarList.add(archive);
                        final File file = toFile(archive);
                        logger.info("Found " + moduleType.getSimpleName() + " in classpath: " + file.getAbsolutePath());
                    }
                }
            } catch (IOException e) {
                logger.warning("Unable to determine the module type of " + url.toExternalForm() + ": Exception: " + e.getMessage(), e);
            } catch (UnknownModuleTypeException ignore) {
            }
        }
    }
}
