/*
 * 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.axis2.deployment;

import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.deployment.repository.util.ArchiveReader;
import org.apache.axis2.deployment.repository.util.DeploymentFileData;
import org.apache.axis2.deployment.repository.util.WSInfo;
import org.apache.axis2.deployment.scheduler.DeploymentIterator;
import org.apache.axis2.deployment.scheduler.Scheduler;
import org.apache.axis2.deployment.scheduler.SchedulerTask;
import org.apache.axis2.deployment.util.Utils;
import org.apache.axis2.description.AxisModule;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.AxisServiceGroup;
import org.apache.axis2.description.Flow;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.util.FaultyServiceData;
import org.apache.axis2.util.JavaUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public abstract class DeploymentEngine implements DeploymentConstants {
    private static final Log log = LogFactory.getLog(DeploymentEngine.class);

    /**
     * Indicates that the deployment task is running
     */
    public static final String  DEPLOYMENT_TASK_RUNNING = "deployment.task.running";

    private static final String MODULE_DEPLOYER = "moduleDeployer";

    //to keep the web resource location if any
    protected static String webLocationString = null;
    protected Scheduler scheduler;
    private SchedulerTask schedulerTask;

    public static void setWebLocationString(String webLocationString) {
        DeploymentEngine.webLocationString = webLocationString;
    }


    /**
     * Support for hot update is controlled by this flag
     */
    protected boolean hotUpdate = true;

    /**
     * Support for hot deployment is controlled by this flag
     */
    protected boolean hotDeployment = true;

    /**
     * Stores all the web Services to deploy.
     */
    protected List<DeploymentFileData> wsToDeploy = new ArrayList<DeploymentFileData>();

    /**
     * Stores all the web Services to undeploy.
     */
    protected List<WSInfo> wsToUnDeploy = new ArrayList<WSInfo>();

    /**
     * to keep a ref to engine register
     * this ref will pass to engine when it call start()
     * method
     */
    protected AxisConfiguration axisConfig;

    protected ConfigurationContext configContext;

    protected RepositoryListener repoListener;

    protected String servicesPath = null;
    protected File servicesDir = null;
    protected String modulesPath = null;
    protected File modulesDir = null;
    private File repositoryDir = null;

    //to deploy service (both aar and expanded)
    protected ServiceDeployer serviceDeployer;
    //To deploy modules (both mar and expanded)
    protected ModuleDeployer moduleDeployer;

    private Map<String, Map<String, Deployer>> deployerMap = new HashMap<String, Map<String, Deployer>>();

    private Lock lock = new ReentrantLock();

    public void loadServices() {
        repoListener.checkServices();
        if (hotDeployment) {
            startSearch(repoListener);
        }
    }

    public void loadRepository(String repoDir) throws DeploymentException {
        File axisRepo = new File(repoDir);
        if (!axisRepo.exists()) {
            throw new DeploymentException(
                    Messages.getMessage("cannotfindrepo", repoDir));
        }
        setDeploymentFeatures();
        prepareRepository(repoDir);
        // setting the CLs
        setClassLoaders(repoDir);
        repoListener = new RepositoryListener(this, false);
        org.apache.axis2.util.Utils
                .calculateDefaultModuleVersion(axisConfig.getModules(), axisConfig);
        try {
            try {
                axisConfig.setRepository(axisRepo.toURI().toURL());
            } catch (MalformedURLException e) {
                log.info(e.getMessage());
            }
            axisConfig.validateSystemPredefinedPhases();
        } catch (AxisFault axisFault) {
            throw new DeploymentException(axisFault);
        }
    }

    public void loadFromClassPath() throws DeploymentException {
        //loading modules from the classpath
        new RepositoryListener(this, true);
        org.apache.axis2.util.Utils.calculateDefaultModuleVersion(
                axisConfig.getModules(), axisConfig);
        axisConfig.validateSystemPredefinedPhases();
        try {
            engageModules();
        } catch (AxisFault axisFault) {
            log.info(Messages.getMessage(DeploymentErrorMsgs.MODULE_VALIDATION_FAILED,
                    axisFault.getMessage()));
            throw new DeploymentException(axisFault);
        }
    }

    private void loadCustomServices(URL repoURL) {
        for (Map.Entry<String, Map<String, Deployer>> entry : getDeployers().entrySet()) {
            String directory = entry.getKey();
            Map<String, Deployer> extensionMap = entry.getValue();
            try {
                String listName;
                if (!directory.endsWith("/")) {
                    listName = directory + ".list";
                    directory += "/";
                } else {
                    listName = directory.replaceAll("/", "") + ".list";
                }
                String repoPath = repoURL.getPath();
                if (!repoPath.endsWith("/")) {
                    repoPath += "/";
                    repoURL = new URL(repoURL.getProtocol() + "://" + repoPath);
                }

                URL servicesDir = new URL(repoURL, directory);
                URL filelisturl = new URL(servicesDir, listName);
                List<String> files = getFileList(filelisturl);
                for (Object file : files) {
                    String fileName = (String) file;
                    String extension = getExtension(fileName);
                    Deployer deployer = extensionMap.get(extension);
                    if (deployer == null) {
                        continue;
                    }
                    URL servicesURL = new URL(servicesDir, fileName);

                    // We are calling reflection code here , to avoid changes to the interface
                    Class<?> classToLoad = deployer.getClass();
                    // We can not call classToLoad.getDeclaredMethed() , since there
                    //  can be insatnce where mutiple services extends using one class
                    // just for init and other reflection methods
                    Method method = null;
                    try {
                        method = classToLoad.getMethod("deployFromURL", URL.class);
                    } catch (Exception e) {
                        //We do not need to inform this to user , since this something
                        // Axis2 is checking to support Session. So if the method is
                        // not there we should ignore that
                    }
                    if (method != null) {
                        try {
                            method.invoke(deployer, servicesURL);
                        } catch (Exception e) {
                            log.info(
                                    "Exception trying to call " + "deployFromURL for the deployer" +
                                            deployer.getClass(), e);
                        }
                    }
                }

            } catch (MalformedURLException e) {
                //I am just ignoring the error at the moment , but need to think how to handle this
            }

        }
    }

    private String getExtension(String fileName) {
        int lastIndex = fileName.lastIndexOf(".");
        return fileName.substring(lastIndex + 1);
    }

    public void loadServicesFromUrl(URL repoURL) {
        try {
            String path = servicesPath == null ? DeploymentConstants.SERVICE_PATH : servicesPath;
            if (!path.endsWith("/")) {
                path += "/";
            }
            String repoPath = repoURL.getPath();
            if (!repoPath.endsWith("/")) {
                repoPath += "/";
                repoURL = new URL(repoURL.getProtocol() + "://" + repoPath);
            }
            URL servicesDir = new URL(repoURL, path);
            URL filelisturl = new URL(servicesDir, "services.list");
            ArrayList<String> files = getFileList(filelisturl);
            repoListener = new RepositoryListener(this, false);
            for (Object file : files) {
                String fileUrl = (String) file;
                if (fileUrl.endsWith(".aar")) {
                    URL servicesURL = new URL(servicesDir, fileUrl);
                    repoListener.addURLToDeploy(servicesURL, getServiceDeployer(),
                            WSInfo.TYPE_SERVICE);
                }
            }
            repoListener.update();
            //Loading other type of services such as custom deployers
            loadCustomServices(repoURL);
        } catch (MalformedURLException e) {
            log.error(e.getMessage(), e);
        } 
    }

    public void loadRepositoryFromURL(URL repoURL) throws DeploymentException {
        try {
            setDeploymentFeatures();
            String path = modulesPath == null ? DeploymentConstants.MODULE_PATH : modulesPath;
            if (!path.endsWith("/")) {
                path = path + "/";
            }
            String repoPath = repoURL.getPath();
            if (!repoPath.endsWith("/")) {
                repoPath += "/";
                repoURL = new URL(repoURL.getProtocol() + "://" + repoPath);
            }
            URL moduleDir = new URL(repoURL, path);
            URL filelisturl = new URL(moduleDir, "modules.list");
            Iterator<String> fileIterator = getFileList(filelisturl).iterator();
            axisConfig.setRepository(repoURL);
            repoListener = new RepositoryListener(this, false);
            while (fileIterator.hasNext()) {
                String fileUrl = (String) fileIterator.next();
                if (fileUrl.endsWith(".mar")) {
                    URL moduleurl = new URL(moduleDir, fileUrl);
                    repoListener.addURLToDeploy(moduleurl, getModuleDeployer(), WSInfo.TYPE_MODULE);
                }
            }
            repoListener.update();
            org.apache.axis2.util.Utils.calculateDefaultModuleVersion(axisConfig.getModules(),
                    axisConfig);
            axisConfig.validateSystemPredefinedPhases();
        } catch (MalformedURLException e) {
            throw new DeploymentException(e);
        } catch (IOException e) {
            throw new DeploymentException(e);
        }
    }

    public static void addNewModule(AxisModule modulemetadata,
                                    AxisConfiguration axisConfiguration) throws AxisFault {

        Flow inflow = modulemetadata.getInFlow();
        ClassLoader moduleClassLoader = modulemetadata.getModuleClassLoader();

        if (inflow != null) {
            Utils.addFlowHandlers(inflow, moduleClassLoader);
        }

        Flow outFlow = modulemetadata.getOutFlow();

        if (outFlow != null) {
            Utils.addFlowHandlers(outFlow, moduleClassLoader);
        }

        Flow faultInFlow = modulemetadata.getFaultInFlow();

        if (faultInFlow != null) {
            Utils.addFlowHandlers(faultInFlow, moduleClassLoader);
        }

        Flow faultOutFlow = modulemetadata.getFaultOutFlow();

        if (faultOutFlow != null) {
            Utils.addFlowHandlers(faultOutFlow, moduleClassLoader);
        }

        axisConfiguration.addModule(modulemetadata);
        log.debug(Messages.getMessage(DeploymentErrorMsgs.ADDING_NEW_MODULE));

        synchronized (axisConfiguration.getFaultyServicesDuetoModules()) {

            //Check whether there are faulty services due to this module
            HashMap<String, FaultyServiceData> faultyServices =
                    (HashMap<String, FaultyServiceData>) axisConfiguration.getFaultyServicesDuetoModule(
                            modulemetadata.getName());
            faultyServices = (HashMap<String, FaultyServiceData>) faultyServices.clone();

            // Here iterating a cloned hashmap and modifying the original hashmap.
            // To avoid the ConcurrentModificationException.
            for (FaultyServiceData faultyServiceData : faultyServices.values()) {

                axisConfiguration.removeFaultyServiceDuetoModule(modulemetadata.getName(),
                        faultyServiceData
                                .getServiceGroup().getServiceGroupName());

                //Recover the faulty serviceGroup.
                addServiceGroup(faultyServiceData.getServiceGroup(),
                        faultyServiceData.getServiceList(),
                        faultyServiceData.getServiceLocation(),
                        faultyServiceData.getCurrentDeploymentFile(),
                        axisConfiguration);
            }
        }
    }

    public static void addServiceGroup(AxisServiceGroup serviceGroup,
                                       ArrayList<AxisService> serviceList,
                                       URL serviceLocation,
                                       DeploymentFileData currentDeploymentFile,
                                       AxisConfiguration axisConfiguration) throws AxisFault {

        if (isServiceGroupReadyToDeploy(serviceGroup, serviceList, serviceLocation,
                currentDeploymentFile, axisConfiguration)) {

            fillServiceGroup(serviceGroup, serviceList, serviceLocation, axisConfiguration);
            axisConfiguration.addServiceGroup(serviceGroup);

            if (currentDeploymentFile != null) {
                addAsWebResources(currentDeploymentFile.getFile(),
                        serviceGroup.getServiceGroupName(), serviceGroup);
                // let the system have hidden services
                if (!JavaUtils.isTrueExplicitly(serviceGroup.getParameterValue(
                        Constants.HIDDEN_SERVICE_PARAM_NAME))) {
                    log.info(Messages.getMessage(DeploymentErrorMsgs.DEPLOYING_WS,
                            currentDeploymentFile.getName(),
                            serviceLocation.toString()));
                }
            } else if (!JavaUtils.isTrueExplicitly(serviceGroup.getParameterValue(
                            Constants.HIDDEN_SERVICE_PARAM_NAME))) {
                log.info(Messages.getMessage(DeploymentErrorMsgs.DEPLOYING_WS,
                        serviceGroup.getServiceGroupName(), ""));
            }

        }
    }

    /**
     * Performs a check routine, in order to identify whether all the serviceGroup, service and
     * operation level modules are available. If a referenced module is not deployed yet, the
     * serviceGroup is added as a faulty service.
     *
     * @param serviceGroup          the AxisServiceGroup we're checking
     * @param serviceList           a List of AxisServices to check
     * @param serviceLocation       the URL of the service (only used if there's a problem)
     * @param currentDeploymentFile the current DeploymentFileData object (only used if there's a
     *                              problem)
     * @param axisConfig            the active AxisConfiguration
     * @return boolean
     * @throws AxisFault
     */
    protected static boolean isServiceGroupReadyToDeploy(AxisServiceGroup serviceGroup,
                                                         ArrayList<AxisService> serviceList,
                                                         URL serviceLocation,
                                                         DeploymentFileData currentDeploymentFile,
                                                         AxisConfiguration axisConfig)
            throws AxisFault {
        synchronized (axisConfig.getFaultyServicesDuetoModules()) {
            String moduleName;
            ArrayList<String> groupModules = serviceGroup.getModuleRefs();
            for (Object groupModule : groupModules) {
                moduleName = (String) groupModule;
                AxisModule module = axisConfig.getModule(moduleName);

                if (module == null) {
                    axisConfig.addFaultyServiceDuetoModule(moduleName,
                            new FaultyServiceData(serviceGroup,
                                    serviceList,
                                    serviceLocation,
                                    currentDeploymentFile));
                    if (log.isDebugEnabled()) {
                        log.debug("Service: " + serviceGroup.getServiceGroupName() +
                                " becomes faulty due to Module: " + moduleName);
                    }
                    return false;
                }
            }

            for (Object aServiceList : serviceList) {
                AxisService axisService = (AxisService) aServiceList;

                // modules from <service>
                ArrayList<String> list = axisService.getModules();

                for (Object aList : list) {
                    moduleName = (String) aList;
                    AxisModule module = axisConfig.getModule(moduleName);

                    if (module == null) {
                        axisConfig.addFaultyServiceDuetoModule(moduleName,
                                new FaultyServiceData(serviceGroup,
                                        serviceList,
                                        serviceLocation,
                                        currentDeploymentFile));
                        if (log.isDebugEnabled()) {
                            log.debug("Service: " + serviceGroup.getServiceGroupName() +
                                    " becomes faulty due to Module: " + moduleName);
                        }
                        return false;
                    }
                }

                for (Iterator<AxisOperation> iterator = axisService.getOperations(); iterator.hasNext();) {
                    AxisOperation opDesc = (AxisOperation) iterator.next();
                    ArrayList<String> modules = opDesc.getModuleRefs();

                    for (Object module1 : modules) {
                        moduleName = (String) module1;
                        AxisModule module = axisConfig.getModule(moduleName);

                        if (module == null) {
                            axisConfig.addFaultyServiceDuetoModule(moduleName,
                                    new FaultyServiceData(
                                            serviceGroup,
                                            serviceList,
                                            serviceLocation,
                                            currentDeploymentFile));
                            if (log.isDebugEnabled()) {
                                log.debug("Service: " + serviceGroup.getServiceGroupName() +
                                        " becomes faulty due to Module: " + moduleName);
                            }
                            return false;
                        }
                    }
                }
            }
        }
        return true;
    }

    protected static void fillServiceGroup(AxisServiceGroup serviceGroup,
                                           ArrayList<AxisService> serviceList,
                                           URL serviceLocation,
                                           AxisConfiguration axisConfig) throws AxisFault {
//        serviceGroup.setParent(axisConfig);
        // module from services.xml at serviceGroup level
        ArrayList<String> groupModules = serviceGroup.getModuleRefs();
        serviceGroup.setParent(axisConfig);
        for (Object groupModule : groupModules) {
            String moduleName = (String) groupModule;
            AxisModule module = axisConfig.getModule(moduleName);

            if (module != null) {
                serviceGroup.engageModule(axisConfig.getModule(moduleName));
            } else {
                throw new DeploymentException(
                        Messages.getMessage(
                                DeploymentErrorMsgs.BAD_MODULE_FROM_SERVICE,
                                serviceGroup.getServiceGroupName(), moduleName));
            }
        }

        Iterator<AxisService> services = serviceList.iterator();

        while (services.hasNext()) {
            AxisService axisService = (AxisService) services.next();
            axisService.setUseDefaultChains(false);

            axisService.setFileName(serviceLocation);
            serviceGroup.addService(axisService);

            // modules from <service>
            ArrayList<String> list = axisService.getModules();

            for (Object aList : list) {
                AxisModule module = axisConfig.getModule((String) aList);

                if (module == null) {
                    throw new DeploymentException(
                            Messages.getMessage(
                                    DeploymentErrorMsgs.BAD_MODULE_FROM_SERVICE,
                                    axisService.getName(),
                                    ((QName) aList).getLocalPart()));
                }

                axisService.engageModule(module);
            }

            for (Iterator<AxisOperation> iterator = axisService.getOperations(); iterator.hasNext();) {
                AxisOperation opDesc = (AxisOperation) iterator.next();
                ArrayList<String> modules = opDesc.getModuleRefs();

                for (Object module1 : modules) {
                    String moduleName = (String) module1;
                    AxisModule module = axisConfig.getModule(moduleName);

                    if (module != null) {
                        opDesc.engageModule(module);
                    } else {
                        throw new DeploymentException(
                                Messages.getMessage(
                                        DeploymentErrorMsgs.BAD_MODULE_FROM_OPERATION,
                                        opDesc.getName().getLocalPart(),
                                        moduleName));
                    }
                }
            }
        }
    }

    /**
     * @param file ArchiveFileData
     */
    public synchronized void addWSToDeploy(DeploymentFileData file) {
        wsToDeploy.add(file);
    }

    /**
     * @param file WSInfo
     */
    public synchronized void addWSToUndeploy(WSInfo file){
        wsToUnDeploy.add(file);
    }

    public synchronized void doDeploy() {
        try {
            if (wsToDeploy.size() > 0) {
                for (Object aWsToDeploy : wsToDeploy) {
                    DeploymentFileData fileToDeploy = (DeploymentFileData) aWsToDeploy;
                    try {
                        fileToDeploy.deploy();
                    } catch (DeploymentException e) {
                        // TODO : This probably isn't sufficient.  Maybe provide an option to stop?
                        log.info(e);
                    }
                }
            }
        } finally {
            wsToDeploy.clear();
        }
    }

    /**
     * Checks if the modules, referred by server.xml, exist or that they are deployed.
     *
     * @throws org.apache.axis2.AxisFault : If smt goes wrong
     */
    public void engageModules() throws AxisFault {
        axisConfig.engageGlobalModules();
    }

    /**
     * To get AxisConfiguration for a given inputStream this method can be used.
     * The inputstream should be a valid axis2.xml , else you will be getting
     * DeploymentExceptions.
     * <p/>
     * First creat a AxisConfiguration using given inputSream , and then it will
     * try to find the repository location parameter from AxisConfiguration, so
     * if user has add a parameter with the name "repository" , then the value
     * specified by that parameter will be the repository and system will try to
     * load modules and services from that repository location if it a valid
     * location. hot deployment and hot update will work as usual in this case.
     * <p/>
     * You will be getting AxisConfiguration corresponding to given inputstream
     * if it is valid , if something goes wrong you will be getting
     * DeploymentException
     *
     * @param in : InputStream to axis2.xml
     * @return a populated AxisConfiguration
     * @throws DeploymentException : If something goes wrong
     */
    public AxisConfiguration populateAxisConfiguration(InputStream in) throws DeploymentException {
        axisConfig = new AxisConfiguration();
        AxisConfigBuilder builder = new AxisConfigBuilder(in, axisConfig, this);
        builder.populateConfig();
        try {
            if (in != null) {
                in.close();
            }
        } catch (IOException e) {
            log.info("error in closing input stream");
        }
        moduleDeployer = new ModuleDeployer(axisConfig);
        return axisConfig;
    }

    /**
     * Starts the Deployment engine to perform Hot deployment and so on.
     *
     * @param listener : RepositoryListener
     */
    protected void startSearch(RepositoryListener listener) {
        scheduler = new Scheduler();

        schedulerTask = new SchedulerTask(listener, axisConfig);
        scheduler.schedule(schedulerTask, new DeploymentIterator());
    }

    /**
     * Method to check whether the deployment task is currently running. Will be used is graceful
     * shutdown & restart scenarios.
     *
     * @return true - if the deployment task is running, false - otherwise
     */
    public boolean isDeploymentTaskRunning() {
        synchronized (axisConfig) {
            Parameter deploymentTaskRunningParam =
                    axisConfig.getParameter(DeploymentEngine.DEPLOYMENT_TASK_RUNNING);
            if (deploymentTaskRunningParam != null) {
                return (Boolean) deploymentTaskRunningParam.getValue();
            }
            return false;
        }
    }

    public synchronized void unDeploy() {
        try {
            if (wsToUnDeploy.size() > 0) {
                for (Object aWsToUnDeploy : wsToUnDeploy) {
                    WSInfo wsInfo = (WSInfo) aWsToUnDeploy;
                    if (wsInfo.getType() == WSInfo.TYPE_SERVICE) {
                        //No matter what we need to undeploy the service
                        // if user has deleted the file from the repository
                        serviceDeployer.undeploy(wsInfo.getFileName());
                    } else {
                        //We need to undeploy the service whether we have enable hotUpdate or not ,
                        // o.w what happen if someone delete the service from the repo
                        Deployer deployer = wsInfo.getDeployer();
                        if (deployer != null) {
                            deployer.undeploy(wsInfo.getFileName());
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.info(e);
        }
        wsToUnDeploy.clear();
    }

    /**
     * Gets AxisConfiguration.
     *
     * @return AxisConfiguration <code>AxisConfiguration</code>
     */
    public AxisConfiguration getAxisConfig() {
        return axisConfig;
    }

    /**
     * Retrieves service name from the archive file name.
     * If the archive file name is service1.aar , then axis2 service name would be service1
     *
     * @param fileName the archive file name
     * @return Returns String.
     */
    public static String getAxisServiceName(String fileName) {
        char seperator = '.';
        String value;
        int index = fileName.lastIndexOf(seperator);

        if (index > 0) {
            value = fileName.substring(0, index);

            return value;
        }

        return fileName;
    }

    public AxisModule getModule(String moduleName) throws AxisFault {
        return axisConfig.getModule(moduleName);
    }

    public boolean isHotUpdate() {
        return hotUpdate;
    }

    private static void addAsWebResources(File in,
                                          String serviceFileName,
                                          AxisServiceGroup serviceGroup) {
        try {
            if (webLocationString == null) {
                return;
            }
            if (in.isDirectory()) {
                return;
            }
            File webLocation = new File(webLocationString);
            File out = new File(webLocation, serviceFileName);
            int BUFFER = 1024;
            byte data[] = new byte[BUFFER];
            FileInputStream fin = new FileInputStream(in);
            ZipInputStream zin = new ZipInputStream(
                    fin);
            ZipEntry entry;
            while ((entry = zin.getNextEntry()) != null) {
                ZipEntry zip = new ZipEntry(entry);
                if (zip.getName().toUpperCase().startsWith("WWW")) {
                    String fileName = zip.getName();
                    fileName = fileName.substring("WWW/".length(),
                            fileName.length());
                    if (zip.isDirectory()) {
                        new File(out, fileName).mkdirs();
                    } else {
                        FileOutputStream tempOut = new FileOutputStream(new File(out, fileName));
                        int count;
                        while ((count = zin.read(data, 0, BUFFER)) != -1) {
                            tempOut.write(data, 0, count);
                        }
                        tempOut.close();
                        tempOut.flush();
                    }
                    serviceGroup.setFoundWebResources(true);
                }
            }
            zin.close();
            fin.close();
        } catch (IOException e) {
            log.info(e.getMessage());
        }
    }

    public static String getWebLocationString() {
        return webLocationString;
    }

    /**
     * To set the all the classLoader hierarchy this method can be used , the top most parent is
     * CCL then SCL(system Class Loader)
     * CCL
     * :
     * SCL
     * :  :
     * MCCL  SCCL
     * :      :
     * MCL    SCL
     * <p/>
     * <p/>
     * MCCL :  module common class loader
     * SCCL : Service common class loader
     * MCL : module class loader
     * SCL  : Service class loader
     *
     * @param axis2repoURI : The repository folder of Axis2
     * @throws DeploymentException if there's a problem
     */
    protected void setClassLoaders(String axis2repoURI) throws DeploymentException {
        if (axisConfig.getSystemClassLoader() == null) {
            ClassLoader sysClassLoader =
                    Utils.getClassLoader(Thread.currentThread().getContextClassLoader(), axis2repoURI,
                            axisConfig.isChildFirstClassLoading());
    
            axisConfig.setSystemClassLoader(sysClassLoader);
        }
        if (servicesDir.exists()) {
            axisConfig.setServiceClassLoader(
                    Utils.getClassLoader(axisConfig.getSystemClassLoader(), servicesDir,
                            axisConfig.isChildFirstClassLoading()));
        } else {
            axisConfig.setServiceClassLoader(axisConfig.getSystemClassLoader());
        }

        if (modulesDir.exists()) {
            axisConfig.setModuleClassLoader(Utils.getClassLoader(axisConfig.getSystemClassLoader(),
                    modulesDir,
                    axisConfig.isChildFirstClassLoading()));
        } else {
            axisConfig.setModuleClassLoader(axisConfig.getSystemClassLoader());
        }
    }

    /**
     * Sets hotDeployment and hot update.
     */
    protected void setDeploymentFeatures() {
        Parameter hotDeployment = axisConfig.getParameter(TAG_HOT_DEPLOYMENT);
        Parameter hotUpdate = axisConfig.getParameter(TAG_HOT_UPDATE);

        if (hotDeployment != null) {
            this.hotDeployment = JavaUtils.isTrue(hotDeployment.getValue(), true);
        }

        if (hotUpdate != null) {
            this.hotUpdate = JavaUtils.isTrue(hotUpdate.getValue(), true);
        }

        String serviceDirPara = (String)
                axisConfig.getParameterValue(DeploymentConstants.SERVICE_DIR_PATH);
        if (serviceDirPara != null) {
            servicesPath = serviceDirPara;
        }

        String moduleDirPara = (String)
                axisConfig.getParameterValue(DeploymentConstants.MODULE_DRI_PATH);
        if (moduleDirPara != null) {
            modulesPath = moduleDirPara;
        }
    }

    /**
     * Creates directories for modules/services, copies configuration xml from class loader if necessary
     *
     * @param repositoryName the pathname of the repository
     */

    protected void prepareRepository(String repositoryName) {
        repositoryDir = new File(repositoryName);
        if (servicesPath != null) {
            servicesDir = new File(servicesPath);
            if (!servicesDir.exists()) {
                servicesDir = new File(repositoryDir, servicesPath);
            }
        } else {
            servicesDir = new File(repositoryDir, DeploymentConstants.SERVICE_PATH);
        }
        if (!servicesDir.exists()) {
            log.info(Messages.getMessage("noservicedirfound", getRepositoryPath(repositoryDir)));
        }
        if (modulesPath != null) {
            modulesDir = new File(modulesPath);
            if (!modulesDir.exists()) {
                modulesDir = new File(repositoryDir, modulesPath);
            }
        } else {
            modulesDir = new File(repositoryDir, DeploymentConstants.MODULE_PATH);
        }
        if (!modulesDir.exists()) {
            log.info(Messages.getMessage("nomoduledirfound", getRepositoryPath(repositoryDir)));
        }
    }

    protected String getRepositoryPath(File repository) {
        try {
            return repository.getCanonicalPath();
        } catch (IOException e) {
            return repository.getAbsolutePath();
        }
    }

    protected ArrayList<String> getFileList(URL fileListUrl) {
        ArrayList<String> fileList = new ArrayList<String>();
        InputStream in;
        try {
            in = fileListUrl.openStream();
        } catch (IOException e) {
        	log.info(e.getMessage() + " -  as per axis2.repository.url, the URL is "+fileListUrl+" that will be used relative to "+new File(".").getAbsolutePath());
            return fileList;
        }
        BufferedReader input = null;
        try {
            input = new BufferedReader(new InputStreamReader(in));
            String line;
            while ((line = input.readLine()) != null) {
                line = line.trim();
                if (line.length() > 0 && line.charAt(0) != '#') {
                    fileList.add(line);
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (input != null) {
                    input.close();
                }
            }
            catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return fileList;
    }

    public void setConfigContext(ConfigurationContext configContext) {
        this.configContext = configContext;
        initializeDeployers(this.configContext);
    }

    private void initializeDeployers(ConfigurationContext configContext) {
        
        for (Map<String, Deployer> extensionMap : deployerMap.values()) {
            for (Deployer deployer : extensionMap.values()) {
                deployer.init(configContext);
                if (deployer instanceof AbstractDeployer) {
                    for (Iterator<ServiceBuilderExtension> sbeItr = ((AbstractDeployer) deployer)
                            .getServiceBuilderExtensions().iterator(); sbeItr.hasNext();) {
                        // init ServiceBuilderExtensions
                        ServiceBuilderExtension builderExtension = sbeItr.next();
                        builderExtension.init(configContext);
                        ((AbstractDeployer) deployer).addServiceBuilderExtensions(builderExtension);                        
                    }
                    /*
                     * URL based deployment does not fully based on standard
                     * deployment architecture hence it's require to set
                     * serviceDeployer variable. serviceDeployer variable
                     * set only if the ServiceDeployer has been registered
                     * on axis2.xml file.
                     */
                    if (deployer instanceof ServiceDeployer) {
                        serviceDeployer = (ServiceDeployer) deployer;
                    }
                }
            }
        }
    }

    /**
     * Builds an AxisModule for a given module archive file. This does not
     * called the init method since there is no reference to configuration context
     * so who ever create module using this has to called module.init if it is
     * required
     *
     * @param modulearchive : Actual module archive file
     * @param config        : AxisConfiguration : for get classloaders etc..
     * @return a complete AxisModule read from the file.
     * @throws org.apache.axis2.deployment.DeploymentException
     *          if there's a problem
     */
    public static AxisModule buildModule(File modulearchive,
                                         AxisConfiguration config)
            throws DeploymentException {
        AxisModule axismodule;
        ModuleDeployer deployer = (ModuleDeployer) config.getParameterValue(MODULE_DEPLOYER);
        try {
            if (deployer == null) {
                deployer = new ModuleDeployer(config);
                config.addParameter(MODULE_DEPLOYER, deployer);
            }

            DeploymentFileData currentDeploymentFile = new DeploymentFileData(modulearchive,
                    deployer);
            axismodule = new AxisModule();
            ArchiveReader archiveReader = new ArchiveReader();

            currentDeploymentFile.setClassLoader(false, config.getModuleClassLoader(), null,
                    config.isChildFirstClassLoading());
            axismodule.setModuleClassLoader(currentDeploymentFile.getClassLoader());
            archiveReader.readModuleArchive(currentDeploymentFile, axismodule,
                    false, config);
            ClassLoader moduleClassLoader = axismodule.getModuleClassLoader();
            Flow inflow = axismodule.getInFlow();

            if (inflow != null) {
                Utils.addFlowHandlers(inflow, moduleClassLoader);
            }

            Flow outFlow = axismodule.getOutFlow();

            if (outFlow != null) {
                Utils.addFlowHandlers(outFlow, moduleClassLoader);
            }

            Flow faultInFlow = axismodule.getFaultInFlow();

            if (faultInFlow != null) {
                Utils.addFlowHandlers(faultInFlow, moduleClassLoader);
            }

            Flow faultOutFlow = axismodule.getFaultOutFlow();

            if (faultOutFlow != null) {
                Utils.addFlowHandlers(faultOutFlow, moduleClassLoader);
            }
        } catch (AxisFault axisFault) {
            throw new DeploymentException(axisFault);
        }
        return axismodule;
    }

    /**
     * Fills an axisservice object using services.xml. First creates
     * an axisservice object using WSDL and then fills it using the given services.xml.
     * Loads all the required class and builds the chains, finally adds the
     * servicecontext to EngineContext and axisservice into EngineConfiguration.
     *
     * @param serviceInputStream InputStream containing configuration data
     * @param configCtx          the ConfigurationContext in which we're deploying
     * @return Returns AxisService.
     * @throws DeploymentException if there's a problem
     */
    public static AxisService buildService(InputStream serviceInputStream,
                                           ConfigurationContext configCtx)
            throws DeploymentException {
        AxisService axisService = new AxisService();
        try {
            ServiceBuilder builder = new ServiceBuilder(serviceInputStream, configCtx, axisService);
            builder.populateService(builder.buildOM());
        } catch (AxisFault axisFault) {
            throw new DeploymentException(axisFault);
        } catch (XMLStreamException e) {
            throw new DeploymentException(e);
        }

        return axisService;
    }

    /**
     * To build a AxisServiceGroup for a given services.xml
     * You have to add the created group into AxisConfig
     *
     * @param servicesxml      InputStream created from services.xml or equivalent
     * @param classLoader      ClassLoader to use
     * @param serviceGroupName name of the service group
     * @param configCtx        the ConfigurationContext in which we're deploying
     * @param archiveReader    the ArchiveReader we're working with
     * @param wsdlServices     Map of existing WSDL services
     * @return a fleshed-out AxisServiceGroup
     * @throws AxisFault if there's a problem
     */
    public static AxisServiceGroup buildServiceGroup(InputStream servicesxml,
                                                     ClassLoader classLoader,
                                                     String serviceGroupName,
                                                     ConfigurationContext configCtx,
                                                     ArchiveReader archiveReader,
                                                     HashMap<String, AxisService> wsdlServices) throws AxisFault {
        DeploymentFileData currentDeploymentFile = new DeploymentFileData(null, null);
        currentDeploymentFile.setClassLoader(classLoader);
        AxisServiceGroup serviceGroup = new AxisServiceGroup();
        serviceGroup.setServiceGroupClassLoader(classLoader);
        serviceGroup.setServiceGroupName(serviceGroupName);
        AxisConfiguration axisConfig = configCtx.getAxisConfiguration();
        try {
            ArrayList<AxisService> serviceList = archiveReader.buildServiceGroup(servicesxml,
                    currentDeploymentFile,
                    serviceGroup,
                    wsdlServices, configCtx);
            fillServiceGroup(serviceGroup, serviceList, null, axisConfig);
            return serviceGroup;
        } catch (XMLStreamException e) {
            throw AxisFault.makeFault(e);
        }
    }

    public static AxisServiceGroup loadServiceGroup(File serviceFile,
                                                    ConfigurationContext configCtx)
            throws AxisFault {
        try {
            DeploymentFileData currentDeploymentFile = new DeploymentFileData(serviceFile, null);
            DeploymentClassLoader classLoader = Utils.createClassLoader(serviceFile,
                    configCtx.getAxisConfiguration().isChildFirstClassLoading());
            currentDeploymentFile.setClassLoader(classLoader);
            AxisServiceGroup serviceGroup = new AxisServiceGroup();
            serviceGroup.setServiceGroupClassLoader(classLoader);

            // Drop the extension and take the name
            String fileName = serviceFile.getName();
            String serviceGroupName = fileName.substring(0, fileName.lastIndexOf("."));
            serviceGroup.setServiceGroupName(serviceGroupName);
            AxisConfiguration axisConfig = configCtx.getAxisConfiguration();

            ArchiveReader archiveReader = new ArchiveReader();
            HashMap<String, AxisService> wsdlServices = archiveReader.processWSDLs(currentDeploymentFile);
            InputStream serviceXml = classLoader.getResourceAsStream("META-INF/services.xml");
            ArrayList<AxisService> serviceList = archiveReader.buildServiceGroup(serviceXml,
                    currentDeploymentFile,
                    serviceGroup,
                    wsdlServices, configCtx);
            fillServiceGroup(serviceGroup, serviceList, null, axisConfig);
            return serviceGroup;
        } catch (Exception e) {
            throw new DeploymentException(e);
        }
    }

    public File getServicesDir() {
        return servicesDir;
    }

    public File getModulesDir() {
        return modulesDir;
    }


    public File getRepositoryDir() {
        return repositoryDir;
    }

    public void setDeployers(Map<String, Map<String, Deployer>> deployerMap) {
        this.deployerMap = deployerMap;
    }

    public Map<String, Map<String, Deployer>> getDeployers() {
        return this.deployerMap;
    }

    public RepositoryListener getRepoListener() {
        return repoListener;
    }


    public ServiceDeployer getServiceDeployer() {
        return serviceDeployer;
    }

    public ModuleDeployer getModuleDeployer() {
        return moduleDeployer;
    }

    public Deployer getDeployer(String directory, String extension) {
        Map<String, Deployer> extensionMap = deployerMap.get(directory);
        return (extensionMap != null) ? extensionMap.get(extension) : null;
    }

    private static void destroyClassLoader(ClassLoader classLoader) {
        if (classLoader instanceof DeploymentClassLoader) {
            try {
                ((DeploymentClassLoader)classLoader).close();
            } catch (IOException ex) {
                log.warn("Failed to destroy class loader " + classLoader, ex);
            }
        }
    }

    /**
     * Clean up the mess
     */
    public void cleanup() {
        destroyClassLoader(axisConfig.getModuleClassLoader());
        destroyClassLoader(axisConfig.getServiceClassLoader());
        destroyClassLoader(axisConfig.getSystemClassLoader());
        if (scheduler != null) {
            scheduler.cleanup(schedulerTask);
        }
        for (Map<String, Deployer> stringDeployerMap : deployerMap.values()) {
            for (Deployer deployer : stringDeployerMap.values()) {
                try {
                    deployer.cleanup();
                } catch (DeploymentException e) {
                    log.error("Error occurred while cleaning up deployer", e);
                }
            }
        }
    }

    /**
     * Add and initialize a new Deployer.
     *
     * @param deployer  Deployer object to be registered
     * @param directory the directory which will be scanned for deployable artifacts
     * @param extension the extension of the deployable artifacts for this Deployer
     */
    public void addDeployer(Deployer deployer, String directory, String extension) {

        if (deployer == null) {
            log.error("Failed to add Deployer : deployer is null");
            return;
        }

        if (directory == null) {
            log.error("Failed to add Deployer " + deployer.getClass().getName() + ": missing 'directory' attribute");
            return;
        }

        //Extention is optional if the extention is not provided deployer will deploy the directories
        if (extension != null) {
            // A leading dot is redundant, so strip it.  So we allow either ".foo" or "foo", either
            // of which will result in extension="foo"
            if (extension.charAt(0) == '.') extension = extension.substring(1);
        }

        // If axis2 is not initialized, Axis2 will handle the deployer init() and relavent service deployment
        // If axis2 is initialized and hotDeployment is on, Axis2 will handle the relavent service deployments.
        // If axis2 is initialized and hotDeployment is off, we need to manually deploy the relavent service artifacts.
        if (configContext != null) {
            // Initialize the Deployer
            deployer.init(configContext);
            for (Iterator<ServiceBuilderExtension> sbeItr = ((AbstractDeployer) deployer)
                    .getServiceBuilderExtensions().iterator(); sbeItr.hasNext();) {
                //init ServiceBuilderExtensions
                sbeItr.next().init(configContext);
            }
            if (!hotDeployment) {
                //TBD
            }
        }

        lock.lock();
        try {
            Map<String, Deployer> extensionMap = deployerMap.get(directory);
            if (extensionMap == null) {
                extensionMap = new HashMap<String, Deployer>();
                deployerMap.put(directory, extensionMap);
            }
            extensionMap.put(extension, deployer);
        } finally {
            lock.unlock();
        }


    }

    /**
     * Remove any Deployer mapped for the given directory and extension
     *
     * @param directory the directory of deployables
     * @param extension the extension of deployables
     */
    public void removeDeployer(String directory, String extension) {
        if (directory == null) {
            log.error("Failed to remove Deployer : missing 'directory' attribute");
            return;
        }

        if (extension == null) {
            log.error("Failed to remove Deployer : Deployer missing 'extension' attribute");
            return;
        }

        Map<String, Deployer> extensionMap = deployerMap.get(directory);
        if (extensionMap == null) {
            return;
        }

        lock.lock();
        try {
            if (extensionMap.containsKey(extension)) {
                Deployer deployer = extensionMap.remove(extension);
                if (extensionMap.isEmpty()) {
                    deployerMap.remove(directory);
                }

                if (log.isDebugEnabled()) {
                    log.debug("Deployer " + deployer.getClass().getName() + " is removed");
                }
            }
        } finally {
            lock.unlock();
        }
    }
}
