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

import java.io.File;
import java.net.URL;
import java.security.PrivilegedAction;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.xml.namespace.QName;

import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.transaction.TransactionConfiguration;
import org.apache.axis2.builder.Builder;
import org.apache.axis2.builder.unknowncontent.UnknownContentBuilder;
import org.apache.axis2.clustering.ClusteringAgent;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.dataretrieval.AxisDataLocator;
import org.apache.axis2.deployment.DeploymentException;
import org.apache.axis2.deployment.ModuleDeployer;
import org.apache.axis2.deployment.repository.util.DeploymentFileData;
import org.apache.axis2.deployment.util.PhasesInfo;
import org.apache.axis2.description.AxisDescription;
import org.apache.axis2.description.AxisEndpoint;
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.ModuleConfiguration;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.TransportInDescription;
import org.apache.axis2.description.TransportOutDescription;
import org.apache.axis2.description.Version;
import org.apache.axis2.description.java2wsdl.Java2WSDLConstants;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.phaseresolver.PhaseMetadata;
import org.apache.axis2.phaseresolver.PhaseResolver;
import org.apache.axis2.transport.MessageFormatter;
import org.apache.axis2.util.TargetResolver;
import org.apache.axis2.util.Utils;
import org.apache.axis2.util.FaultyServiceData;
import org.apache.axis2.util.JavaUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Class AxisConfiguration
 */
public class AxisConfiguration extends AxisDescription {

    private static final Log log = LogFactory.getLog(AxisConfiguration.class);
    /* 
     * To store configured data locators
     */
    private HashMap<String, AxisDataLocator> dataLocators = new HashMap<String, AxisDataLocator>();
    private HashMap<String, String> dataLocatorClassNames = new HashMap<String, String>();

    /**
     * Map of all available modules. The key is the archive name as defined by
     * {@link AxisModule#getArchiveName()}.
     */
    private final HashMap<String, AxisModule> allModules = new HashMap<String, AxisModule>();

    // To store mapping between default version and module name
    private final HashMap<String, String> nameToversionMap = new HashMap<String, String>();

    // private final HashMap serviceGroups = new HashMap();
    private final HashMap<String, TransportInDescription> transportsIn = new HashMap<String, TransportInDescription>();

    private final HashMap<String, TransportOutDescription> transportsOut = new HashMap<String, TransportOutDescription>();

    private final HashMap<String, List<AxisModule>> policySupportedModules = new HashMap<String, List<AxisModule>>();

    /**
     * Stores the QNames of local policy assertions
     */
    private final ArrayList<QName> localPolicyAssertions = new ArrayList<QName>();

    // to store AxisObserver Objects
    private Set<AxisObserver> observerSet = null;

    private URL axis2Repository = null;

    private Map<String, AxisService> allServices = new ConcurrentHashMap<String, AxisService>();
    private Map<String, AxisService> allEndpoints = new ConcurrentHashMap<String, AxisService>();

    /**
     * Stores the module specified in the server.xml at the document parsing time.
     */
    private List<String> globalModuleList;

    private Hashtable<String, String> faultyModules;

    /**
     * To store faulty services
     */
    private Hashtable<String, String> faultyServices;

    /**
     * To store services which have become faulty due to modules. Here key is the module name and
     * the corresponding value is an another map which holds the a Map of faulty services due a
     * single module (keyed by service name).
     */
    private final Map<String, Map<String, FaultyServiceData>> faultyServicesDueToModules =
            new HashMap<String, Map<String, FaultyServiceData>>();


    private List<Phase> inFaultPhases;

    private List<Phase> inPhasesUptoAndIncludingPostDispatch;

    private HashMap<String, MessageReceiver> messageReceivers;

    private HashMap<String, Builder> messageBuilders;

    private HashMap<String, MessageFormatter> messageFormatters;

    private ClassLoader moduleClassLoader;

    private HashMap<String, ModuleConfiguration> moduleConfigmap;

    private List<Phase> outFaultPhases;

    private List<Phase> outPhases;

    protected PhasesInfo phasesinfo;

    private ClassLoader serviceClassLoader;

    private ClassLoader systemClassLoader;

    //To keep track of whether the system has started or not
    private boolean start;

    private ArrayList<TargetResolver> targetResolvers;

    private ClusteringAgent clusteringAgent;

    private AxisConfigurator configurator;

    private TransactionConfiguration transactionConfiguration;

    /**
     * Constructor AxisConfiguration.
     */
    public AxisConfiguration() {
        moduleConfigmap = new HashMap<String, ModuleConfiguration>();
        globalModuleList = new ArrayList<String>();
        messageReceivers = new HashMap<String, MessageReceiver>();
        messageBuilders = new HashMap<String, Builder>();
        messageFormatters = new HashMap<String, MessageFormatter>();
        outPhases = new ArrayList<Phase>();
        inFaultPhases = new ArrayList<Phase>();
        outFaultPhases = new ArrayList<Phase>();
        faultyServices = new Hashtable<String, String>();
        faultyModules = new Hashtable<String, String>();
        observerSet = new CopyOnWriteArraySet<AxisObserver>();
        inPhasesUptoAndIncludingPostDispatch = new ArrayList<Phase>();
        systemClassLoader = org.apache.axis2.java.security.AccessController
                .doPrivileged(new PrivilegedAction<ClassLoader>() {
                    public ClassLoader run() {
                        return Thread.currentThread().getContextClassLoader();
                    }
                });
        serviceClassLoader = systemClassLoader;
        moduleClassLoader = systemClassLoader;

        this.phasesinfo = new PhasesInfo();
        targetResolvers = new ArrayList<TargetResolver>();
    }

    public void addMessageReceiver(String mepURL,
                                   MessageReceiver messageReceiver) {
        messageReceivers.put(mepURL, messageReceiver);
    }

    /**
     * Register a messageBuilder implementation against a content type.
     * This is used by Axis2 to support different message formats.
     *
     * @param contentType    the relevant content-type (i.e. "text/xml")
     * @param messageBuilder a Builder implementation
     */
    public void addMessageBuilder(String contentType,
                                  Builder messageBuilder) {
        messageBuilders.put(contentType, messageBuilder);
    }

    /**
     * Register a messageFormatter implementation against a content type.
     * This is used by Axis2 to support serialization of messages to different
     * message formats. (Eg: JSON)
     *
     * @param contentType      the relevant content-type (i.e. "text/xml")
     * @param messageFormatter a MessageFormatter implementation
     */
    public void addMessageFormatter(String contentType,
                                    MessageFormatter messageFormatter) {
        messageFormatters.put(contentType, messageFormatter);
    }

    /**
     * Add an available Module to this configuration
     *
     * @param module an AxisModule
     * @throws AxisFault in case of error
     */
    public void addModule(AxisModule module) throws AxisFault {
        module.setParent(this);

        // check whether the module version paramter is there , if so set the module version as that
        Parameter versionParameter = module.getParameter(org.apache.axis2.Constants.MODULE_VERSION);
        if (versionParameter !=null ) {
            String version = (String) versionParameter.getValue();
            try {
                module.setVersion(new Version(version));
            } catch (ParseException ex) {
                throw new AxisFault("The version number '" + version + "' specified by the "
                        + org.apache.axis2.Constants.MODULE_VERSION + " parameter is invalid");
            }
        }

        allModules.put(module.getArchiveName(), module);
        notifyObservers(new AxisEvent(AxisEvent.MODULE_DEPLOY,null), module);

        // Registering the policy namespaces that the module understand
        registerModulePolicySupport(module);
        // Registering the policy assertions that are local to the system
        registerLocalPolicyAssertions(module);

    }

    public void deployModule(String moduleFileName) throws DeploymentException {
        File moduleFile = new File(moduleFileName);
        if (!moduleFile.exists()) {
            throw new DeploymentException("Module archive '" + moduleFileName + "' doesn't exist");
        }
        DeploymentFileData dfd = new DeploymentFileData(moduleFile, new ModuleDeployer(this));
        dfd.deploy();
    }

    /**
     * Remove a module with moduleName & moduleVersion
     *
     * @param moduleName the name of the module to remove
     * @param moduleVersion the version of the module to remove
     */
    public void removeModule(String moduleName, String moduleVersion) {
        allModules.remove(Utils.getModuleName(moduleName, moduleVersion));
        // TODO disengage has to be done here
    }

    /**
     * Remove a module with moduleName & moduleVersion
     *
     * @param moduleName the name of the module to remove
     * @param moduleVersion the version of the module to remove
     */
    public void removeModule(String moduleName, Version moduleVersion) {
        String version = null;
        if (moduleVersion != null) {
            version = moduleVersion.toString();
        }
        removeModule(moduleName, version);
    }

    /**
     * Adds module configuration, if there is a moduleConfig tag in service.
     *
     * @param moduleConfiguration a ModuleConfiguration to remember
     */
    public void addModuleConfig(ModuleConfiguration moduleConfiguration) {
        moduleConfigmap.put(moduleConfiguration.getModuleName(),
                            moduleConfiguration);
    }

    /**
     * Register given AxisObserver object to the {@link AxisConfiguration}.
     * 
     * @param axisObserver the axis observer
     */
    public void addObservers(AxisObserver axisObserver) {
        observerSet.add(axisObserver);
    }
    
    /**
     * Unregister the given AxisObserver object if it is registered with
     * the {@link AxisConfiguration}.
     * 
     * @param axisObserver the axis observer
     */
    public void removeObserver(AxisObserver axisObserver) {
        observerSet.remove(axisObserver);
    }

    /**
     * Add an AxisService to our global configuration.  Since services must
     * be in ServiceGroups, we construct an anonymous AxisServiceGroup around
     * the passed AxisService and then call addServiceGroup().
     *
     * @param service an AxisService to deploy.
     * @throws AxisFault if something goes wrong (invalid service, service is
     *                   already deployed, etc...)
     */
    public synchronized void addService(AxisService service) throws AxisFault {
        AxisServiceGroup axisServiceGroup = new AxisServiceGroup();
        axisServiceGroup.setServiceGroupName(service.getName());
        axisServiceGroup.setParent(this);
        axisServiceGroup.addService(service);
        addServiceGroup(axisServiceGroup);
//        processEndpoints(service, service.getAxisConfiguration());
    }

    public synchronized void addServiceGroup(AxisServiceGroup axisServiceGroup)
            throws AxisFault {
        axisServiceGroup.setParent(this);
        notifyObservers(new AxisEvent(AxisEvent.SERVICE_DEPLOY, axisServiceGroup), axisServiceGroup);
        AxisService axisService;

        Iterator<AxisService> services = axisServiceGroup.getServices();
        while (services.hasNext()) {
            axisService = services.next();
            if (axisService.getSchemaTargetNamespace() == null) {
                axisService.setSchemaTargetNamespace(Java2WSDLConstants.AXIS2_XSD);
            }
        }
        services = axisServiceGroup.getServices();
        while (services.hasNext()) {
            axisService = services.next();
            if (axisService.isUseDefaultChains()) {
                Iterator<AxisOperation> operations = axisService.getOperations();
                while (operations.hasNext()) {
                    AxisOperation operation = operations.next();
                    phasesinfo.setOperationPhases(operation);
                }
            }
        }
        Iterator<AxisModule> enModule = getEngagedModules().iterator();
        while (enModule.hasNext()) {
            axisServiceGroup.engageModule(enModule.next());
        }
        services = axisServiceGroup.getServices();
        ArrayList<AxisService> servicesIAdded = new ArrayList<AxisService>();
        while (services.hasNext()) {
            axisService = services.next();
            processEndpoints(axisService, axisService.getAxisConfiguration());

            Map<String, AxisEndpoint> endpoints = axisService.getEndpoints();
            String serviceName = axisService.getName();
            try {
                addToAllServicesMap(axisService);
            } catch (AxisFault axisFault) {
                // Whoops, must have been a duplicate!  If we had a problem here, we have to
                // remove all the ones we added...
                for (AxisService service : servicesIAdded) {
                    allServices.remove(service.getName());
                }
                // And toss this in case anyone wants it?
                throw axisFault;
            }
            servicesIAdded.add(axisService);
            if (endpoints != null) {
                Iterator<String> endpointNameIter = endpoints.keySet().iterator();
                while (endpointNameIter.hasNext()) {
                    String endpointName = endpointNameIter.next();
                    if (log.isDebugEnabled()) {
                        log.debug("Adding service to allEndpoints map: ("
                                  + serviceName + "," + endpointName + ") ");
                    }

                    allEndpoints.put(serviceName + "." + endpointName, axisService);
                }
                if (log.isDebugEnabled()) {
                    log.debug("After adding to allEndpoints map, size is "
                              + allEndpoints.size());
                }
            }

            if (!axisService.isClientSide()) {
                notifyObservers(new AxisEvent(AxisEvent.SERVICE_DEPLOY ,axisService ), axisService);
            }
        }
        // serviceGroups.put(axisServiceGroup.getServiceGroupName(),
        // axisServiceGroup);
        addChild(axisServiceGroup);
    }

    /**
     * This method is used to add a service to an existing active service group in the axis configuration
     *
     * @param axisService service to be added to the existing service group provided
     * @param serviceGroupName name of the service group which should be existing in the axis configuration
     * @throws AxisFault in case of an error in adding the service to the group specified or if the group is not existing
     */
    public void addServiceToExistingServiceGroup(AxisService axisService,
                                                 String serviceGroupName) throws AxisFault {

        AxisServiceGroup serviceGroup = getServiceGroup(serviceGroupName);
        if (serviceGroup == null) {
            String message = "A ServiceGroup with the provided name "
                    + serviceGroupName + " is not existing";
            log.error(message);
            throw new AxisFault(message);
        }

        if (axisService.getSchemaTargetNamespace() == null) {
            axisService.setSchemaTargetNamespace(Java2WSDLConstants.AXIS2_XSD);
        }

        if (axisService.isUseDefaultChains()) {
            Iterator<AxisOperation> operations = axisService.getOperations();
            while (operations.hasNext()) {
                AxisOperation operation = operations.next();
                phasesinfo.setOperationPhases(operation);
            }
        }

        Map<String, AxisEndpoint> endpoints = axisService.getEndpoints();
        if (endpoints == null || endpoints.size() == 0) {
            org.apache.axis2.deployment.util.Utils.addEndpointsToService(
                    axisService, axisService.getAxisConfiguration());
            endpoints = axisService.getEndpoints();
        }

        String serviceName = axisService.getName();
        addToAllServicesMap(axisService);

        if (endpoints != null) {
            Iterator<String> endpointNameIter = endpoints.keySet().iterator();
            while (endpointNameIter.hasNext()) {
                String endpointName = endpointNameIter.next();
                if (log.isDebugEnabled()) {
                    log.debug("Adding service to allEndpoints map: ("
                            + serviceName + "," + endpointName + ") ");
                }

                allEndpoints.put(serviceName + "." + endpointName, axisService);
            }
            if (log.isDebugEnabled()) {
                log.debug("After adding to allEndpoints map, size is "
                        + allEndpoints.size());
            }
        }
        
        serviceGroup.addService(axisService);

        if (!axisService.isClientSide()) {
            notifyObservers(new AxisEvent(AxisEvent.SERVICE_DEPLOY, axisService), axisService);
        }
    }

    public void addToAllServicesMap(AxisService axisService) throws AxisFault {
        String serviceName = axisService.getName();
        AxisService oldService = allServices.get(serviceName);
        if (oldService == null) {
            if (log.isDebugEnabled()) {
                log.debug("Adding service to allServices map: [" + serviceName + "] ");
            }
            allServices.put(serviceName, axisService);
            if (log.isTraceEnabled()) {
                //noinspection ThrowableInstanceNeverThrown
                log.trace("After adding to allServices map, size is "
                          + allServices.size() + " call stack is " + 
                          JavaUtils.stackToString(new Exception()));
            }

        } else {
            // If we were already there, that's fine.  If not, fault!
            if (oldService != axisService) {
                throw new AxisFault(Messages.getMessage("twoservicecannothavesamename",
                                                        axisService.getName() +
                                                        " [" + axisService.getFileName() + "]"));
            }
        }
    }

    public AxisServiceGroup removeServiceGroup(String serviceGroupName) throws AxisFault {
        AxisServiceGroup axisServiceGroup = (AxisServiceGroup) getChild(serviceGroupName);
        if (axisServiceGroup == null) {
            throw new AxisFault(Messages.getMessage("invalidservicegroupname",
                                                    serviceGroupName));
        }

        Iterator<AxisService> services = axisServiceGroup.getServices();
        boolean isClientSide = false;
        while (services.hasNext()) {
            AxisService axisService = services.next();           
            isClientSide = axisService.isClientSide()? true : false;

            //removes the endpoints to this service         
            removeServiceReferences(axisService.getName());    

        }
        removeChild(serviceGroupName);
        if (!isClientSide) {
            notifyObservers(new AxisEvent(AxisEvent.SERVICE_REMOVE, axisServiceGroup), axisServiceGroup);
        }

        return axisServiceGroup;
    }

    /**
     * Add an incoming transport description (i.e. receiver) to our configuration.
     *
     * @param transport TransportInDescription to add.
     * @throws AxisFault
     */
    public void addTransportIn(TransportInDescription transport) throws AxisFault {
        if (transport.getReceiver() == null) {
            throw new AxisFault(
                    "Transport Receiver can not be null for the transport "
                    + transport.getName());
        }
        transportsIn.put(transport.getName(), transport);
    }

    /**
     * Add an outgoing transport description (i.e. sender) to our configuration.
     *
     * @param transport TransportOutDescription to add.
     * @throws AxisFault
     */
    public void addTransportOut(TransportOutDescription transport)
            throws AxisFault {
        if (transport.getSender() == null) {
            throw new AxisFault(
                    "Transport sender can not be null for the transport "
                    + transport.getName());
        }
        transportsOut.put(transport.getName(), transport);
    }

    /**
     * Engages the default module version corresponding to given module name ,
     * or if the module name contains version number in it then it will engage
     * the correct module. Both of the below two cases are valid 1.
     * engageModule("addressing"); 2. engageModule("addressing-1.23");
     *
     * @param moduleref name of module to engage
     * @throws AxisFault
     */
    public void engageModule(String moduleref) throws AxisFault {
        AxisModule module = getModule(moduleref);
        if (module != null) {
            engageModule(module);
        } else {
            throw new AxisFault(Messages.getMessage("modulenotavailble", moduleref));
        }
    }

    /**
     * Engages a module using given name and its version ID.
     *
     * @param moduleName name of module to engage
     * @param versionID version of module to engage
     * @throws AxisFault
     */
    public void engageModule(String moduleName, String versionID)
            throws AxisFault {
        String actualName = Utils.getModuleName(moduleName, versionID);
        AxisModule module = getModule(actualName);
        if (module != null) {
            engageModule(module);
        } else {
            // TODO : Should this be an NPE or InvalidArgumentException?
            throw new AxisFault(Messages.getMessage("refertoinvalidmodule"));
        }
    }

    public void onEngage(AxisModule module, AxisDescription engager) throws AxisFault {
        Iterator<AxisServiceGroup> servicegroups = getServiceGroups();
        while (servicegroups.hasNext()) {
            AxisServiceGroup serviceGroup = servicegroups.next();
            serviceGroup.engageModule(module, engager);
        }
    }

    /**
     * To dis-engage a module from the system. This will remove all the handlers
     * belonging to this module from all the handler chains.
     *
     * @param module module to disengage
     */
    public void onDisengage(AxisModule module) throws AxisFault {
        PhaseResolver phaseResolver = new PhaseResolver(this);
        phaseResolver.disengageModuleFromGlobalChains(module);

        Iterator<AxisServiceGroup> serviceGroups = getServiceGroups();
        while (serviceGroups.hasNext()) {
            AxisServiceGroup axisServiceGroup = serviceGroups.next();
            axisServiceGroup.disengageModule(module);
        }
    }

    public void notifyObservers(AxisEvent event, AxisService service) {
        if (service.isClientSide())
            return;

        for (AxisObserver observer : observerSet) {
            try {
                observer.serviceUpdate(event, service);
            } catch (Throwable e) {
                // No need to stop the system due to this, so log an error and ignore
                log.error("Error occured while notifying observer", e);
            }
        }
    }

    public void notifyObservers(AxisEvent event, AxisModule moule) {

        for (AxisObserver anObserversList : observerSet) {

            try {
                anObserversList.moduleUpdate(event, moule);
            } catch (Throwable e) {
                // No need to stop the system due to this, so log an error and ignore
                log.error("Error occured while notifying observer", e);
            }
        }
    }

    public void notifyObservers(AxisEvent event, AxisServiceGroup serviceGroup) {

        for (AxisObserver anObserversList : observerSet) {

            try {
                anObserversList.serviceGroupUpdate(event, serviceGroup);
            } catch (Throwable e) {
                // No need to stop the system due to this, so log an error and ignore
                log.error("Error occured while notifying observer", e);
            }
        }
    }

    /**
     * Remove a service.
     *
     * @param name name of service to remove
     * @throws AxisFault
     */
    public synchronized void removeService(String name) throws AxisFault {
        AxisService service = removeServiceReferences(name);
        if (service != null) {
            AxisServiceGroup serviceGroup = service.getAxisServiceGroup();
            serviceGroup.removeService(name);
            log.debug(Messages.getMessage("serviceremoved", name));
        }
    }

    /**
     * Add an AxisModule to the list of globally deployed modules.
     * <p/>
     * TODO: should this check for duplicate names?
     *
     * @param moduleName name of AxisModule to add to list.
     */
    public void addGlobalModuleRef(String moduleName) {
        globalModuleList.add(moduleName);
    }

    /**
     * Engage all the previously added global modules.
     *
     * @throws AxisFault if an individual engageModule() fails
     */
    public void engageGlobalModules() throws AxisFault {
        for (String aGlobalModuleList : globalModuleList) {
            engageModule(aGlobalModuleList);
        }
    }

    public Hashtable<String, String> getFaultyModules() {
        return faultyModules;
    }

    public Hashtable<String, String> getFaultyServices() {
        return faultyServices;
    }

    /**
     * Updates the map that keeps track of faulty services due to modules
     * @param moduleName This service has become faulty due this module.
     * @param faultyServiceData  Data that are required when recovering the faulty service.
     */
    public void addFaultyServiceDuetoModule(String moduleName, FaultyServiceData faultyServiceData) {
        Map<String, FaultyServiceData> faultyServicesMap;

        synchronized (faultyServicesDueToModules) {

            if (faultyServicesDueToModules.containsKey(moduleName)) {
                faultyServicesMap = faultyServicesDueToModules.get(moduleName);
                faultyServicesMap.put(faultyServiceData.getServiceGroupName(), faultyServiceData);

            } else {
                faultyServicesMap = new HashMap<String, FaultyServiceData>();
                faultyServicesMap.put(faultyServiceData.getServiceGroupName(), faultyServiceData);
                faultyServicesDueToModules.put(moduleName, faultyServicesMap);
            }

            //Adding the faulty service to default service map
            String serviceStatus = "Error:\n" + "Engaged module not found :" + moduleName;

            String serviceLocation = null;
            if(faultyServiceData.getCurrentDeploymentFile() != null){
                serviceLocation = faultyServiceData.getCurrentDeploymentFile().getFile().getAbsolutePath();
            }

            if(serviceLocation == null){
                serviceLocation = faultyServiceData.getServiceGroupName();
            }
            faultyServices.put(serviceLocation, serviceStatus);
        }
    }

    /**
     * Returns a map which contains the faulty services due a particular module.
     *
     * @param moduleName name of the module about which to inquire
     * @return a Map&lt;String, FaultyServiceData&gt; mapping service name to data
     */
    public Map<String, FaultyServiceData> getFaultyServicesDuetoModule(String moduleName) {
        if (faultyServicesDueToModules.containsKey(moduleName)) {
            return faultyServicesDueToModules.get(moduleName);

        }
        return new HashMap<String, FaultyServiceData>(1);
    }

    /**
     * Returns the map which keeps track of faulty services due to modules.
     * @return a Map keyed by module name, containing Maps keyed by service name containing
     *         FaultyServiceData for each faulty service.
     */
    public Map<String, Map<String, FaultyServiceData>> getFaultyServicesDuetoModules(){
        return faultyServicesDueToModules;
    }

    /**
     * Removes a faulty service for a given module from the internal map.
     *
     * TODO: Doesn't this actually remove a faulty service *group*? And should this even be public?
     * 
     * @param moduleName name of the module to look up
     * @param serviceGroupName name of the service group to remove
     */
    public void removeFaultyServiceDuetoModule(String moduleName, String serviceGroupName) {
        synchronized (faultyServicesDueToModules) {
            Map<String, FaultyServiceData> faultyServicesDueToModule = faultyServicesDueToModules.get(moduleName);
            FaultyServiceData faultyServiceData = faultyServicesDueToModule.get(serviceGroupName);

            if (faultyServicesDueToModule != null) {
                faultyServicesDueToModule.remove(serviceGroupName);

                //Removing from the default faulty services map.
                String serviceLocation = null;
                if (faultyServiceData.getCurrentDeploymentFile() != null) {
                    serviceLocation = faultyServiceData.getCurrentDeploymentFile().getFile().getAbsolutePath();
                }

                if (serviceLocation == null) {
                    serviceLocation = faultyServiceData.getServiceGroupName();
                }
                faultyServices.remove(serviceLocation);

                if (faultyServicesDueToModule.isEmpty()) {
                    faultyServicesDueToModules.remove(moduleName);
                }
            }
        }
    }

    public void removeFaultyService(String key) {
        Iterator<String> itr = faultyServices.keySet().iterator();
        while (itr.hasNext()) {
            String fullFileName = itr.next();
            if (fullFileName.indexOf(key) >= 0) {
                faultyServices.remove(fullFileName);
                return;
            }
        }
    }

    // to get the out flow correpodning to the global out flow;
    public List<Phase> getOutFlowPhases() {
        return this.outPhases;
    }

    /**
     * @return Returns ArrayList.
     */
    public List<Phase> getInFaultFlowPhases() {
        return inFaultPhases;
    }

    public List<Phase> getInFlowPhases() {
        return inPhasesUptoAndIncludingPostDispatch;
    }

    public MessageReceiver getMessageReceiver(String mepURL) {
        return messageReceivers.get(mepURL);
    }

    /**
     * Get a Builder for a particular content type.
     *
     * @param contentType the desired content type
     * @return the configured message builder implementation class name against
     *         the given content type.
     */
    public Builder getMessageBuilder(String contentType) {
        Builder builder = null;
        if (messageBuilders.isEmpty()) {
            return null;
        }
        if (contentType != null) {
            builder = messageBuilders.get(contentType);
            if (builder == null) {
                builder = messageBuilders.get(contentType.toLowerCase());
            }
            if (builder == null) {
                Iterator<Entry<String, Builder>> iterator = messageBuilders.entrySet().iterator();
                while (iterator.hasNext() && builder == null) {
                    Entry<String, Builder> entry = iterator.next();
                    String key = entry.getKey();
                    if (contentType.matches(key)) {
                        builder = entry.getValue();
                    }
                }
            }
        }
        return builder;
    }

    public Builder getMessageBuilder(String contentType, boolean defaultBuilder) {
        Builder builder = getMessageBuilder(contentType);
        if (builder == null && defaultBuilder){
            builder = new UnknownContentBuilder();
        }
        return builder;
    }

    /**
     * Get a MessageFormatter for the specified content type.
     *
     * @param contentType content type to look up
     * @return a MessageFormatter corresponding to the given content type, or null.
     */
    public MessageFormatter getMessageFormatter(String contentType) {
        return messageFormatters.get(contentType);
    }

//    /**
//     *
//     * @deprecate Please use String version instead
//     * @param qname
//     * @return
//     */
//    public AxisModule getModule(QName qname) {
//        return getModule(qname.getLocalPart());
//    }

    /**
     * Get an AxisModule by name.
     *
     * If the exact name passed (which might contain a version) is present, we'll return that,
     * otherwise we'll look for the default version *if* there is no version in the passed
     * name.
     *
     * @param name module name to look up
     * @return an AxisModule if found, or null
     */
    public AxisModule getModule(String name) {
        AxisModule module = allModules.get(name);
        if (module != null) {
            return module;
        }
        // checks whether the version string seperator is not there in the
        // module name
        String defaultModuleVersion = getDefaultModuleVersion(name);
        if (defaultModuleVersion != null) {
            module = allModules.get(Utils.getModuleName(name, defaultModuleVersion));
            if (module != null) {
                return module;
            }
        }
        return null;
    }

    /**
     * Return the module having name=moduleName & version=moduleVersion
     *
     * @param moduleName    The module name
     * @param moduleVersion The version of the module
     * @return The AxisModule having name=moduleName & version=moduleVersion
     */
    public AxisModule getModule(String moduleName, String moduleVersion) {
        if (moduleVersion == null || moduleVersion.trim().length() == 0) {
            moduleVersion = getDefaultModuleVersion(moduleName);
        }
        return allModules.get(Utils.getModuleName(moduleName, moduleVersion));
    }

    /**
     * Get the class loader that becomes the parent of all the modules
     *
     * @return a ClassLoader
     */
    public ClassLoader getModuleClassLoader() {
        return this.moduleClassLoader;
    }

    public ModuleConfiguration getModuleConfig(String moduleName) {
        return moduleConfigmap.get(moduleName);
    }

    /**
     * @return Returns HashMap.
     */
    public HashMap<String, AxisModule> getModules() {
        return allModules;
    }   

    /**
     * @return Returns ArrayList.
     */
    public List<Phase> getOutFaultFlowPhases() {
        return outFaultPhases;
    }

    public PhasesInfo getPhasesInfo() {
        return phasesinfo;
    }

    public URL getRepository() {
        return axis2Repository;
    }

    /**
     * Method getService.
     *
     * @param name the name of the service to look up
     * @return an AxisService if found, or null
     */
    public AxisService getService(String name) throws AxisFault {
        AxisService axisService = allServices.get(name);
        if (axisService != null) {
            if (axisService.isActive()) {
                return axisService;
            } else {
                throw new AxisFault(Messages
                        .getMessage("serviceinactive", name));
            }
        } else {
            axisService = allEndpoints.get(name);
            if (axisService != null) {
                if (axisService.isActive()) {
                    return axisService;
                } else {
                    throw new AxisFault(Messages
                            .getMessage("serviceinactive", name));
                }
            }
        }
        return null;
    }

    /**
     * Service can start and stop, once stopped it cannot be accessed, so we
     * need a way to get the service even if service is not active.
     *
     * @param serviceName name to look up
     * @return AxisService
     */
    public AxisService getServiceForActivation(String serviceName) {
        AxisService axisService;
        axisService = allServices.get(serviceName);
        if (axisService != null) {
            return axisService;
        } else {
            axisService = allEndpoints.get(serviceName);
            return axisService;
        }
    }

    // The class loader that becomes the parent of all the services
    public ClassLoader getServiceClassLoader() {
        return this.serviceClassLoader;
    }

    public AxisServiceGroup getServiceGroup(String serviceNameAndGroupString) {
        // return (AxisServiceGroup)
        // serviceGroups.get(serviceNameAndGroupString);
        return (AxisServiceGroup) getChild(serviceNameAndGroupString);
    }

    public Iterator<AxisServiceGroup> getServiceGroups() {
        // return serviceGroups.values().iterator();
        return (Iterator<AxisServiceGroup>) getChildren();
    }

    // To get all the services in the system
    public HashMap<String, AxisService> getServices() {
        HashMap<String, AxisService> hashMap = new HashMap<String, AxisService>(this.allServices.size());
        String key;
        for (String s : this.allServices.keySet()) {
            key = s;
            hashMap.put(key, this.allServices.get(key));
        }
        return hashMap;
    }

    // The class loader which become the top most parent of all the modules and
    // services
    public ClassLoader getSystemClassLoader() {
        return this.systemClassLoader;
    }

    public TransportInDescription getTransportIn(String name) {
        return transportsIn.get(name);
    }

    public TransportOutDescription getTransportOut(String name) {
        return transportsOut.get(name);
    }

    public HashMap<String, TransportInDescription> getTransportsIn() {
        return transportsIn;
    }

    public HashMap<String, TransportOutDescription> getTransportsOut() {
        return transportsOut;
    }
    
    public boolean isEngaged(String moduleId) {
        AxisModule module = getModule(moduleId);
        if (module == null) {
            return false;
        }
        boolean isEngaged = super.isEngaged(module);
        if (!isEngaged) {
            AxisModule defaultModule = getDefaultModule(moduleId);
            isEngaged = engagedModules != null && engagedModules.values().contains(defaultModule);
        }
        return isEngaged;
    }

    public boolean isEngaged(AxisModule axisModule) {
        boolean isEngaged = super.isEngaged(axisModule);
        if (!isEngaged) {
            isEngaged = engagedModules != null &&
                        engagedModules.values().contains(axisModule);
        }
        return isEngaged;
    }

    public void setGlobalOutPhase(List<Phase> outPhases) {
        this.outPhases = outPhases;
    }

    /**
     * Set the inbound fault phases
     *
     * TODO: Passing mutable lists like this and using them directly is bad practice.
     *
     * @param list a List of Phases which will become our inbound fault flow
     */
    public void setInFaultPhases(List<Phase> list) {
        inFaultPhases = list;
    }

    public void setInPhasesUptoAndIncludingPostDispatch(
            List<Phase> inPhasesUptoAndIncludingPostDispatch) {
        this.inPhasesUptoAndIncludingPostDispatch = inPhasesUptoAndIncludingPostDispatch;
    }

    public void setModuleClassLoader(ClassLoader classLoader) {
        this.moduleClassLoader = classLoader;
    }

    /**
     * Set the outbound fault phases
     *
     * TODO: Passing mutable lists like this and using them directly is bad practice.
     *
     * @param list a List of Phases which will become our outbound fault flow
     */
    public void setOutFaultPhases(List<Phase> list) {
        outFaultPhases = list;
    }

    public void setPhasesInfo(PhasesInfo phasesInfo) {
        this.phasesinfo = phasesInfo;
    }

    public void setRepository(URL axis2Repository) {
        this.axis2Repository = axis2Repository;
    }

    public void setServiceClassLoader(ClassLoader classLoader) {
        this.serviceClassLoader = classLoader;
    }

    public void setSystemClassLoader(ClassLoader classLoader) {
        this.systemClassLoader = classLoader;
    }

    /**
     * Adds a default module version, which can be done either programmatically
     * or by using axis2.xml. The default module version is important if user
     * asks to engage a module without given version ID, in which case,
     * the default version is engaged.
     *
     * TODO: This currently does NOTHING if a default has already been set. Should either overwrite or throw.
     *
     * @param moduleName the name of the module for which we're setting the default version
     * @param moduleVersion the default version
     */
    public void addDefaultModuleVersion(String moduleName, String moduleVersion) {
        if (nameToversionMap.get(moduleName) == null) {
            nameToversionMap.put(moduleName, moduleVersion);
        }
    }

    public String getDefaultModuleVersion(String moduleName) {
        return nameToversionMap.get(moduleName);
    }

    public AxisModule getDefaultModule(String moduleName) {
        String defaultModuleVersion = getDefaultModuleVersion(moduleName);
        if (defaultModuleVersion == null) {
            return allModules.get(moduleName);
        } else {
            return allModules.get(moduleName + "-" + defaultModuleVersion);
        }
    }

    public ClusteringAgent getClusteringAgent() {
        return clusteringAgent;
    }

    public void setClusteringAgent(ClusteringAgent clusteringAgent) {
        this.clusteringAgent = clusteringAgent;
    }

     public TransactionConfiguration getTransactionConfiguration() {
        return transactionConfiguration;
    }

    public void setTransactionConfig(TransactionConfiguration transactionConfiguration) {
        this.transactionConfiguration = transactionConfiguration;
    }

    public Object getKey() {
        return toString();
    }

    public void stopService(String serviceName) throws AxisFault {
        AxisService service = allServices.get(serviceName);
        if (service == null) {
            throw new AxisFault(Messages.getMessage("servicenamenotvalid",
                                                    serviceName));
        }
        service.setActive(false);
        notifyObservers(new AxisEvent(AxisEvent.SERVICE_STOP , service), service);
    }

    public void startService(String serviceName) throws AxisFault {
        AxisService service = allServices.get(serviceName);
        if (service == null) {
            throw new AxisFault(Messages.getMessage("servicenamenotvalid",
                                                    serviceName));
        }
        service.setActive(true);
        notifyObservers(new AxisEvent(AxisEvent.SERVICE_START , service), service);
    }

    public List<AxisModule> getModulesForPolicyNamesapce(String namesapce) {
        return policySupportedModules.get(namesapce);
    }

    public void registerModulePolicySupport(AxisModule axisModule) {
        String[] namespaces = axisModule.getSupportedPolicyNamespaces();

        if (namespaces == null) {
            return;
        }

        List<AxisModule> modulesList;

        for (String namespace : namespaces) {
            modulesList = policySupportedModules.get(namespace);

            if (modulesList != null) {
                modulesList.add(axisModule);
            } else {
                modulesList = new ArrayList<AxisModule>();
                modulesList.add(axisModule);
                policySupportedModules.put(namespace, modulesList);
            }
        }
    }

    public void registerLocalPolicyAssertions(AxisModule axisModule) {
        QName[] localPolicyAssertions = axisModule.getLocalPolicyAssertions();

        if (localPolicyAssertions == null) {
            return;
        }

        for (QName localPolicyAssertion : localPolicyAssertions) {
            addLocalPolicyAssertion(localPolicyAssertion);
        }
    }

    /**
     * This method returns read-only list of AxisObservers registered with this
     * {@link AxisConfiguration}.
     * 
     * @return ArrayList<AxisObserver>
     */
    public ArrayList<AxisObserver> getObserversList() {
        AxisObserver[] array = observerSet.toArray(new AxisObserver[observerSet.size()]);
        ArrayList<AxisObserver> observers = new ArrayList<AxisObserver>(array.length);
        observers.addAll(Arrays.asList(array));
        return observers;
    }

    public boolean isStart() {
        return start;
    }

    public void setStart(boolean start) {
        this.start = start;
    }

    /**
     * getTargetResolverChain returns an instance of
     * TargetResolver which iterates over the registered
     * TargetResolvers, calling each one in turn when
     * resolveTarget is called.
     *
     * @return a TargetResolver which iterates over all registered TargetResolvers.
     */
    public TargetResolver getTargetResolverChain() {
        if (targetResolvers.isEmpty()) {
            return null;
        }
        return new TargetResolver() {
            public void resolveTarget(MessageContext messageContext) {
                Iterator<TargetResolver> iter = targetResolvers.iterator();
                while (iter.hasNext()) {
                    TargetResolver tr = iter.next();
                    tr.resolveTarget(messageContext);
                }
            }
        };
    }

    public void addTargetResolver(TargetResolver tr) {
        targetResolvers.add(tr);
    }

    public void addLocalPolicyAssertion(QName name) {
        this.localPolicyAssertions.add(name);
    }

    public List<QName> getLocalPolicyAssertions() {
        return this.localPolicyAssertions;
    }

    public void removeLocalPolicyAssertion(QName name) {
        this.localPolicyAssertions.remove(name);
    }

    public boolean isAssertionLocal(QName name) {
        return this.localPolicyAssertions.contains(name);
    }

    /**
     * Allows to define/configure Data Locator for specified dialect at Axis 2 Configuration.
     *
     * @param dialect-  an absolute URI represents the format and version of data
     * @param classname - class name of the Data Locator configured to support retrieval
     *                  for the specified dialect.
     */
    public void addDataLocatorClassNames(String dialect, String classname) {
        dataLocatorClassNames.put(dialect, classname);
    }

    /**
     * For internal used only! To store instance of DataLocator when it is first loaded. This allows to
     * reuse of the DataLocator after it is initially loaded.
     *
     * @param dialect-    an absolute URI represents the format and version of data
     * @param dataLocator - specified an DataLocator instance  to support retrieval
     *                    of the specified dialect.
     */
    public void addDataLocator(String dialect, AxisDataLocator dataLocator) {
        dataLocators.put(dialect, dataLocator);
    }

    /**
     * Return DataLocator instance for specified dialect.
     * @param dialect the dialect to look up
     * @return an AxisDataLocator, or null
     */
    public AxisDataLocator getDataLocator(String dialect) {
        return dataLocators.get(dialect);
    }


    /**
     * Return classname of DataLocator configured for specified dialect.
     * @param dialect the dialect to look up
     * @return a String containing a class name, or null
     */
    public String getDataLocatorClassName(String dialect) {
        return dataLocatorClassNames.get(dialect);
    }


    /**
     * Checks whether the system pre-defined phases
     * for all the flows, have been changed. If they have been changed, throws a DeploymentException.
     *
     * @throws org.apache.axis2.deployment.DeploymentException
     *
     */
    public void validateSystemPredefinedPhases() throws DeploymentException {
        PhasesInfo phasesInfo = getPhasesInfo();
        setInPhasesUptoAndIncludingPostDispatch(phasesInfo.getGlobalInflow());
        setInFaultPhases(phasesInfo.getGlobalInFaultPhases());
        setGlobalOutPhase(phasesInfo.getGlobalOutPhaseList());
        setOutFaultPhases(phasesInfo.getOUT_FaultPhases());
    }

    public AxisConfigurator getConfigurator() {
        return configurator;
    }

    public void setConfigurator(AxisConfigurator configurator) {
        this.configurator = configurator;
    }

    public void cleanup() {
        if (configurator != null) {
            configurator.cleanup();
        }
        if (clusteringAgent != null) {
            clusteringAgent.finalize();
        }
        this.policySupportedModules.clear();
        this.moduleConfigmap.clear();
        this.allEndpoints.clear();
        this.allModules.clear();
        this.allServices.clear();
        this.outPhases.clear();
        this.messageReceivers.clear();
        this.targetResolvers.clear();
        if (this.engagedModules != null) {
            this.engagedModules.clear();
        }
        this.configurator = null;
    }

    /**
     * This method can be used to insert a phase at the runtime for a given location
     * And the relative location can be specified by beforePhase and afterPhase. Parameters
     * Either or both of them can be null , if both the parameters are null then the phase
     * will be added some where in the global phase. If one of them are null then the phase
     * will be added
     *  - If the beforePhase is null then the phase will be added after the afterPhase
     *  - If the after phase is null then the phase will be added before the beforePhase
     * Type of the flow will be specified by the parameter flow.
     *   1 - Inflow
     *   2 - out flow
     *   3 - fault in flow
     *   4 - fault out flow
     *
     * @param d the Deployable representing the Phase to deploy
     * @param flow the type of the flow
     * @throws org.apache.axis2.AxisFault : If something went wrong
     */
    public void insertPhase(Deployable d, int flow) throws AxisFault {

        switch (flow) {
            case PhaseMetadata.IN_FLOW : {
                List<Phase> phaseList = phasesinfo.getINPhases();
                phaseList = findAndInsertPhase(d, phaseList);
                if (phaseList != null) {
                    phasesinfo.setINPhases(phaseList);
                }
                break;
            }
            case PhaseMetadata.OUT_FLOW : {
                List<Phase> phaseList = phasesinfo.getOUTPhases();
                phaseList = findAndInsertPhase(d, phaseList);
                if (phaseList != null) {
                    phasesinfo.setOUTPhases(phaseList);
                }
                break;
            }
            case PhaseMetadata.FAULT_OUT_FLOW : {
                List<Phase> phaseList = phasesinfo.getOutFaultPhaseList();
                phaseList = findAndInsertPhase(d, phaseList);
                if (phaseList != null) {
                    phasesinfo.setOUT_FaultPhases(phaseList);
                }
                break;
            }
            case PhaseMetadata.FAULT_IN_FLOW : {
                List<Phase> phaseList = phasesinfo.getIN_FaultPhases();
                phaseList = findAndInsertPhase(d, phaseList);
                if (phaseList != null) {
                    phasesinfo.setIN_FaultPhases(phaseList);
                }
                break;
            }
        }
    }

    /**
     * Insert a Phase into a list of Phases
     *
     * @param d a Deployable containing the Phase to insert
     * @param phaseList a list of Phases
     * @return a new List of Phases with the new one correctly deployed.
     * @throws AxisFault
     */
    private List<Phase> findAndInsertPhase(Deployable d, List<Phase> phaseList) throws AxisFault {
        DeployableChain<Phase> ec = new DeployableChain<Phase>();
        String last = null;
        for (Phase phase : phaseList) {
            String name = phase.getName();
            Deployable existing = new Deployable(name);
            existing.setTarget(phase);
            if (last != null) {
                // Set up explicit chain relationship for preexisting phases, for now.
                ec.addRelationship(last, name);
            }
            last = name;
            try {
                ec.deploy(existing);
            } catch (Exception e) {
                // This should never happen when building a simple list like the above
                throw AxisFault.makeFault(e);
            }
        }

        try {
            ec.deploy(d);

            if (d.getTarget() == null) {
                Phase phase = new Phase();
                phase.setName(d.getName());
                d.setTarget(phase);
            }

            ec.rebuild();
        } catch (Exception e) {
            throw AxisFault.makeFault(e);
        }

        phaseList = ec.getChain();

        return phaseList;
    }
    
    private void processEndpoints(AxisService axisService,
            AxisConfiguration axisConfiguration) throws AxisFault {
        Map<String, AxisEndpoint> enspoints = axisService.getEndpoints();
        if (enspoints == null || enspoints.size() == 0) {
            org.apache.axis2.deployment.util.Utils.addEndpointsToService(
                    axisService, axisConfiguration);
        }
    }

    public boolean isChildFirstClassLoading(){
        boolean childFirstClassLoading = false;
        Parameter isChildFirstClassLoading = this.getParameter(Constants.Configuration.ENABLE_CHILD_FIRST_CLASS_LOADING);
        if (isChildFirstClassLoading != null){
             childFirstClassLoading = JavaUtils.isTrueExplicitly(isChildFirstClassLoading.getValue());
        }
        return childFirstClassLoading;
    }
    
    private AxisService removeServiceReferences(String serviceName) {

        AxisService axisService = allServices.remove(serviceName);
        if (axisService != null) {
            if (!axisService.isClientSide()) {
                notifyObservers(new AxisEvent(AxisEvent.SERVICE_REMOVE,
                        axisService), axisService);
            }

            // removes the endpoints to this service
            for (Iterator<String> iter = axisService.getEndpoints().keySet()
                    .iterator(); iter.hasNext();) {
                String key = serviceName + "." + iter.next();
                this.allEndpoints.remove(key);
            }
        }
        return axisService;
    }
    
    public boolean isGlobalModulesRegistered(String moduleName) {
        if (globalModuleList.contains(moduleName)) {
            return true;
        }
        return false;
    }
}
