org.apache.axis2.deployment.DeploymentEngine.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.axis2.deployment.DeploymentEngine.java

Source

/*
 * 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.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.classloader.JarFileClassLoader;
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.resolver.AARBasedWSDLLocator;
import org.apache.axis2.deployment.resolver.AARFileBasedURIResolver;
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.description.WSDL11ToAxisServiceBuilder;
import org.apache.axis2.description.WSDL2Constants;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.engine.MessageReceiver;
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.*;
import java.util.concurrent.ConcurrentHashMap;
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 wsToDeploy = new ArrayList();

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

    /**
     * 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 ConcurrentHashMap<String, Map<String, Deployer>>();

    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.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);
                ArrayList 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 files = getFileList(filelisturl);

            for (Object file : files) {
                String fileUrl = (String) file;
                if (fileUrl.endsWith(".aar")) {
                    AxisServiceGroup serviceGroup = new AxisServiceGroup();
                    URL servicesURL = new URL(servicesDir, fileUrl);
                    ArrayList servicelist = populateService(serviceGroup, servicesURL,
                            fileUrl.substring(0, fileUrl.indexOf(".aar")));
                    addServiceGroup(serviceGroup, servicelist, servicesURL, null, axisConfig);
                    // let the system have hidden services
                    if (!JavaUtils.isTrueExplicitly(
                            serviceGroup.getParameterValue(Constants.HIDDEN_SERVICE_PARAM_NAME))) {
                        log.info(Messages.getMessage(DeploymentErrorMsgs.DEPLOYING_WS,
                                serviceGroup.getServiceGroupName(), servicesURL.toString()));
                    }
                }
            }
            //Loading other type of services such as custom deployers
            loadCustomServices(repoURL);
        } catch (MalformedURLException e) {
            log.error(e.getMessage(), e);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    public void loadRepositoryFromURL(URL repoURL) throws DeploymentException {
        try {
            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");
            ArrayList files = getFileList(filelisturl);
            Iterator fileIterator = files.iterator();
            while (fileIterator.hasNext()) {
                String fileUrl = (String) fileIterator.next();
                if (fileUrl.endsWith(".mar")) {
                    URL moduleurl = new URL(moduleDir, fileUrl);
                    ClassLoader deploymentClassLoader = Utils.createClassLoader(new URL[] { moduleurl },
                            axisConfig.getModuleClassLoader(), true,
                            (File) axisConfig.getParameterValue(Constants.Configuration.ARTIFACTS_TEMP_DIR),
                            axisConfig.isChildFirstClassLoading());
                    AxisModule module = new AxisModule();
                    module.setModuleClassLoader(deploymentClassLoader);
                    module.setParent(axisConfig);
                    String moduleFile = fileUrl.substring(0, fileUrl.indexOf(".mar"));
                    module.setArchiveName(moduleFile);
                    populateModule(module, moduleurl);
                    module.setFileName(moduleurl);
                    addNewModule(module, axisConfig);
                    log.info(Messages.getMessage(DeploymentErrorMsgs.DEPLOYING_MODULE, module.getArchiveName(),
                            moduleurl.toString()));
                }
            }
            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);
        }
    }

    private void populateModule(AxisModule module, URL moduleUrl) throws DeploymentException {
        try {
            ClassLoader classLoader = module.getModuleClassLoader();
            InputStream moduleStream = classLoader.getResourceAsStream("META-INF/module.xml");
            if (moduleStream == null) {
                moduleStream = classLoader.getResourceAsStream("meta-inf/module.xml");
            }
            if (moduleStream == null) {
                throw new DeploymentException(
                        Messages.getMessage(DeploymentErrorMsgs.MODULE_XML_MISSING, moduleUrl.toString()));
            }
            ModuleBuilder moduleBuilder = new ModuleBuilder(moduleStream, module, axisConfig);
            moduleBuilder.populateModule();
        } catch (IOException e) {
            throw new DeploymentException(e);
        }
    }

    protected ArrayList populateService(AxisServiceGroup serviceGroup, URL servicesURL, String serviceName)
            throws DeploymentException {
        try {
            serviceGroup.setServiceGroupName(serviceName);
            ClassLoader serviceClassLoader = Utils.createClassLoader(new URL[] { servicesURL },
                    axisConfig.getServiceClassLoader(), true,
                    (File) axisConfig.getParameterValue(Constants.Configuration.ARTIFACTS_TEMP_DIR),
                    axisConfig.isChildFirstClassLoading());
            String metainf = "meta-inf";
            serviceGroup.setServiceGroupClassLoader(serviceClassLoader);
            //processing wsdl.list
            InputStream wsdlfilesStream = serviceClassLoader.getResourceAsStream("meta-inf/wsdl.list");
            if (wsdlfilesStream == null) {
                wsdlfilesStream = serviceClassLoader.getResourceAsStream("META-INF/wsdl.list");
                if (wsdlfilesStream != null) {
                    metainf = "META-INF";
                }
            }
            HashMap servicesMap = new HashMap();
            if (wsdlfilesStream != null) {
                ArchiveReader reader = new ArchiveReader();
                BufferedReader input = new BufferedReader(new InputStreamReader(wsdlfilesStream));
                String line;
                while ((line = input.readLine()) != null) {
                    line = line.trim();
                    if (line.length() > 0 && line.charAt(0) != '#') {
                        line = metainf + "/" + line;
                        try {
                            List services = reader.getAxisServiceFromWsdl(
                                    serviceClassLoader.getResourceAsStream(line), serviceClassLoader, line);
                            if (services != null) {
                                for (Object service : services) {
                                    AxisService axisService = (AxisService) service;
                                    servicesMap.put(axisService.getName(), axisService);
                                }
                            }

                        } catch (Exception e) {
                            throw new DeploymentException(e);
                        }
                    }
                }
            }
            InputStream servicexmlStream = serviceClassLoader.getResourceAsStream("META-INF/services.xml");
            if (servicexmlStream == null) {
                servicexmlStream = serviceClassLoader.getResourceAsStream("meta-inf/services.xml");
            } else {
                metainf = "META-INF";
            }
            if (servicexmlStream == null) {
                throw new DeploymentException(
                        Messages.getMessage(DeploymentErrorMsgs.SERVICE_XML_NOT_FOUND, servicesURL.toString()));
            }
            DescriptionBuilder builder = new DescriptionBuilder(servicexmlStream, configContext);
            OMElement rootElement = builder.buildOM();
            String elementName = rootElement.getLocalName();

            if (TAG_SERVICE.equals(elementName)) {
                AxisService axisService = null;
                String wsdlLocation = "META-INF/service.wsdl";
                InputStream wsdlStream = serviceClassLoader.getResourceAsStream(wsdlLocation);
                URL wsdlURL = serviceClassLoader.getResource(metainf + "/service.wsdl");
                if (wsdlStream == null) {
                    wsdlLocation = "META-INF/" + serviceName + ".wsdl";
                    wsdlStream = serviceClassLoader.getResourceAsStream(wsdlLocation);
                    wsdlURL = serviceClassLoader.getResource(wsdlLocation);
                }
                if (wsdlStream != null) {
                    WSDL11ToAxisServiceBuilder wsdl2AxisServiceBuilder = new WSDL11ToAxisServiceBuilder(wsdlStream,
                            null, null);
                    File file = Utils.toFile(servicesURL);
                    if (file != null && file.exists()) {
                        wsdl2AxisServiceBuilder
                                .setCustomWSDLResolver(new AARBasedWSDLLocator(wsdlLocation, file, wsdlStream));
                        wsdl2AxisServiceBuilder.setCustomResolver(new AARFileBasedURIResolver(file));
                    }
                    if (wsdlURL != null) {
                        wsdl2AxisServiceBuilder.setDocumentBaseUri(wsdlURL.toString());
                    }
                    axisService = wsdl2AxisServiceBuilder.populateService();
                    axisService.setWsdlFound(true);
                    axisService.setCustomWsdl(true);
                    axisService.setName(serviceName);
                }
                if (axisService == null) {
                    axisService = new AxisService(serviceName);
                }

                axisService.setParent(serviceGroup);
                axisService.setClassLoader(serviceClassLoader);

                ServiceBuilder serviceBuilder = new ServiceBuilder(configContext, axisService);
                AxisService service = serviceBuilder.populateService(rootElement);

                ArrayList serviceList = new ArrayList();
                serviceList.add(service);
                return serviceList;
            } else if (TAG_SERVICE_GROUP.equals(elementName)) {
                ServiceGroupBuilder groupBuilder = new ServiceGroupBuilder(rootElement, servicesMap, configContext);
                ArrayList servicList = groupBuilder.populateServiceGroup(serviceGroup);
                Iterator serviceIterator = servicList.iterator();
                while (serviceIterator.hasNext()) {
                    AxisService axisService = (AxisService) serviceIterator.next();
                    String wsdlLocation = "META-INF/service.wsdl";
                    InputStream wsdlStream = serviceClassLoader.getResourceAsStream(wsdlLocation);
                    URL wsdlURL = serviceClassLoader.getResource(wsdlLocation);
                    if (wsdlStream == null) {
                        wsdlLocation = "META-INF/" + serviceName + ".wsdl";
                        wsdlStream = serviceClassLoader.getResourceAsStream(wsdlLocation);
                        wsdlURL = serviceClassLoader.getResource(wsdlLocation);
                    }
                    if (wsdlStream != null) {
                        WSDL11ToAxisServiceBuilder wsdl2AxisServiceBuilder = new WSDL11ToAxisServiceBuilder(
                                wsdlStream, axisService);
                        File file = Utils.toFile(servicesURL);
                        if (file != null && file.exists()) {
                            wsdl2AxisServiceBuilder
                                    .setCustomWSDLResolver(new AARBasedWSDLLocator(wsdlLocation, file, wsdlStream));
                            wsdl2AxisServiceBuilder.setCustomResolver(new AARFileBasedURIResolver(file));
                        }
                        if (wsdlURL != null) {
                            wsdl2AxisServiceBuilder.setDocumentBaseUri(wsdlURL.toString());
                        }
                        axisService = wsdl2AxisServiceBuilder.populateService();
                        axisService.setWsdlFound(true);
                        axisService.setCustomWsdl(true);
                        // Set the default message receiver for the operations that were
                        // not listed in the services.xml
                        Iterator operations = axisService.getOperations();
                        while (operations.hasNext()) {
                            AxisOperation operation = (AxisOperation) operations.next();
                            if (operation.getMessageReceiver() == null) {
                                operation.setMessageReceiver(loadDefaultMessageReceiver(
                                        operation.getMessageExchangePattern(), axisService));
                            }
                        }
                    }
                }
                return servicList;
            }
        } catch (IOException e) {
            throw new DeploymentException(e);
        } catch (XMLStreamException e) {
            throw new DeploymentException(e);
        }
        return null;
    }

    protected MessageReceiver loadDefaultMessageReceiver(String mepURL, AxisService service) {
        MessageReceiver messageReceiver;
        if (mepURL == null) {
            mepURL = WSDL2Constants.MEP_URI_IN_OUT;
        }
        if (service != null) {
            messageReceiver = service.getMessageReceiver(mepURL);
            if (messageReceiver != null) {
                return messageReceiver;
            }
        }
        return axisConfig.getMessageReceiver(mepURL);
    }

    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 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 serviceList,
            URL serviceLocation, DeploymentFileData currentDeploymentFile, AxisConfiguration axisConfig)
            throws AxisFault {
        synchronized (axisConfig.getFaultyServicesDuetoModules()) {
            String moduleName;
            ArrayList 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 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 iterator = axisService.getOperations(); iterator.hasNext();) {
                    AxisOperation opDesc = (AxisOperation) iterator.next();
                    ArrayList 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 serviceList,
            URL serviceLocation, AxisConfiguration axisConfig) throws AxisFault {
        //        serviceGroup.setParent(axisConfig);
        // module from services.xml at serviceGroup level
        ArrayList 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 services = serviceList.iterator();

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

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

            // modules from <service>
            ArrayList 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 iterator = axisService.getOperations(); iterator.hasNext();) {
                AxisOperation opDesc = (AxisOperation) iterator.next();
                ArrayList 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) {
                sortWSToDeploy();
                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();
        }
    }

    /**
     * Sort the deployable artifacts, s.t original order (metafiles first, then artifacts) is preserved.
     * Thus, supporting Ghost Deployment of the artifacts properly.
     * <p/>
     * Take the first file in each category (metafiles,artifacts etc), & take its file path without the file name to
     * identify which category it belongs.
     * Then,count all the files belonging to that category, & sort it within the list.
     * The final list will have the original order of categories, with only files inside each category sorted.
     */
    private void sortWSToDeploy() {
        int artifactsCount = 0;
        final int listSize = wsToDeploy.size();

        while (artifactsCount < listSize) {
            DeploymentFileData tempDeployableArtifact = (DeploymentFileData) wsToDeploy.get(artifactsCount);
            String tempFilePathWithoutFileName = tempDeployableArtifact.getFile().getParent();
            int startIndex = artifactsCount;
            //get the count of artifacts belonging to each category
            for (ListIterator<Object> it = wsToDeploy.listIterator(startIndex); it.hasNext();) {
                DeploymentFileData deployableArtifact = (DeploymentFileData) it.next();
                String filePathWithoutFileName = deployableArtifact.getFile().getParent();
                if (tempFilePathWithoutFileName.equals(filePathWithoutFileName)) {
                    artifactsCount++;
                } else {
                    break;
                }
            }
            //sort artifacts belonging to each category, within the list itself.
            Collections.sort(wsToDeploy.subList(startIndex, artifactsCount), new Comparator<DeploymentFileData>() {
                public int compare(DeploymentFileData deploymentFileData1, DeploymentFileData deploymentFileData2) {
                    return deploymentFileData1.getFile().getName()
                            .compareTo(deploymentFileData2.getFile().getName());
                }
            });
        }
    }

    /**
     * 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 {
        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 getFileList(URL fileListUrl) {
        ArrayList fileList = new ArrayList();
        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) {
        serviceDeployer = new ServiceDeployer();
        serviceDeployer.init(configContext);
        if (this.servicesDir != null) {
            serviceDeployer.setDirectory(this.servicesDir.getName());
        }
        for (Map<String, Deployer> extensionMap : deployerMap.values()) {
            for (Deployer deployer : extensionMap.values()) {
                deployer.init(configContext);
            }
        }
    }

    /**
     * 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 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 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 wsdlServices = archiveReader.processWSDLs(currentDeploymentFile);
            InputStream serviceXml = classLoader.getResourceAsStream("META-INF/services.xml");
            ArrayList 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;
    }

    /**
     * Clean up the mess
     */
    public void cleanup() {
        if (axisConfig.getModuleClassLoader() instanceof JarFileClassLoader) {
            ((JarFileClassLoader) axisConfig.getModuleClassLoader()).destroy();
        }
        if (axisConfig.getServiceClassLoader() instanceof JarFileClassLoader) {
            ((JarFileClassLoader) axisConfig.getServiceClassLoader()).destroy();
        }
        if (axisConfig.getSystemClassLoader() instanceof JarFileClassLoader) {
            ((JarFileClassLoader) axisConfig.getSystemClassLoader()).destroy();
        }
        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);
            if (!hotDeployment) {
                //TBD
            }
        }

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

    }

    /**
     * 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;
        }

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

    }
}