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

import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.AddressingHelper;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.ServiceContext;
import org.apache.axis2.dataretrieval.*;
import org.apache.axis2.deployment.DeploymentConstants;
import org.apache.axis2.deployment.util.ExcludeInfo;
import org.apache.axis2.deployment.util.PhasesInfo;
import org.apache.axis2.deployment.util.Utils;
import org.apache.axis2.description.java2wsdl.*;
import org.apache.axis2.engine.*;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.phaseresolver.PhaseResolver;
import org.apache.axis2.transport.TransportListener;
import org.apache.axis2.util.*;
import org.apache.axis2.util.XMLUtils;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.neethi.Policy;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.apache.ws.commons.schema.XmlSchemaExternal;
import org.apache.ws.commons.schema.XmlSchemaObjectCollection;
import org.apache.ws.commons.schema.utils.NamespaceMap;
import org.apache.ws.commons.schema.utils.NamespacePrefixList;
import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.wsdl.*;
import javax.wsdl.extensions.http.HTTPAddress;
import javax.wsdl.extensions.schema.Schema;
import javax.wsdl.extensions.soap.SOAPAddress;
import javax.wsdl.extensions.soap12.SOAP12Address;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.wsdl.xml.WSDLWriter;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.lang.reflect.Method;
import java.net.SocketException;
import java.net.URL;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

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

	// ////////////////////////////////////////////////////////////////
	// Standard Parameter names

	/**
	 * If this param is true, and the service has exactly one AxisOperation,
	 * normal operation dispatch (via URI/soapAction/etc) will not be necessary,
	 * and we'll just default to funneling all messages to that op. This is
	 * useful for passthrough/ESB/embedded applications.
	 */
	public static final String SUPPORT_SINGLE_OP = "supportSingleOperation";
	// ////////////////////////////////////////////////////////////////

	public static final String IMPORT_TAG = "import";
	public static final String INCLUDE_TAG = "include";
	public static final String SCHEMA_LOCATION = "schemaLocation";

	private Map<String, AxisEndpoint> endpointMap = new HashMap<String, AxisEndpoint>();

	/*
	 * This is a map between the QName of the element of a message specified in
	 * the WSDL and an Operation. It enables SOAP Body-based dispatching for
	 * doc-literal bindings.
	 */
	private Map<QName, AxisOperation> messageElementQNameToOperationMap = new HashMap<QName, AxisOperation>();

	private int nsCount = 0;
	private static final Log log = LogFactory.getLog(AxisService.class);
	private URL fileName;

	// Maps httpLocations to corresponding operations. Used to dispatch rest
	// messages.
	private HashMap<String, AxisOperation> httpLocationDispatcherMap = null;

	// A map of (String alias, AxisOperation operation). The aliases might
	// include: SOAPAction,
	// WS-Addressing action, the operation name, the AxisInputMessage name. See:
	// - invalidOperationsAliases
	// - mapActionToOperatoin()
	// - getOperationByAction()
	// REVIEW: This really should be seperate maps for the different types of
	// aliases so they don't
	// conflict with each other. For example, so that an identical operation
	// name and soap action
	// on different operatoins don't cause a collision; the following can't be
	// routed because
	// "foo" is not unique across different operations:
	// operation 1: action = foo, name = bar
	// operation 2: action = bar, name = foo
	private HashMap<String, AxisOperation> operationsAliasesMap = null;

	// Collection of aliases that are invalid for this service because they are
	// duplicated across
	// multiple operations under this service.
	private List<String> invalidOperationsAliases = null;
	// private HashMap operations = new HashMap();

	// to store module ref at deploy time parsing
	private ArrayList<String> moduleRefs = null;

	// to keep the time that last update time of the service
	private long lastupdate;
	private HashMap<String, ModuleConfiguration> moduleConfigmap;
	private String name;
	private ClassLoader serviceClassLoader;

	// to keep the XMLScheam getting either from WSDL or java2wsdl
	private ArrayList<XmlSchema> schemaList;
	// private XmlSchema schema;

	// wsdl is there for this service or not (in side META-INF)
	private boolean wsdlFound = false;

	// to store the scope of the service
	private String scope;

	// to store default message receivers
	private HashMap<String, MessageReceiver> messageReceivers;

	// to set the handler chain available in phase info
	private boolean useDefaultChains = true;

	// to keep the status of the service , since service can stop at the run
	// time
	private boolean active = true;

	private boolean elementFormDefault = true;

	// to keep the service target name space
	private String targetNamespace = Java2WSDLConstants.DEFAULT_TARGET_NAMESPACE;
	private String targetNamespacePrefix = Java2WSDLConstants.TARGETNAMESPACE_PREFIX;

	// to store the target namespace for the schema
	private String schematargetNamespace;// = Java2WSDLConstants.AXIS2_XSD;
	private String schematargetNamespacePrefix = Java2WSDLConstants.SCHEMA_NAMESPACE_PRFIX;

	private boolean enableAllTransports = true;
	private List<String> exposedTransports = new ArrayList<String>();

	// To keep reference to ServiceLifeCycle instance , if the user has
	// specified in services.xml
	private ServiceLifeCycle serviceLifeCycle;

	/**
	 * Keeps track whether the schema locations are adjusted
	 */
	private boolean schemaLocationsAdjusted = false;

	private boolean wsdlImportLocationAdjusted = false;

	/**
	 * A table that keeps a mapping of unique xsd names (Strings) against the
	 * schema objects. This is populated in the first instance the schemas are
	 * asked for and then used to serve the subsequent requests
	 */
	private Map schemaMappingTable = null;

	/**
	 * counter variable for naming the schemas
	 */
	private int count = 0;
	/**
	 * A custom schema Name prefix. if set this will be used to modify the
	 * schema names
	 */
	private String customSchemaNamePrefix = null;

	/**
	 * A custom schema name suffix. will be attached to the schema file name
	 * when the files are uniquely named. A good place to add a file extension
	 * if needed
	 */
	private String customSchemaNameSuffix = null;

	// ///////////////////////////////////////
	// WSDL related stuff ////////////////////
	// //////////////////////////////////////

	/** Map of prefix -> namespaceURI */
	private NamespaceMap namespaceMap;

	private String soapNsUri;
	private String endpointName;
	private String endpointURL;
    
    private List importedNamespaces;

	private boolean clientSide = false;

	// To keep a ref to ObjectSupplier instance
	private ObjectSupplier objectSupplier;

	// package to namespace mapping
	private Map p2nMap;

	// to keep the exclude property details
	private ExcludeInfo excludeInfo;

	private TypeTable typeTable;

	// Data Locators for WS-Mex Support
	private HashMap dataLocators;
	private HashMap<String, String> dataLocatorClassNames;
	private AxisDataLocatorImpl defaultDataLocator;
	// Define search sequence for datalocator based on Data Locator types.
	LocatorType[] availableDataLocatorTypes = new LocatorType[] {
			LocatorType.SERVICE_DIALECT, LocatorType.SERVICE_LEVEL,
			LocatorType.GLOBAL_DIALECT, LocatorType.GLOBAL_LEVEL,
			LocatorType.DEFAULT_AXIS };

	// name of the binding used : use in codegeneration
	private String bindingName;
        
	// List of MessageContextListeners that listen for events on the MessageContext
        private CopyOnWriteArrayList<MessageContextListener> messageContextListeners = 
            new CopyOnWriteArrayList<MessageContextListener>();

        // names list keep to preserve the parameter order
        private List operationsNameList;

	private String[] eprs;
	private boolean customWsdl = false;

	private HashMap policyMap = new HashMap();

	public AxisEndpoint getEndpoint(String key) {
		return (AxisEndpoint) endpointMap.get(key);
	}

	public void addEndpoint(String key, AxisEndpoint axisEndpoint) {
		this.endpointMap.put(key, axisEndpoint);
	}

	/**
	 * @deprecated Use AddressingHelper.getAddressingRequirementParemeterValue
	 */
	public String getWSAddressingFlag() {
		return AddressingHelper.getAddressingRequirementParemeterValue(this);
	}

	/**
	 * @deprecated Use AddressingHelper.setAddressingRequirementParemeterValue
	 */
	public void setWSAddressingFlag(String ar) {
		AddressingHelper.setAddressingRequirementParemeterValue(this, ar);
	}

	public boolean isSchemaLocationsAdjusted() {
		return schemaLocationsAdjusted;
	}

	public void setSchemaLocationsAdjusted(boolean schemaLocationsAdjusted) {
		this.schemaLocationsAdjusted = schemaLocationsAdjusted;
	}

	public Map getSchemaMappingTable() {
		return schemaMappingTable;
	}

	public void setSchemaMappingTable(Map schemaMappingTable) {
		this.schemaMappingTable = schemaMappingTable;
	}

	public String getCustomSchemaNamePrefix() {
		return customSchemaNamePrefix;
	}

	public void setCustomSchemaNamePrefix(String customSchemaNamePrefix) {
		this.customSchemaNamePrefix = customSchemaNamePrefix;
	}

	public String getCustomSchemaNameSuffix() {
		return customSchemaNameSuffix;
	}

	public void setCustomSchemaNameSuffix(String customSchemaNameSuffix) {
		this.customSchemaNameSuffix = customSchemaNameSuffix;
	}

	/**
	 * Constructor AxisService.
	 */
	public AxisService() {
		super();
		this.operationsAliasesMap = new HashMap();
		this.invalidOperationsAliases = new ArrayList();
		moduleConfigmap = new HashMap();
		// by default service scope is for the request
		scope = Constants.SCOPE_REQUEST;
		httpLocationDispatcherMap = new HashMap();
		messageReceivers = new HashMap();
		moduleRefs = new ArrayList();
		schemaList = new ArrayList();
		serviceClassLoader = (ClassLoader) org.apache.axis2.java.security.AccessController
				.doPrivileged(new PrivilegedAction<ClassLoader>() {
					public ClassLoader run() {
						return Thread.currentThread().getContextClassLoader();
					}
				});
		objectSupplier = new DefaultObjectSupplier();
		dataLocators = new HashMap();
		dataLocatorClassNames = new HashMap();
	}

	/**
	 * @return name of the port type
	 * @deprecated use AxisService#getEndpointName() instead.
	 */
	public String getPortTypeName() {
		return endpointName;
	}

	/**
	 * @param portTypeName
	 * @deprecated use AxisService#setEndpointName() instead
	 */
	public void setPortTypeName(String portTypeName) {
		this.endpointName = portTypeName;
	}

	public String getBindingName() {
		return bindingName;
	}

	public void setBindingName(String bindingName) {
		this.bindingName = bindingName;
	}

	/**
	 * get the SOAPVersion
	 */
	public String getSoapNsUri() {
		return soapNsUri;
	}

	public void setSoapNsUri(String soapNsUri) {
		this.soapNsUri = soapNsUri;
	}

	/**
	 * get the endpointName
	 */
	public String getEndpointName() {
		return endpointName;
	}

	public void setEndpointName(String endpoint) {
		this.endpointName = endpoint;
	}

	/**
	 * Constructor AxisService.
	 */
	public AxisService(String name) {
		this();
		this.name = name;
	}

	public void addMessageReceiver(String mepURI,
			MessageReceiver messageReceiver) {
		if (WSDL2Constants.MEP_URI_IN_ONLY.equals(mepURI)
				|| WSDLConstants.WSDL20_2006Constants.MEP_URI_IN_ONLY
						.equals(mepURI)
				|| WSDLConstants.WSDL20_2004_Constants.MEP_URI_IN_ONLY
						.equals(mepURI)) {
			messageReceivers.put(WSDL2Constants.MEP_URI_IN_ONLY,
					messageReceiver);
			messageReceivers.put(
					WSDLConstants.WSDL20_2006Constants.MEP_URI_IN_ONLY,
					messageReceiver);
			messageReceivers.put(
					WSDLConstants.WSDL20_2004_Constants.MEP_URI_IN_ONLY,
					messageReceiver);
		} else if (WSDL2Constants.MEP_URI_OUT_ONLY.equals(mepURI)
				|| WSDLConstants.WSDL20_2006Constants.MEP_URI_OUT_ONLY
						.equals(mepURI)
				|| WSDLConstants.WSDL20_2004_Constants.MEP_URI_OUT_ONLY
						.equals(mepURI)) {
			messageReceivers.put(WSDL2Constants.MEP_URI_OUT_ONLY,
					messageReceiver);
			messageReceivers.put(
					WSDLConstants.WSDL20_2006Constants.MEP_URI_OUT_ONLY,
					messageReceiver);
			messageReceivers.put(
					WSDLConstants.WSDL20_2004_Constants.MEP_URI_OUT_ONLY,
					messageReceiver);
		} else if (WSDL2Constants.MEP_URI_IN_OUT.equals(mepURI)
				|| WSDLConstants.WSDL20_2006Constants.MEP_URI_IN_OUT
						.equals(mepURI)
				|| WSDLConstants.WSDL20_2004_Constants.MEP_URI_IN_OUT
						.equals(mepURI)) {
			messageReceivers
					.put(WSDL2Constants.MEP_URI_IN_OUT, messageReceiver);
			messageReceivers.put(
					WSDLConstants.WSDL20_2006Constants.MEP_URI_IN_OUT,
					messageReceiver);
			messageReceivers.put(
					WSDLConstants.WSDL20_2004_Constants.MEP_URI_IN_OUT,
					messageReceiver);
		} else if (WSDL2Constants.MEP_URI_IN_OPTIONAL_OUT.equals(mepURI)
				|| WSDLConstants.WSDL20_2006Constants.MEP_URI_IN_OPTIONAL_OUT
						.equals(mepURI)
				|| WSDLConstants.WSDL20_2004_Constants.MEP_URI_IN_OPTIONAL_OUT
						.equals(mepURI)) {
			messageReceivers.put(WSDL2Constants.MEP_URI_IN_OPTIONAL_OUT,
					messageReceiver);
			messageReceivers.put(
					WSDLConstants.WSDL20_2006Constants.MEP_URI_IN_OPTIONAL_OUT,
					messageReceiver);
			messageReceivers
					.put(
							WSDLConstants.WSDL20_2004_Constants.MEP_URI_IN_OPTIONAL_OUT,
							messageReceiver);
		} else if (WSDL2Constants.MEP_URI_OUT_IN.equals(mepURI)
				|| WSDLConstants.WSDL20_2006Constants.MEP_URI_OUT_IN
						.equals(mepURI)
				|| WSDLConstants.WSDL20_2004_Constants.MEP_URI_OUT_IN
						.equals(mepURI)) {
			messageReceivers
					.put(WSDL2Constants.MEP_URI_OUT_IN, messageReceiver);
			messageReceivers.put(
					WSDLConstants.WSDL20_2006Constants.MEP_URI_OUT_IN,
					messageReceiver);
			messageReceivers.put(
					WSDLConstants.WSDL20_2004_Constants.MEP_URI_OUT_IN,
					messageReceiver);
		} else if (WSDL2Constants.MEP_URI_OUT_OPTIONAL_IN.equals(mepURI)
				|| WSDLConstants.WSDL20_2006Constants.MEP_URI_OUT_OPTIONAL_IN
						.equals(mepURI)
				|| WSDLConstants.WSDL20_2004_Constants.MEP_URI_OUT_OPTIONAL_IN
						.equals(mepURI)) {
			messageReceivers.put(WSDL2Constants.MEP_URI_OUT_OPTIONAL_IN,
					messageReceiver);
			messageReceivers.put(
					WSDLConstants.WSDL20_2006Constants.MEP_URI_OUT_OPTIONAL_IN,
					messageReceiver);
			messageReceivers
					.put(
							WSDLConstants.WSDL20_2004_Constants.MEP_URI_OUT_OPTIONAL_IN,
							messageReceiver);
		} else if (WSDL2Constants.MEP_URI_ROBUST_OUT_ONLY.equals(mepURI)
				|| WSDLConstants.WSDL20_2006Constants.MEP_URI_ROBUST_OUT_ONLY
						.equals(mepURI)
				|| WSDLConstants.WSDL20_2004_Constants.MEP_URI_ROBUST_OUT_ONLY
						.equals(mepURI)) {
			messageReceivers.put(WSDL2Constants.MEP_URI_ROBUST_OUT_ONLY,
					messageReceiver);
			messageReceivers.put(
					WSDLConstants.WSDL20_2006Constants.MEP_URI_ROBUST_OUT_ONLY,
					messageReceiver);
			messageReceivers
					.put(
							WSDLConstants.WSDL20_2004_Constants.MEP_URI_ROBUST_OUT_ONLY,
							messageReceiver);
		} else if (WSDL2Constants.MEP_URI_ROBUST_IN_ONLY.equals(mepURI)
				|| WSDLConstants.WSDL20_2006Constants.MEP_URI_ROBUST_IN_ONLY
						.equals(mepURI)
				|| WSDLConstants.WSDL20_2004_Constants.MEP_URI_ROBUST_IN_ONLY
						.equals(mepURI)) {
			messageReceivers.put(WSDL2Constants.MEP_URI_ROBUST_IN_ONLY,
					messageReceiver);
			messageReceivers.put(
					WSDLConstants.WSDL20_2006Constants.MEP_URI_ROBUST_IN_ONLY,
					messageReceiver);
			messageReceivers.put(
					WSDLConstants.WSDL20_2004_Constants.MEP_URI_ROBUST_IN_ONLY,
					messageReceiver);
		} else {
			messageReceivers.put(mepURI, messageReceiver);
		}
	}

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

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

	/**
	 * Add any control operations defined by a Module to this service.
	 * 
	 * @param module
	 *            the AxisModule which has just been engaged
	 * @throws AxisFault
	 *             if a problem occurs
	 */
	void addModuleOperations(AxisModule module) throws AxisFault {
		HashMap<QName, AxisOperation> map = module.getOperations();
		Collection<AxisOperation> col = map.values();
		PhaseResolver phaseResolver = new PhaseResolver(getAxisConfiguration());
		for (Iterator<AxisOperation> iterator = col.iterator(); iterator.hasNext();) {
			AxisOperation axisOperation = copyOperation((AxisOperation) iterator
					.next());
			if (this.getOperation(axisOperation.getName()) == null) {
				ArrayList<String> wsamappings = axisOperation.getWSAMappingList();
				if (wsamappings != null) {
					for (int j = 0, size = wsamappings.size(); j < size; j++) {
						String mapping = (String) wsamappings.get(j);
						mapActionToOperation(mapping, axisOperation);
					}
				}
				// If we've set the "expose" parameter for this operation, it's
				// normal (non-
				// control) and therefore it will appear in generated WSDL. If
				// we haven't,
				// it's a control operation and will be ignored at WSDL-gen
				// time.
				if (axisOperation
						.isParameterTrue(DeploymentConstants.TAG_EXPOSE)) {
					axisOperation.setControlOperation(false);
				} else {
					axisOperation.setControlOperation(true);
				}

				phaseResolver.engageModuleToOperation(axisOperation, module);

				this.addOperation(axisOperation);
			}
		}
	}

	public void addModuleref(String moduleref) {
		moduleRefs.add(moduleref);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.axis2.description.AxisService#addOperation(org.apache.axis2.description.AxisOperation)
	 */

	/**
	 * Method addOperation.
	 * 
	 * @param axisOperation
	 */
	public void addOperation(AxisOperation axisOperation) {
		axisOperation.setParent(this);
        
        if (log.isDebugEnabled()) {
            if (axisOperation.getName().equals(ServiceClient.ANON_OUT_ONLY_OP)
                    || (axisOperation.getName().equals(ServiceClient.ANON_OUT_ONLY_OP))
                    || (axisOperation.getName().equals(ServiceClient.ANON_OUT_ONLY_OP))) {
                log.debug("Client-defined operation name matches default operation name. "
                        + "this may cause interoperability issues.  Name is: " + axisOperation.getName().toString());
            }
        }

		Iterator<AxisModule> modules = getEngagedModules().iterator();

		while (modules.hasNext()) {
			AxisModule module = (AxisModule) modules.next();
			try {
				axisOperation.engageModule(module);
			} catch (AxisFault axisFault) {
				log.info(Messages.getMessage("modulealredyengagetoservice",
						module.getName()));
			}
		}
		if (axisOperation.getMessageReceiver() == null) {
			axisOperation.setMessageReceiver(loadDefaultMessageReceiver(
					axisOperation.getMessageExchangePattern(), this));
		}
		if (axisOperation.getInputAction() == null) {
			axisOperation.setSoapAction("urn:"
					+ axisOperation.getName().getLocalPart());
		}

		if (axisOperation.getOutputAction() == null) {
			axisOperation.setOutputAction("urn:"
					+ axisOperation.getName().getLocalPart()
					+ Java2WSDLConstants.RESPONSE);
		}
		addChild(axisOperation);

		String operationName = axisOperation.getName().getLocalPart();

		/*
		 * Some times name of the operation can be different from the name of
		 * the first child of the SOAPBody. This will put the correct mapping
		 * associating that name with the operation. This will be useful
		 * especially for the SOAPBodyBasedDispatcher
		 */

		Iterator axisMessageIter = axisOperation.getChildren();

		while (axisMessageIter.hasNext()) {
			AxisMessage axisMessage = (AxisMessage) axisMessageIter.next();
			String messageName = axisMessage.getName();
			if (messageName != null && !messageName.equals(operationName)) {
				mapActionToOperation(messageName, axisOperation);
			}
		}

		mapActionToOperation(operationName, axisOperation);

		String action = axisOperation.getInputAction();
		if (action.length() > 0) {
			mapActionToOperation(action, axisOperation);
		}

		ArrayList<String> wsamappings = axisOperation.getWSAMappingList();
		if (wsamappings != null) {
			for (int j = 0, size = wsamappings.size(); j < size; j++) {
				String mapping = (String) wsamappings.get(j);
				mapActionToOperation(mapping, axisOperation);
			}
		}

		if (axisOperation.getMessageReceiver() == null) {
			axisOperation.setMessageReceiver(loadDefaultMessageReceiver(
					axisOperation.getMessageExchangePattern(), this));
		}
	}

	private 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;
			}
		}
		if (getAxisConfiguration() != null) {
			return getAxisConfiguration().getMessageReceiver(mepURL);
		}
		return null;
	}

	/**
	 * Gets a copy from module operation.
	 * 
	 * @param axisOperation
	 * @return Returns AxisOperation.
	 * @throws AxisFault
	 */
	private AxisOperation copyOperation(AxisOperation axisOperation)
			throws AxisFault {
		AxisOperation operation = AxisOperationFactory
				.getOperationDescription(axisOperation
						.getMessageExchangePattern());

		operation.setMessageReceiver(axisOperation.getMessageReceiver());
		operation.setName(axisOperation.getName());

		Iterator<Parameter> parameters = axisOperation.getParameters().iterator();

		while (parameters.hasNext()) {
			Parameter parameter = (Parameter) parameters.next();

			operation.addParameter(parameter);
		}

		PolicyInclude policyInclude = new PolicyInclude(operation);
		PolicyInclude axisOperationPolicyInclude = axisOperation
				.getPolicyInclude();

		if (axisOperationPolicyInclude != null) {
			Policy policy = axisOperationPolicyInclude.getPolicy();
			if (policy != null) {
				policyInclude.setPolicy(axisOperationPolicyInclude.getPolicy());
			}
		}
		operation.setPolicyInclude(policyInclude);

		operation.setWsamappingList(axisOperation.getWSAMappingList());
		operation.setRemainingPhasesInFlow(axisOperation
				.getRemainingPhasesInFlow());
		operation.setPhasesInFaultFlow(axisOperation.getPhasesInFaultFlow());
		operation.setPhasesOutFaultFlow(axisOperation.getPhasesOutFaultFlow());
		operation.setPhasesOutFlow(axisOperation.getPhasesOutFlow());

		operation.setOutputAction(axisOperation.getOutputAction());
		String[] faultActionNames = axisOperation.getFaultActionNames();
		for (int i = 0; i < faultActionNames.length; i++) {
			operation.addFaultAction(faultActionNames[i], axisOperation
					.getFaultAction(faultActionNames[i]));
		}

		return operation;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.axis2.description.AxisService#addToengagedModules(javax.xml.namespace.QName)
	 */

	/**
	 * Engages a module. It is required to use this method.
	 * 
	 * @param axisModule
	 * @param engager
	 */
	public void onEngage(AxisModule axisModule, AxisDescription engager)
			throws AxisFault {
		// adding module operations
		addModuleOperations(axisModule);

		Iterator<AxisOperation> operations = getOperations();
		while (operations.hasNext()) {
			AxisOperation axisOperation = (AxisOperation) operations.next();
			axisOperation.engageModule(axisModule, engager);
		}
	}

	/**
	 * Maps an alias (such as a SOAPAction, WSA action, or an operation name) to
	 * the given AxisOperation. This is used by dispatching (both SOAPAction-
	 * and WSAddressing- based dispatching) to figure out which operation a
	 * given message is for. Some notes on restrictions of "action" - A null or
	 * empty action will be ignored - An action that is a duplicate and
	 * references an idential operation is allowed - An acton that is a
	 * duplicate and references a different operation is NOT allowed. In this
	 * case, the action for the original operation is removed from the alias
	 * table, thus removing the ability to route based on this action. This is
	 * necessary to prevent mis-directing incoming message to the wrong
	 * operation based on SOAPAction.
	 * 
	 * Note that an alias could be a SOAPAction, WS-Addressing Action, the
	 * operation name, or some other alias.
	 * 
	 * @see #getOperationByAction(String)
	 * 
	 * @param action
	 *            the alias key
	 * @param axisOperation
	 *            the operation to map to
	 */
	public void mapActionToOperation(String action, AxisOperation axisOperation) {
		if (action == null || "".equals(action)) {
			if (log.isDebugEnabled()) {
				log
						.debug("mapActionToOperation: A null or empty action cannot be used to map to an operation.");
			}
			return;
		}
		if (log.isDebugEnabled()) {
			log
					.debug("mapActionToOperation: Mapping Action to Operation: action: "
							+ action
							+ "; operation: "
							+ axisOperation
							+ "named: " + axisOperation.getName());
		}

		// First check if this action has already been flagged as invalid
		// because it is a duplicate.
		if (invalidOperationsAliases.contains(action)) {
			// This SOAPAction has already been determined to be invalid; log a
			// message
			// and do not add it to the operation alias map.
			if (log.isDebugEnabled()) {
				log
						.debug("mapActionToOperation: The action: "
								+ action
								+ " can not be used for operation: "
								+ axisOperation
								+ " with operation name: "
								+ axisOperation.getName()
								+ " because that SOAPAction is not unique for this service.");
			}
			return;
		}

		// Check if the action is currently mapping to an operation.
		AxisOperation currentlyMappedOperation = getOperationByAction(action);
		if (currentlyMappedOperation != null) {
			if (currentlyMappedOperation == axisOperation) {
				// This maps to the same operation, then it is already in the
				// alias table, so
				// just silently ignore this mapping request.
				if (log.isDebugEnabled()) {
					log
							.debug("mapActionToOperation: This operation is already mapped to this action: "
									+ action
									+ "; AxisOperation: "
									+ currentlyMappedOperation
									+ " named: "
									+ currentlyMappedOperation.getName());
				}
			} else {
				// This action is already mapped, but it is to a different
				// operation. Remove
				// the action mapping from the alias table and add it to the
				// list of invalid mappings
				operationsAliasesMap.remove(action);
				invalidOperationsAliases.add(action);
				if (log.isDebugEnabled()) {
					log
							.debug("mapActionToOperation: The action is already mapped to a different "
									+ "operation.  The mapping of the action to any operations will be "
									+ "removed.  Action: "
									+ action
									+ "; original operation: "
									+ currentlyMappedOperation
									+ " named "
									+ currentlyMappedOperation.getName()
									+ "; new operation: "
									+ axisOperation
									+ " named " + axisOperation.getName());
				}
			}
		} else {
			operationsAliasesMap.put(action, axisOperation);
			// Adding operation name to the mapping table
			// operationsAliasesMap.put(axisOperation.getName().getLocalPart(),
			// axisOperation);
		}
	}

	/**
	 * Maps an constant string in the whttp:location to the given operation.
	 * This is used by RequestURIOperationDispatcher based dispatching to figure
	 * out which operation it is that a given message is for.
	 * 
	 * @param string
	 *            the constant drawn from whttp:location
	 * @param axisOperation
	 *            the operation to map to
	 */
	public void addHttpLocationDispatcherString(String string,
			AxisOperation axisOperation) {
		httpLocationDispatcherMap.put(string, axisOperation);
	}

	public void printSchema(OutputStream out) throws AxisFault {
		for (int i = 0; i < schemaList.size(); i++) {
			XmlSchema schema = addNameSpaces(i);
			schema.write(out);
		}
	}

	public XmlSchema getSchema(int index) {
		return addNameSpaces(index);
	}

	/**
	 * Release the list of schema objects. <p/> In some environments, this can
	 * provide significant relief of memory consumption in the java heap, as
	 * long as the need for the schema list has completed.
	 */
	public void releaseSchemaList() {
		if (schemaList != null) {
			// release the schema list
			schemaList.clear();
		}

		if (log.isDebugEnabled()) {
			log.debug("releaseSchemaList: schema list has been released.");
		}
	}

	private XmlSchema addNameSpaces(int i) {
		XmlSchema schema = (XmlSchema) schemaList.get(i);
		NamespaceMap map = (NamespaceMap) namespaceMap.clone();
		NamespacePrefixList namespaceContext = schema.getNamespaceContext();
		String prefixes[] = namespaceContext.getDeclaredPrefixes();
		for (int j = 0; j < prefixes.length; j++) {
			String prefix = prefixes[j];
			map.add(prefix, namespaceContext.getNamespaceURI(prefix));
		}
		schema.setNamespaceContext(map);
		return schema;
	}

	public void setEPRs(String[] eprs) {
		this.eprs = eprs;
	}

	public String[] getEPRs() {
		if (eprs != null && eprs.length != 0) {
			return eprs;
		}
		eprs = calculateEPRs();
		return eprs;
	}

	private String[] calculateEPRs() {
		try {
			String requestIP = org.apache.axis2.util.Utils.getIpAddress(getAxisConfiguration());
			return calculateEPRs(requestIP);
		} catch (SocketException e) {
			log.error("Cannot get local IP address", e);
		}
		return new String[0];
	}

	private String[] calculateEPRs(String requestIP) {
		AxisConfiguration axisConfig = getAxisConfiguration();
		if (axisConfig == null) {
			return null;
		}
		ArrayList<String> eprList = new ArrayList<String>();
		if (enableAllTransports) {
			for (Iterator<TransportInDescription> transports = axisConfig.getTransportsIn().values()
					.iterator(); transports.hasNext();) {
				TransportInDescription transportIn = (TransportInDescription) transports
						.next();
				TransportListener listener = transportIn.getReceiver();
				if (listener != null) {
					try {
						EndpointReference[] eprsForService = listener
								.getEPRsForService(this.name, requestIP);
						if (eprsForService != null) {
							for (int i = 0; i < eprsForService.length; i++) {
								EndpointReference endpointReference = eprsForService[i];
								if (endpointReference != null) {
									String address = endpointReference
											.getAddress();
									if (address != null) {
										eprList.add(address);
									}
								}
							}
						}
					} catch (AxisFault axisFault) {
						log.warn(axisFault.getMessage());
					}
				}
			}
		} else {
			List<String> trs = this.exposedTransports;
			for (int i = 0; i < trs.size(); i++) {
				String trsName = (String) trs.get(i);
				TransportInDescription transportIn = axisConfig
						.getTransportIn(trsName);
				if (transportIn != null) {
					TransportListener listener = transportIn.getReceiver();
					if (listener != null) {
						try {
							EndpointReference[] eprsForService = listener
									.getEPRsForService(this.name, requestIP);
							if (eprsForService != null) {
								for (int j = 0; j < eprsForService.length; j++) {
									EndpointReference endpointReference = eprsForService[j];
									if (endpointReference != null) {
										String address = endpointReference
												.getAddress();
										if (address != null) {
											eprList.add(address);
										}
									}
								}
							}
						} catch (AxisFault axisFault) {
							log.warn(axisFault.getMessage());
						}
					}
				}
			}
		}
		eprs = (String[]) eprList.toArray(new String[eprList.size()]);
		return eprs;
	}

	private void printDefinitionObject(Definition definition, OutputStream out,
			String requestIP) throws AxisFault, WSDLException {
		if (isModifyUserWSDLPortAddress()) {
			setPortAddress(definition, requestIP);
		}
		if (!wsdlImportLocationAdjusted) {
			changeImportAndIncludeLocations(definition);
			wsdlImportLocationAdjusted = true;
		}
		WSDLWriter writer = WSDLFactory.newInstance().newWSDLWriter();
		writer.writeWSDL(definition, out);
	}

	public void printUserWSDL(OutputStream out, String wsdlName)
			throws AxisFault {
		Definition definition = null;
		// first find the correct wsdl definition
		Parameter wsdlParameter = getParameter(WSDLConstants.WSDL_4_J_DEFINITION);
		if (wsdlParameter != null) {
			definition = (Definition) wsdlParameter.getValue();
		}

		if (definition != null) {
			try {
				printDefinitionObject(getWSDLDefinition(definition, wsdlName),
						out, null);
			} catch (WSDLException e) {
				throw AxisFault.makeFault(e);
			}
		} else {
			printWSDLError(out);
		}

	}

	/**
	 * find the defintion object for given name
	 * 
	 * @param parentDefinition
	 * @param name
	 * @return wsdl definition
	 */
	private Definition getWSDLDefinition(Definition parentDefinition,
			String name) {

		if (name == null)
			return parentDefinition;

		Definition importedDefinition = null;
		Iterator iter = parentDefinition.getImports().values().iterator();
		Vector values = null;
		Import wsdlImport = null;
		for (; iter.hasNext();) {
			values = (Vector) iter.next();
			for (Iterator valuesIter = values.iterator(); valuesIter.hasNext();) {
				wsdlImport = (Import) valuesIter.next();
				if (wsdlImport.getLocationURI().endsWith(name)) {
					importedDefinition = wsdlImport.getDefinition();
					break;
				} else {
					importedDefinition = getWSDLDefinition(wsdlImport
							.getDefinition(), name);
				}
				if (importedDefinition != null) {
					break;
				}
			}
			if (importedDefinition != null) {
				break;
			}
		}
		return importedDefinition;
	}

	/**
	 * this procesdue recursively adjust the wsdl imports locations and the
	 * schmea import and include locations.
	 * 
	 * @param definition
	 */
	private void changeImportAndIncludeLocations(Definition definition) throws AxisFault {

        // adjust the schema locations in types section
        Types types = definition.getTypes();
        if (types != null) {
            List extensibilityElements = types.getExtensibilityElements();
            Object extensibilityElement = null;
            Schema schema = null;
            for (Iterator iter = extensibilityElements.iterator(); iter.hasNext();) {
                extensibilityElement = iter.next();
                if (extensibilityElement instanceof Schema) {
                    schema = (Schema) extensibilityElement;
                    changeLocations(schema.getElement());
                }
            }
        }

        Iterator iter = definition.getImports().values().iterator();
        Vector values = null;
        Import wsdlImport = null;
        String originalImprotString = null;
        for (; iter.hasNext();) {
            values = (Vector) iter.next();
            for (Iterator valuesIter = values.iterator(); valuesIter.hasNext();) {
                wsdlImport = (Import) valuesIter.next();
                originalImprotString = wsdlImport.getLocationURI();
                if (originalImprotString.indexOf("://") == -1 && originalImprotString.indexOf("?wsdl=") == -1){
                    wsdlImport.setLocationURI(this.getServiceEPR() + "?wsdl=" + originalImprotString);
                }
                changeImportAndIncludeLocations(wsdlImport.getDefinition());
            }
        }

    }

	/**
	 * change the schema Location in the elemment
	 * 
	 * @param element
	 */

	private void changeLocations(Element element) throws AxisFault {
        NodeList nodeList = element.getChildNodes();
        String tagName;
        for (int i = 0; i < nodeList.getLength(); i++) {
            tagName = nodeList.item(i).getLocalName();
            if (IMPORT_TAG.equals(tagName) || INCLUDE_TAG.equals(tagName)) {
                processImport(nodeList.item(i));
            }
        }
    }

	private void updateSchemaLocation(XmlSchema schema) throws AxisFault {
        XmlSchemaObjectCollection includes = schema.getIncludes();
        for (int j = 0; j < includes.getCount(); j++) {
            Object item = includes.getItem(j);
            if (item instanceof XmlSchemaExternal) {
                XmlSchemaExternal xmlSchemaExternal = (XmlSchemaExternal) item;
                XmlSchema s = xmlSchemaExternal.getSchema();
                updateSchemaLocation(s, xmlSchemaExternal);
            }
        }
    }
	   
	private void updateSchemaLocation(XmlSchema s, XmlSchemaExternal xmlSchemaExternal) throws AxisFault {
        if (s != null) {
            String schemaLocation = xmlSchemaExternal.getSchemaLocation();

            if (schemaLocation.indexOf("://") == -1 && schemaLocation.indexOf("?xsd=") == -1) {
                String newscheamlocation = this.getServiceEPR() + "?xsd=" + schemaLocation;
                xmlSchemaExternal.setSchemaLocation(newscheamlocation);
            }
        }
    }
	   
	private void processImport(Node importNode) throws AxisFault {
        NamedNodeMap nodeMap = importNode.getAttributes();
        Node attribute;
        String attributeValue;
        for (int i = 0; i < nodeMap.getLength(); i++) {
            attribute = nodeMap.item(i);
            if (attribute.getNodeName().equals("schemaLocation")) {
                attributeValue = attribute.getNodeValue();
                if (attributeValue.indexOf("://") == -1 && attributeValue.indexOf("?xsd=") == -1) {
                    attribute.setNodeValue(this.getServiceEPR() + "?xsd=" + attributeValue);
                }
            }
        }
    }

    private String getServiceEPR() {
        String serviceEPR = null;
        Parameter parameter = this.getParameter(Constants.Configuration.GENERATE_ABSOLUTE_LOCATION_URIS);
        if ((parameter != null) && JavaUtils.isTrueExplicitly(parameter.getValue())) {
            String[] eprs = this.getEPRs();
            for (int i = 0; i < eprs.length; i++) {
                if ((eprs[i] != null) && (eprs[i].startsWith("http:"))){
                    serviceEPR = eprs[i];
                    break;
                }
            }
            if (serviceEPR == null){
                serviceEPR = eprs[0];
            }
        } else {
            serviceEPR = this.name;
        }
        if (serviceEPR.endsWith("/")){
            serviceEPR = serviceEPR.substring(0, serviceEPR.lastIndexOf("/"));
        }
        return serviceEPR;
    }

    /**
	 * Produces a XSD for this AxisService and prints it to the specified
	 * OutputStream.
	 * 
	 * @param out
	 *            destination stream.
	 * @param xsd
	 *            schema name
	 * @return -1 implies not found, 0 implies redirect to root, 1 implies
	 *         found/printed a schema
	 * @throws IOException
	 */
	public int printXSD(OutputStream out, String xsd) throws IOException {

		// If we find a SchemaSupplier, use that
		SchemaSupplier supplier = (SchemaSupplier) getParameterValue("SchemaSupplier");
		if (supplier != null) {
			XmlSchema schema = supplier.getSchema(this, xsd);
			if (schema != null) {
			    updateSchemaLocation(schema);
				schema.write(new OutputStreamWriter(out, "UTF8"));
				out.flush();
				out.close();
				return 1;
			}
		}

		// call the populator
		populateSchemaMappings();
		Map schemaMappingtable = getSchemaMappingTable();
		ArrayList<XmlSchema> schemas = getSchema();

		// a name is present - try to pump the requested schema
		if (!"".equals(xsd)) {
			XmlSchema schema = (XmlSchema) schemaMappingtable.get(xsd);
			if (schema == null) {
				int dotIndex = xsd.indexOf('.');
				if (dotIndex > 0) {
					String schemaKey = xsd.substring(0, dotIndex);
					schema = (XmlSchema) schemaMappingtable.get(schemaKey);
				}
			}
			if (schema != null) {
				// schema is there - pump it outs
				schema.write(new OutputStreamWriter(out, "UTF8"));
				out.flush();
				out.close();
			} else {
                            // make sure we are only serving .xsd files and ignore requests with
                            // ".." in the name.
                            if (xsd.endsWith(".xsd") && xsd.indexOf("..") == -1) {
				InputStream in = getClassLoader().getResourceAsStream(
						DeploymentConstants.META_INF + "/" + xsd);
				if (in != null) {
                                    IOUtils.copy(in, out, true);
				} else {
                                    // Can't find the schema
                                    return -1;
				}
                            } else {
                                // bad schema request
                                return -1;
                            }
			}
		} else if (schemas.size() > 1) {
			// multiple schemas are present and the user specified
			// no name - in this case we cannot possibly pump a schema
			// so redirect to the service root
			return 0;
		} else {
			// user specified no name and there is only one schema
			// so pump that out
			ArrayList<XmlSchema> list = getSchema();
			if (list.size() > 0) {
				XmlSchema schema = getSchema(0);
				if (schema != null) {
					schema.write(new OutputStreamWriter(out, "UTF8"));
					out.flush();
					out.close();
				}
			} else {
				String xsdNotFound = "<error>"
						+ "<description>Unable to access schema for this service</description>"
						+ "</error>";
				out.write(xsdNotFound.getBytes());
				out.flush();
				out.close();
			}
		}
		return 1;
	}

	/**
	 * Produces a WSDL for this AxisService and prints it to the specified
	 * OutputStream.
	 * 
	 * @param out
	 *            destination stream. The WSDL will be sent here.
	 * @param requestIP
	 *            the hostname the WSDL request was directed at. This should be
	 *            the address that appears in the generated WSDL.
	 * @throws AxisFault
	 *             if an error occurs
	 */
	public void printWSDL(OutputStream out, String requestIP) throws AxisFault {
		// If we're looking for pre-existing WSDL, use that.
		if (isUseUserWSDL()) {
			printUserWSDL(out, null);
			return;
		}

		// If we find a WSDLSupplier, use that
		WSDLSupplier supplier = (WSDLSupplier) getParameterValue("WSDLSupplier");
		if (supplier != null) {
			try {
				Definition definition = supplier.getWSDL(this);
				if (definition != null) {
				    changeImportAndIncludeLocations(definition);
                    printDefinitionObject(getWSDLDefinition(definition, null),
							out, requestIP);
				}
			} catch (Exception e) {
				printWSDLError(out, e);
			}
			return;
		}

		// Otherwise, generate WSDL ourselves
		String[] eprArray = requestIP == null ? new String[] { this.endpointName }
				: calculateEPRs(requestIP);
		getWSDL(out, eprArray);
	}

	/**
	 * Print the WSDL with a default URL. This will be called only during
	 * codegen time.
	 * 
	 * @param out
	 * @throws AxisFault
	 */
	public void printWSDL(OutputStream out) throws AxisFault {
		printWSDL(out, null);
	}

        private AxisEndpoint getAxisEndpoint(String port) {
            // if service has a single endpoint, this will cause the [serviceName] address
            // to be used in wsdl instead of the [serviceName].[endpointName]
            if (endpointMap.size() == 1 && endpointMap.containsKey(getEndpointName())) {
                return null;
            } else {
                return (AxisEndpoint)endpointMap.get(port);
            }
        }

	private void setPortAddress(Definition definition, String requestIP)
			throws AxisFault {
		Iterator serviceItr = definition.getServices().values().iterator();
		while (serviceItr.hasNext()) {
			Service serviceElement = (Service) serviceItr.next();
			Iterator portItr = serviceElement.getPorts().values().iterator();
			while (portItr.hasNext()) {
				Port port = (Port) portItr.next();
				AxisEndpoint endpoint = getAxisEndpoint(port.getName());
				List list = port.getExtensibilityElements();
				for (int i = 0; i < list.size(); i++) {
					Object extensibilityEle = list.get(i);
					if (extensibilityEle instanceof SOAPAddress) {
						SOAPAddress soapAddress = (SOAPAddress) extensibilityEle;
						String existingAddress = soapAddress.getLocationURI();
						if (existingAddress == null
								|| existingAddress
										.equals("REPLACE_WITH_ACTUAL_URL")) {
							if (endpoint != null) {
								((SOAPAddress) extensibilityEle)
										.setLocationURI(endpoint
												.calculateEndpointURL());
							} else {
								((SOAPAddress) extensibilityEle)
										.setLocationURI(getEPRs()[0]);
							}
						} else {
							if (requestIP == null) {
								if (endpoint != null) {
									((SOAPAddress) extensibilityEle)
											.setLocationURI(endpoint
													.calculateEndpointURL());
								} else {
									((SOAPAddress) extensibilityEle)
											.setLocationURI(getLocationURI(
													getEPRs(), existingAddress));
								}
							} else {
								if (endpoint != null) {
									((SOAPAddress) extensibilityEle)
											.setLocationURI(endpoint
													.calculateEndpointURL());
								} else {
									((SOAPAddress) extensibilityEle)
											.setLocationURI(getLocationURI(
													calculateEPRs(requestIP),
													existingAddress));
								}
							}
						}
					} else if (extensibilityEle instanceof SOAP12Address) {
						SOAP12Address soapAddress = (SOAP12Address) extensibilityEle;
						String exsistingAddress = soapAddress.getLocationURI();
						if (requestIP == null) {
							if (endpoint != null) {
								((SOAP12Address) extensibilityEle)
										.setLocationURI(endpoint
												.calculateEndpointURL());

							} else {
								((SOAP12Address) extensibilityEle)
										.setLocationURI(getLocationURI(
												getEPRs(), exsistingAddress));
							}
						} else {
							if (endpoint != null) {
								((SOAP12Address) extensibilityEle)
										.setLocationURI(endpoint
												.calculateEndpointURL());
							} else {
								((SOAP12Address) extensibilityEle)
										.setLocationURI(getLocationURI(
												calculateEPRs(requestIP),
												exsistingAddress));

							}
						}
					} else if (extensibilityEle instanceof HTTPAddress) {
						HTTPAddress httpAddress = (HTTPAddress) extensibilityEle;
						String exsistingAddress = httpAddress.getLocationURI();
						if (requestIP == null) {
							if (endpoint != null) {
								((HTTPAddress) extensibilityEle)
										.setLocationURI(endpoint
												.calculateEndpointURL());
							} else {
								((HTTPAddress) extensibilityEle)
										.setLocationURI(getLocationURI(
												getEPRs(), exsistingAddress));
							}
						} else {
							if (endpoint != null) {
								((HTTPAddress) extensibilityEle)
										.setLocationURI(endpoint
												.calculateEndpointURL());
							} else {
								((HTTPAddress) extensibilityEle)
										.setLocationURI(getLocationURI(
												calculateEPRs(requestIP),
												exsistingAddress));
							}
						}
					}
					// TODO : change the Endpoint refrence addess as well.
				}
			}
		}
	}

	/**
	 * this method returns the new IP address corresponding to the already
	 * existing ip
	 * 
	 * @param eprs
	 * @param epr
	 * @return corresponding Ip address
	 */
	private String getLocationURI(String[] eprs, String epr) throws AxisFault {
		String returnIP = null;
		if (epr != null) {
			if (epr.indexOf(":") > -1) {
				String existingProtocol = epr.substring(0, epr.indexOf(":"))
						.trim();
				String eprProtocol;
				for (int i = 0; i < eprs.length; i++) {
					eprProtocol = eprs[i].substring(0, eprs[i].indexOf(":"))
							.trim();
					if (eprProtocol.equals(existingProtocol)) {
						returnIP = eprs[i];
						break;
					}
				}
				if (returnIP != null) {
					return returnIP;
				} else {
					throw new AxisFault(
							"Server does not have an epr for the wsdl epr==>"
									+ epr);
				}
			} else {
				throw new AxisFault("invalid epr is given epr ==> " + epr);
			}
		} else {
			throw new AxisFault("No epr is given in the wsdl port");
		}
	}

	private void getWSDL(OutputStream out, String[] serviceURL)
			throws AxisFault {
		// Retrieve WSDL using the same data retrieval path for GetMetadata
		// request.
		DataRetrievalRequest request = new DataRetrievalRequest();
		request.putDialect(DRConstants.SPEC.DIALECT_TYPE_WSDL);
		request.putOutputForm(OutputForm.INLINE_FORM);

		MessageContext context = new MessageContext();
		context.setAxisService(this);
		context.setTo(new EndpointReference(serviceURL[0]));

		Data[] result = getData(request, context);
		OMElement wsdlElement;
		if (result != null && result.length > 0) {
			wsdlElement = (OMElement) (result[0].getData());
			try {
				XMLPrettyPrinter.prettify(wsdlElement, out);
				out.flush();
				out.close();
			} catch (Exception e) {
				throw AxisFault.makeFault(e);
			}
		}
	}

	private void printWSDLError(OutputStream out) throws AxisFault {
		printWSDLError(out, null);
	}

	private void printWSDLError(OutputStream out, Exception e) throws AxisFault {
		try {
			String wsdlntfound = "<error>"
					+ "<description>Unable to generate WSDL 1.1 for this service</description>"
					+ "<reason>If you wish Axis2 to automatically generate the WSDL 1.1, then please "
					+ "set useOriginalwsdl as false in your services.xml</reason>";
			out.write(wsdlntfound.getBytes());
			if (e != null) {
				PrintWriter pw = new PrintWriter(out);
				e.printStackTrace(pw);
				pw.flush();
			}
			out.write("</error>".getBytes());
			out.flush();
			out.close();
		} catch (IOException ex) {
			throw AxisFault.makeFault(ex);
		}
	}

	/**
	 * Print the WSDL2.0 with a default URL. This will be called only during
	 * codegen time.
	 * 
	 * @param out
	 * @throws AxisFault
	 */
	public void printWSDL2(OutputStream out) throws AxisFault {
		printWSDL2(out, null);
	}

	public void printWSDL2(OutputStream out, String requestIP) throws AxisFault {
		AxisService2WSDL20 axisService2WSDL2 = new AxisService2WSDL20(this);
		try {
			if (requestIP != null) {
				axisService2WSDL2.setEPRs(calculateEPRs(requestIP));
			}
			OMElement wsdlElement = axisService2WSDL2.generateOM();
			wsdlElement.serialize(out);
			out.flush();
			out.close();
		} catch (Exception e) {
			throw AxisFault.makeFault(e);
		}
	}

    /**
     * Produces a WSDL2 for this AxisService and prints it to the specified
     * OutputStream.
     * 
     * @param out
     *            destination stream.
     * @param wsdl
     *            wsdl name
     * @return -1 implies not found, 0 implies redirect to root, 1 implies
     *         found/printed wsdl
     * @throws IOException
     */
    public int printWSDL2(OutputStream out, String requestIP, String wsdl) 
        throws IOException, AxisFault {    
        // a name is present - try to pump the requested wsdl file
        if (!"".equals(wsdl)) {
            // make sure we are only serving .wsdl files and ignore requests with
            // ".." in the name.
            if (wsdl.endsWith(".wsdl") && wsdl.indexOf("..") == -1) {
                InputStream in = getClassLoader().getResourceAsStream(
                                    DeploymentConstants.META_INF + "/" + wsdl);
                if (in != null) {
                    IOUtils.copy(in, out, true);
                } else {
                    // can't find the wsdl
                    return -1;
                }
            } else {
                // bad wsdl2 request
                return -1;
            }
        } else {
            printWSDL2(out, requestIP);
        }
        
        return 1;
    }
    
	/**
	 * Gets the description about the service which is specified in
	 * services.xml.
	 * 
	 * @return Returns String.
	 * @deprecated Use getDocumentation() instead
	 */
	public String getServiceDescription() {
		return getDocumentation();
	}

	/**
	 * Method getClassLoader.
	 * 
	 * @return Returns ClassLoader.
	 */
	public ClassLoader getClassLoader() {
		return this.serviceClassLoader;
	}

	/**
	 * Gets the control operation which are added by module like RM.
	 */
	public ArrayList<AxisOperation> getControlOperations() {
		Iterator<AxisOperation> op_itr = getOperations();
		ArrayList<AxisOperation> operationList = new ArrayList<AxisOperation>();

		while (op_itr.hasNext()) {
			AxisOperation operation = (AxisOperation) op_itr.next();

			if (operation.isControlOperation()) {
				operationList.add(operation);
			}
		}

		return operationList;
	}

	public URL getFileName() {
		return fileName;
	}

    /**
     * @deprecated please use getLastUpdate
     * @return
     */
    public long getLastupdate() {
		return lastupdate;
	}

    public long getLastUpdate() {
        return lastupdate;
    }

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

	public ArrayList<String> getModules() {
		return moduleRefs;
	}

	public String getName() {
		return name;
	}

	/**
	 * Method getOperation.
	 * 
	 * @param operationName
	 * @return Returns AxisOperation.
	 */
	public AxisOperation getOperation(QName operationName) {
        if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled())
            log.debug("Get operation for " + operationName);
                
		AxisOperation axisOperation = (AxisOperation) getChild(operationName);
		
        if (axisOperation == null) {
			axisOperation = (AxisOperation) getChild(new QName(
					getTargetNamespace(), operationName.getLocalPart()));
            
            if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled())
                log.debug("Target namespace: " + getTargetNamespace());
		}
        
		if (axisOperation == null) {
			axisOperation = (AxisOperation) operationsAliasesMap
					.get(operationName.getLocalPart());
            
            if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled())
                log.debug("Operations aliases map: " + operationsAliasesMap);
		}
        
        //The operation may be associated with a namespace other than the
        //target namespace, e.g. if the operation is from an imported wsdl.
        if (axisOperation == null) {            
            List namespaces = getImportedNamespaces();
            
            if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled())
                log.debug("Imported namespaces: " + namespaces);

            if (namespaces != null) {
                Iterator iterator = namespaces.iterator();
                
                while (iterator.hasNext()) {
                    String namespace = (String) iterator.next();
                    axisOperation = (AxisOperation) getChild(new QName(
                            namespace, operationName.getLocalPart()));
                    
                    if (axisOperation != null)
                        break;
                }
            }
        }

        if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled())
            log.debug("Found axis operation:  " + axisOperation);

		return axisOperation;
	}

	/**
	 * Returns the AxisOperation which has been mapped to the given alias.
	 * 
	 * @see #mapActionToOperation(String, AxisOperation)
	 * 
	 * @param action
	 *            the alias key
	 * @return Returns the corresponding AxisOperation or null if it isn't
	 *         found.
	 */
	public AxisOperation getOperationByAction(String action) {
		return (AxisOperation) operationsAliasesMap.get(action);
	}

	/**
	 * Returns the operation given a SOAP Action. This method should be called
	 * if only one Endpoint is defined for this Service. If more than one
	 * Endpoint exists, one of them will be picked. If more than one Operation
	 * is found with the given SOAP Action; null will be returned. If no
	 * particular Operation is found with the given SOAP Action; null will be
	 * returned. If the action is in the list of invaliad aliases, which means
	 * it did not uniquely identify an operation, a null will be returned.
	 * 
	 * @param soapAction
	 *            SOAP Action defined for the particular Operation
	 * @return Returns an AxisOperation if a unique Operation can be found with
	 *         the given SOAP Action otherwise will return null.
	 */
	public AxisOperation getOperationBySOAPAction(String soapAction) {

		// Check for illegal soapActions
		if ((soapAction == null) || soapAction.length() == 0) {
			if (log.isDebugEnabled()) {
				log.debug("getOperationBySOAPAction: " + soapAction
						+ " is null or ''. Returning null.");
			}
			return null;
		}

		// If the action maps to an alais that is not unique, then it can't be
		// used to map to
		// an operation.
		if (invalidOperationsAliases.contains(soapAction)) {
			if (log.isDebugEnabled()) {
				log.debug("getOperationBySOAPAction: " + soapAction
						+ " is an invalid operation alias. Returning null.");
			}
			return null;
		}

		// Get the operation from the action->operation map
		AxisOperation operation = (AxisOperation) operationsAliasesMap
				.get(soapAction);

		if (operation != null) {
			if (log.isDebugEnabled()) {
				log.debug("getOperationBySOAPAction: Operation (" + operation
						+ "," + operation.getName() + ") for soapAction: "
						+ soapAction + " found in action map.");
			}
			return operation;
		}

		// The final fallback is to check the operations for a matching name.

		Iterator children = getChildren();
		// I could not find any spec statement that explicitly forbids using a
		// short name in the SOAPAction header or wsa:Action element,
		// so I believe this to be valid. There may be customers using the
		// shortname as the SOAPAction in their client code that would
		// also require this support.
		while (children.hasNext() && (operation == null)) {
			AxisOperation op = (AxisOperation) children.next();
			if (op.getName().getLocalPart().equals(soapAction)) {
				operation = op;
			}
		}

		if (operation != null) {
			if (log.isDebugEnabled()) {
				log.debug("getOperationBySOAPAction: Operation (" + operation
						+ "," + operation.getName() + ") for soapAction: "
						+ soapAction + " found as child.");
			}
		}

		return operation;
	}

	/**
	 * Method getOperations.
	 * 
	 * @return Returns HashMap
	 */
	public Iterator<AxisOperation> getOperations() {
		return (Iterator<AxisOperation>) getChildren();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.axis2.description.ParameterInclude#getParameter(java.lang.String)
	 */

	/**
	 * Gets only the published operations.
	 */
	public ArrayList<AxisOperation> getPublishedOperations() {
		Iterator<AxisOperation> op_itr = getOperations();
		ArrayList<AxisOperation> operationList = new ArrayList<AxisOperation>();

		while (op_itr.hasNext()) {
			AxisOperation operation = (AxisOperation) op_itr.next();

			if (!operation.isControlOperation()) {
				operationList.add(operation);
			}
		}

		return operationList;
	}

	/**
	 * Sets the description about the service which is specified in services.xml
	 * 
	 * @param documentation
	 * @deprecated Use setDocumentation() instead
	 */
	public void setServiceDescription(String documentation) {
		setDocumentation(documentation);
	}

	/**
	 * Method setClassLoader.
	 * 
	 * @param classLoader
	 */
	public void setClassLoader(ClassLoader classLoader) {
		this.serviceClassLoader = classLoader;
	}

	public void setFileName(URL fileName) {
		this.fileName = fileName;
	}

	/**
	 * Sets the current time as last update time of the service.
     * @deprecated please use setLastUpdate
	 */
	public void setLastupdate() {
		lastupdate = new Date().getTime();
	}

    /**
     * Sets the current time as last update time of the service.
     */
    public void setLastUpdate() {
        lastupdate = new Date().getTime();
    }

	public void setName(String name) {
		this.name = name;
	}

	public ArrayList<XmlSchema> getSchema() {
		return schemaList;
	}

	public void addSchema(XmlSchema schema) {
		if (schema != null) {
			schemaList.add(schema);
			if (schema.getTargetNamespace() != null) {
				addSchemaNameSpace(schema);
			}
		}
	}

	public void addSchema(Collection<XmlSchema> schemas) {
		Iterator<XmlSchema> iterator = schemas.iterator();
		while (iterator.hasNext()) {
			XmlSchema schema = (XmlSchema) iterator.next();
			schemaList.add(schema);
			addSchemaNameSpace(schema);
		}
	}

	public boolean isWsdlFound() {
		return wsdlFound;
	}

	public void setWsdlFound(boolean wsdlFound) {
		this.wsdlFound = wsdlFound;
	}

	public String getScope() {
		return scope;
	}

	/**
	 * @param scope -
	 *            Available scopes : Constants.SCOPE_APPLICATION
	 *            Constants.SCOPE_TRANSPORT_SESSION Constants.SCOPE_SOAP_SESSION
	 *            Constants.SCOPE_REQUEST.equals
	 */
	public void setScope(String scope) {
		if (Constants.SCOPE_APPLICATION.equals(scope)
				|| Constants.SCOPE_TRANSPORT_SESSION.equals(scope)
				|| Constants.SCOPE_SOAP_SESSION.equals(scope)
				|| Constants.SCOPE_REQUEST.equals(scope)) {
			this.scope = scope;
		}
	}

	public boolean isUseDefaultChains() {
		return useDefaultChains;
	}

	public void setUseDefaultChains(boolean useDefaultChains) {
		this.useDefaultChains = useDefaultChains;
	}

	public Object getKey() {
		return this.name;
	}

	public boolean isActive() {
		return active;
	}

	public void setActive(boolean active) {
		this.active = active;
	}

    /**
     * @deprecated please use getSchemaTargetNamespace
     * @return
     */
    public String getSchematargetNamespace() {
        return schematargetNamespace;
    }

	public String getSchemaTargetNamespace() {
		return schematargetNamespace;
	}

	public void setSchemaTargetNamespace(String schematargetNamespace) {
		this.schematargetNamespace = schematargetNamespace;
	}

	public String getSchemaTargetNamespacePrefix() {
		return schematargetNamespacePrefix;
	}

    /**
     * @deprecated please use setSchemaTargetNamespacePrefix
     * @param schematargetNamespacePrefix
     */
    public void setSchematargetNamespacePrefix(
            String schematargetNamespacePrefix) {
        this.schematargetNamespacePrefix = schematargetNamespacePrefix;
    }

	public void setSchemaTargetNamespacePrefix(
			String schematargetNamespacePrefix) {
		this.schematargetNamespacePrefix = schematargetNamespacePrefix;
	}

	public String getTargetNamespace() {
		return targetNamespace;
	}

	public void setTargetNamespace(String targetNamespace) {
		this.targetNamespace = targetNamespace;
	}

	public String getTargetNamespacePrefix() {
		return targetNamespacePrefix;
	}

	public void setTargetNamespacePrefix(String targetNamespacePrefix) {
		this.targetNamespacePrefix = targetNamespacePrefix;
	}

	public XmlSchemaElement getSchemaElement(QName elementQName) {
		XmlSchemaElement element;
		for (int i = 0; i < schemaList.size(); i++) {
			XmlSchema schema = (XmlSchema) schemaList.get(i);
			if (schema != null) {
				element = schema.getElementByName(elementQName);
				if (element != null) {
					return element;
				}
			}
		}
		return null;
	}

	public boolean isEnableAllTransports() {
		return enableAllTransports;
	}

	/**
	 * To eneble service to be expose in all the transport
	 * 
	 * @param enableAllTransports
	 */
	public void setEnableAllTransports(boolean enableAllTransports) {
		this.enableAllTransports = enableAllTransports;
		eprs = calculateEPRs();
	}

	public List<String> getExposedTransports() {
		return this.exposedTransports;
	}

	public void setExposedTransports(List transports) {
		enableAllTransports = false;
		this.exposedTransports = transports;
		eprs = null; // Do not remove this. We need to force EPR
						// recalculation.
	}

	public void addExposedTransport(String transport) {
		enableAllTransports = false;
		if (!this.exposedTransports.contains(transport)) {
			this.exposedTransports.add(transport);
			try {
				eprs = calculateEPRs();
			} catch (Exception e) {
				eprs = null;
			}
		}
	}

	public void removeExposedTransport(String transport) {
		enableAllTransports = false;
		this.exposedTransports.remove(transport);
		try {
			eprs = calculateEPRs();
		} catch (Exception e) {
			eprs = null;
		}
	}

	public boolean isExposedTransport(String transport) {
		return exposedTransports.contains(transport);
	}

	public void onDisengage(AxisModule module) throws AxisFault {
		removeModuleOperations(module);
		for (Iterator operations = getChildren(); operations.hasNext();) {
			AxisOperation axisOperation = (AxisOperation) operations.next();
			axisOperation.disengageModule(module);
		}
		AxisConfiguration config = getAxisConfiguration();
		if (!config.isEngaged(module.getName())) {
			PhaseResolver phaseResolver = new PhaseResolver(config);
			phaseResolver.disengageModuleFromGlobalChains(module);
		}
	}

	/**
	 * Remove any operations which were added by a given module.
	 * 
	 * @param module
	 *            the module in question
	 */
	private void removeModuleOperations(AxisModule module) {
		HashMap<QName, AxisOperation> moduleOperations = module.getOperations();
		if (moduleOperations != null) {
			for (Iterator<AxisOperation> modOpsIter = moduleOperations.values().iterator(); modOpsIter
					.hasNext();) {
				AxisOperation operation = (AxisOperation) modOpsIter.next();
				removeOperation(operation.getName());
			}
		}
	}

	// #######################################################################################
	// APIs to create AxisService

	//

	/**
	 * To create a AxisService for a given WSDL and the created client is most
	 * suitable for client side invocation not for server side invocation. Since
	 * all the soap action and wsa action is added to operations
	 * 
	 * @param wsdlURL
	 *            location of the WSDL
	 * @param wsdlServiceName
	 *            name of the service to be invoke , if it is null then the
	 *            first one will be selected if there are more than one
	 * @param portName
	 *            name of the port , if there are more than one , if it is null
	 *            then the first one in the iterator will be selected
	 * @param options
	 *            Service client options, to set the target EPR
	 * @return AxisService , the created service will be return
	 */
	public static AxisService createClientSideAxisService(URL wsdlURL,
			QName wsdlServiceName, String portName, Options options)
			throws AxisFault {
		try {
			InputStream in = wsdlURL.openConnection().getInputStream();
			Document doc = XMLUtils.newDocument(in);
			WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
			reader.setFeature("javax.wsdl.importDocuments", true);
			Definition wsdlDefinition = reader.readWSDL(getBaseURI(wsdlURL
					.toString()), doc);
			if (wsdlDefinition != null) {
				wsdlDefinition.setDocumentBaseURI(getDocumentURI(wsdlURL
						.toString()));
			}
			return createClientSideAxisService(wsdlDefinition, wsdlServiceName,
					portName, options);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			throw AxisFault.makeFault(e);
		} catch (ParserConfigurationException e) {
			log.error(e.getMessage(), e);
			throw AxisFault.makeFault(e);
		} catch (SAXException e) {
			log.error(e.getMessage(), e);
			throw AxisFault.makeFault(e);
		} catch (WSDLException e) {
			log.error(e.getMessage(), e);
			throw AxisFault.makeFault(e);
		}
	}

	private static String getBaseURI(String currentURI) {
		try {
			File file = new File(currentURI);
			if (file.exists()) {
				return file.getCanonicalFile().getParentFile().toURI()
						.toString();
			}
			String uriFragment = currentURI.substring(0, currentURI
					.lastIndexOf("/"));
			return uriFragment + (uriFragment.endsWith("/") ? "" : "/");
		} catch (IOException e) {
			return null;
		}
	}

	private static String getDocumentURI(String currentURI) {
		try {
			File file = new File(currentURI);
			return file.getCanonicalFile().toURI().toString();
		} catch (IOException e) {
			return null;
		}
	}

	public static AxisService createClientSideAxisService(
			Definition wsdlDefinition, QName wsdlServiceName, String portName,
			Options options) throws AxisFault {
		WSDL11ToAxisServiceBuilder serviceBuilder = new WSDL11ToAxisServiceBuilder(
				wsdlDefinition, wsdlServiceName, portName);
		serviceBuilder.setServerSide(false);
		AxisService axisService = serviceBuilder.populateService();
		AxisEndpoint axisEndpoint = (AxisEndpoint) axisService.getEndpoints()
				.get(axisService.getEndpointName());
		options.setTo(new EndpointReference(axisEndpoint.getEndpointURL()));
		if (axisEndpoint != null) {
			options.setSoapVersionURI((String) axisEndpoint.getBinding()
					.getProperty(WSDL2Constants.ATTR_WSOAP_VERSION));
		}
		return axisService;
	}

	/**
	 * To create an AxisService using given service impl class name first
	 * generate schema corresponding to the given java class , next for each
	 * methods AxisOperation will be created. If the method is in-out it will
	 * uses RPCMessageReceiver else RPCInOnlyMessageReceiver <p/> Note : Inorder
	 * to work this properly RPCMessageReceiver should be available in the class
	 * path otherewise operation can not continue
	 * 
	 * @param implClass
	 *            Service implementation class
	 * @param axisConfig
	 *            Current AxisConfiguration
	 * @return return created AxisSrevice the creted service , it can either be
	 *         null or valid service
	 */
	public static AxisService createService(String implClass,
			AxisConfiguration axisConfig) throws AxisFault {

		try {
			HashMap<String, MessageReceiver> messageReciverMap = new HashMap<String, MessageReceiver>();
			Class inOnlyMessageReceiver = Loader
					.loadClass("org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver");
			MessageReceiver messageReceiver = (MessageReceiver) inOnlyMessageReceiver
					.newInstance();
			messageReciverMap.put(WSDL2Constants.MEP_URI_IN_ONLY,
					messageReceiver);
			Class inoutMessageReceiver = Loader
					.loadClass("org.apache.axis2.rpc.receivers.RPCMessageReceiver");
			MessageReceiver inOutmessageReceiver = (MessageReceiver) inoutMessageReceiver
					.newInstance();
			messageReciverMap.put(WSDL2Constants.MEP_URI_IN_OUT,
					inOutmessageReceiver);
			messageReciverMap.put(WSDL2Constants.MEP_URI_ROBUST_IN_ONLY,
					inOutmessageReceiver);

			return createService(implClass, axisConfig, messageReciverMap,
					null, null, axisConfig.getSystemClassLoader());
		} catch (Exception e) {
			throw AxisFault.makeFault(e);
		}
	}

	/**
	 * messageReceiverClassMap will hold the MessageReceivers for given meps.
	 * Key will be the mep and value will be the instance of the MessageReceiver
	 * class. Ex: Map mrMap = new HashMap();
	 * mrMap.put("http://www.w3.org/2004/08/wsdl/in-only",
	 * RPCInOnlyMessageReceiver.class.newInstance());
	 * mrMap.put("http://www.w3.org/2004/08/wsdl/in-out",
	 * RPCMessageReceiver.class.newInstance());
	 * 
	 * @param implClass
	 * @param axisConfiguration
	 * @param messageReceiverClassMap
	 * @param targetNamespace
	 * @param schemaNamespace
	 * @throws AxisFault
	 */
	public static AxisService createService(String implClass,
			AxisConfiguration axisConfiguration, Map messageReceiverClassMap,
			String targetNamespace, String schemaNamespace, ClassLoader loader)
			throws AxisFault {
		int index = implClass.lastIndexOf(".");
		String serviceName;
		if (index > 0) {
			serviceName = implClass.substring(index + 1, implClass.length());
		} else {
			serviceName = implClass;
		}

		SchemaGenerator schemaGenerator;
		ArrayList excludeOpeartion = new ArrayList();
		AxisService service = new AxisService();
		service.setParent(axisConfiguration);
		service.setName(serviceName);

		try {
			Parameter generateBare = service
					.getParameter(Java2WSDLConstants.DOC_LIT_BARE_PARAMETER);
			if (generateBare != null && "true".equals(generateBare.getValue())) {
				schemaGenerator = new DocLitBareSchemaGenerator(loader,
						implClass, schemaNamespace,
						Java2WSDLConstants.SCHEMA_NAMESPACE_PRFIX, service);
			} else {
				schemaGenerator = new DefaultSchemaGenerator(loader, implClass,
						schemaNamespace,
						Java2WSDLConstants.SCHEMA_NAMESPACE_PRFIX, service);
			}
			schemaGenerator
					.setElementFormDefault(Java2WSDLConstants.FORM_DEFAULT_UNQUALIFIED);
			Utils.addExcludeMethods(excludeOpeartion);
			schemaGenerator.setExcludeMethods(excludeOpeartion);
		} catch (Exception e) {
			throw AxisFault.makeFault(e);
		}

		return createService(implClass, serviceName, axisConfiguration,
				messageReceiverClassMap, targetNamespace, loader,
				schemaGenerator, service);
	}

	/**
	 * messageReceiverClassMap will hold the MessageReceivers for given meps.
	 * Key will be the mep and value will be the instance of the MessageReceiver
	 * class. Ex: Map mrMap = new HashMap();
	 * mrMap.put("http://www.w3.org/2004/08/wsdl/in-only",
	 * RPCInOnlyMessageReceiver.class.newInstance());
	 * mrMap.put("http://www.w3.org/2004/08/wsdl/in-out",
	 * RPCMessageReceiver.class.newInstance());
	 * 
	 * @param implClass
	 * @param axisConfiguration
	 * @param messageReceiverClassMap
	 * @param targetNamespace
	 * @throws AxisFault
	 */
	public static AxisService createService(String implClass,
			String serviceName, AxisConfiguration axisConfiguration,
			Map<String, MessageReceiver> messageReceiverClassMap, String targetNamespace,
			ClassLoader loader, SchemaGenerator schemaGenerator,
			AxisService axisService) throws AxisFault {
		Parameter parameter = new Parameter(Constants.SERVICE_CLASS, implClass);
		OMElement paraElement = Utils.getParameter(Constants.SERVICE_CLASS,
				implClass, false);
		parameter.setParameterElement(paraElement);
		axisService.setUseDefaultChains(false);
		axisService.addParameter(parameter);
		axisService.setName(serviceName);
		axisService.setClassLoader(loader);

		NamespaceMap map = new NamespaceMap();
		map.put(Java2WSDLConstants.AXIS2_NAMESPACE_PREFIX,
				Java2WSDLConstants.AXIS2_XSD);
		map.put(Java2WSDLConstants.DEFAULT_SCHEMA_NAMESPACE_PREFIX,
				Java2WSDLConstants.URI_2001_SCHEMA_XSD);
		axisService.setNamespaceMap(map);
		Utils.processBeanPropertyExclude(axisService);
		axisService.setElementFormDefault(false);
		try {
			axisService.addSchema(schemaGenerator.generateSchema());
		} catch (Exception e) {
			throw AxisFault.makeFault(e);
		}
		axisService.setSchemaTargetNamespace(schemaGenerator
				.getSchemaTargetNameSpace());
		axisService.setTypeTable(schemaGenerator.getTypeTable());
		if (targetNamespace == null) {
			targetNamespace = schemaGenerator.getSchemaTargetNameSpace();
		}
		if (targetNamespace != null && !"".equals(targetNamespace)) {
			axisService.setTargetNamespace(targetNamespace);
		}
		Method[] method = schemaGenerator.getMethods();
		PhasesInfo pinfo = axisConfiguration.getPhasesInfo();
		for (int i = 0; i < method.length; i++) {
			Method jmethod = method[i];
			AxisOperation operation = axisService.getOperation(new QName(
					jmethod.getName()));
			String mep = operation.getMessageExchangePattern();
			MessageReceiver mr;
			if (messageReceiverClassMap != null) {

				if (messageReceiverClassMap.get(mep) != null) {
					Object obj = messageReceiverClassMap.get(mep);
					if (obj instanceof MessageReceiver) {
						mr = (MessageReceiver) obj;
						operation.setMessageReceiver(mr);
					} else {
						log
								.error("Object is not an instance of MessageReceiver, thus, default MessageReceiver has been set");
						mr = axisConfiguration.getMessageReceiver(operation
								.getMessageExchangePattern());
						operation.setMessageReceiver(mr);
					}
				} else {
					log
							.error("Required MessageReceiver couldn't be found, thus, default MessageReceiver has been used");
					mr = axisConfiguration.getMessageReceiver(operation
							.getMessageExchangePattern());
					operation.setMessageReceiver(mr);
				}
			} else {
				log
						.error("MessageRecevierClassMap couldn't be found, thus, default MessageReceiver has been used");
				mr = axisConfiguration.getMessageReceiver(operation
						.getMessageExchangePattern());
				operation.setMessageReceiver(mr);
			}
			pinfo.setOperationPhases(operation);
			axisService.addOperation(operation);
		}

		String endpointName = axisService.getEndpointName();
		if ((endpointName == null || endpointName.length() == 0)
				&& axisService.getAxisConfiguration() != null) {
			Utils.addEndpointsToService(axisService, axisService.getAxisConfiguration());
		}

		return axisService;

	}

	public void removeOperation(QName opName) {
		AxisOperation operation = getOperation(opName);
		if (operation != null) {
			removeChild(opName);
			ArrayList<String> mappingList = operation.getWSAMappingList();
			if (mappingList != null) {
				for (int i = 0; i < mappingList.size(); i++) {
					String actionMapping = (String) mappingList.get(i);
					operationsAliasesMap.remove(actionMapping);
				}
			}
			operationsAliasesMap.remove(operation.getName().getLocalPart());
		}
	}

	/**
	 * Get the namespace map for this service.
	 * 
	 * @return a Map of prefix (String) to namespace URI (String)
	 * @deprecated please use getNamespaceMap()
	 */
	public Map<String, String> getNameSpacesMap() {
		return namespaceMap;
	}

	/**
	 * Get the namespace map for this service.
	 * 
	 * @return a Map of prefix (String) to namespace URI (String)
	 */
	public Map getNamespaceMap() {
		return namespaceMap;
	}
    
    /**
     * Get the namespaces associated with imported WSDLs
     * 
     * @return a <code>List</code> of namespace URIs (String)
     */
    public List getImportedNamespaces() {
        return importedNamespaces;
    }

    /**
     * Set the namespaces associated with imported WSDLs
     * 
     * @param importedNamespaces
     */
    public void setImportedNamespaces(List importedNamespaces) {
        this.importedNamespaces = importedNamespaces;
    }
    
    /**
     * @deprecated please use setNamespaceMap
     * @param nameSpacesMap
     */
    public void setNameSpacesMap(NamespaceMap nameSpacesMap) {
		this.namespaceMap = nameSpacesMap;
	}

	public void setNamespaceMap(NamespaceMap namespaceMap) {
		this.namespaceMap = namespaceMap;
	}

	private void addSchemaNameSpace(XmlSchema schema) {
		String targetNameSpace = schema.getTargetNamespace();
		String prefix = schema.getNamespaceContext().getPrefix(targetNameSpace);

		if (namespaceMap == null) {
			namespaceMap = new NamespaceMap();
		}

		if (!namespaceMap.values().contains(targetNameSpace)) {
			// i.e this target namespace not exists in the namesapce map
			// find a non exists prefix to add this target namesapce
			while ((prefix == null) || namespaceMap.keySet().contains(prefix)) {
				prefix = "ns" + nsCount++;
			}
			namespaceMap.put(prefix, targetNameSpace);
		}

	}

	public Map populateSchemaMappings() {
		// when calling from other than codegen. i.e from deployment
		// engine we don't have to override the absolute http locations.
		return populateSchemaMappings(false);
	}

	/**
	 * runs the schema mappings if it has not been run previously it is best
	 * that this logic be in the axis service since one can call the axis
	 * service to populate the schema mappings
	 */
	public Map populateSchemaMappings(boolean overrideAbsoluteAddress) {

		// populate the axis service with the necessary schema references
		ArrayList schema = this.schemaList;
		Map changedSchemaLocations = null;
		if (!this.schemaLocationsAdjusted) {
			Hashtable nameTable = new Hashtable();
			Hashtable sourceURIToNewLocationMap = new Hashtable();
			// calculate unique names for the schemas
			calculateSchemaNames(schema, nameTable, sourceURIToNewLocationMap,
					overrideAbsoluteAddress);
			// adjust the schema locations as per the calculated names
			changedSchemaLocations = adjustSchemaNames(schema, nameTable,
					sourceURIToNewLocationMap);
			// reverse the nametable so that there is a mapping from the
			// name to the schemaObject
			setSchemaMappingTable(swapMappingTable(nameTable));
			setSchemaLocationsAdjusted(true);
		}
		return changedSchemaLocations;
	}

	/**
	 * run 1 -calcualte unique names
	 * 
	 * @param schemas
	 */
	private void calculateSchemaNames(List schemas, Hashtable nameTable,
			Hashtable sourceURIToNewLocationMap, boolean overrideAbsoluteAddress) {
		// first traversal - fill the hashtable
		for (int i = 0; i < schemas.size(); i++) {
			XmlSchema schema = (XmlSchema) schemas.get(i);
			XmlSchemaObjectCollection includes = schema.getIncludes();

			for (int j = 0; j < includes.getCount(); j++) {
				Object item = includes.getItem(j);
				XmlSchema s;
				if (item instanceof XmlSchemaExternal) {
					XmlSchemaExternal externalSchema = (XmlSchemaExternal) item;
					s = externalSchema.getSchema();

					if (s != null
							&& getScheamLocationWithDot(
									sourceURIToNewLocationMap, s) == null) {
						// insert the name into the table
						insertIntoNameTable(nameTable, s,
								sourceURIToNewLocationMap,
								overrideAbsoluteAddress);
						// recursively call the same procedure
						calculateSchemaNames(Arrays
								.asList(new XmlSchema[] { s }), nameTable,
								sourceURIToNewLocationMap,
								overrideAbsoluteAddress);
					}
				}
			}
		}
	}

	/**
	 * A quick private sub routine to insert the names
	 * 
	 * @param nameTable
	 * @param s
	 */
	private void insertIntoNameTable(Hashtable nameTable, XmlSchema s,
			Hashtable sourceURIToNewLocationMap, boolean overrideAbsoluteAddress) {
		String sourceURI = s.getSourceURI();
		// check whether the sourece uri is an absolute one and are
		// we allowed to override it.
		// if the absolute uri overriding is not allowed the use the
		// original sourceURI as new one
		if (sourceURI.startsWith("http") && !overrideAbsoluteAddress) {
			nameTable.put(s, sourceURI);
			sourceURIToNewLocationMap.put(sourceURI, sourceURI);
		} else {
			String newURI = sourceURI.substring(sourceURI.lastIndexOf('/') + 1);
			if (newURI.endsWith(".xsd")) {
				// remove the .xsd extention
				newURI = newURI.substring(0, newURI.lastIndexOf("."));
			} else {
				newURI = "xsd" + count++;
			}

			newURI = customSchemaNameSuffix != null ? newURI
					+ customSchemaNameSuffix : newURI;
			// make it unique
			while (nameTable.containsValue(newURI)) {
				newURI = newURI + count++;
			}

			nameTable.put(s, newURI);
			sourceURIToNewLocationMap.put(sourceURI, newURI);
		}

	}

	/**
	 * Run 2 - adjust the names
	 */
	private Map adjustSchemaNames(List schemas, Hashtable nameTable,
			Hashtable sourceURIToNewLocationMap) {
		Hashtable importedSchemas = new Hashtable();
		// process the schemas in the main schema list
		for (int i = 0; i < schemas.size(); i++) {
			adjustSchemaName((XmlSchema) schemas.get(i), nameTable,
					importedSchemas, sourceURIToNewLocationMap);
		}
		// process all the rest in the name table
		Enumeration nameTableKeys = nameTable.keys();
		while (nameTableKeys.hasMoreElements()) {
			adjustSchemaName((XmlSchema) nameTableKeys.nextElement(),
					nameTable, importedSchemas, sourceURIToNewLocationMap);

		}
		return importedSchemas;
	}

	/**
	 * Adjust a single schema
	 * 
	 * @param parentSchema
	 * @param nameTable
	 */
	private void adjustSchemaName(XmlSchema parentSchema, Hashtable nameTable,
			Hashtable importedScheams, Hashtable sourceURIToNewLocationMap) {
		XmlSchemaObjectCollection includes = parentSchema.getIncludes();
		for (int j = 0; j < includes.getCount(); j++) {
			Object item = includes.getItem(j);
			if (item instanceof XmlSchemaExternal) {
				XmlSchemaExternal xmlSchemaExternal = (XmlSchemaExternal) item;
				XmlSchema s = xmlSchemaExternal.getSchema();
				adjustSchemaLocation(s, xmlSchemaExternal, nameTable,
						importedScheams, sourceURIToNewLocationMap);
			}
		}

	}
		
	/**
	 * Adjusts a given schema location
	 * 
	 * @param s
	 * @param xmlSchemaExternal
	 * @param nameTable
	 */
    private void adjustSchemaLocation(XmlSchema s,
                                      XmlSchemaExternal xmlSchemaExternal, Hashtable nameTable,
                                      Hashtable importedScheams, Hashtable sourceURIToNewLocationMap) {
        if (s != null) {
            String schemaLocation = xmlSchemaExternal.getSchemaLocation();

            String newscheamlocation = customSchemaNamePrefix == null ?
                    // use the default mode
                    (this.getServiceEPR() + "?xsd=" + getScheamLocationWithDot(
                            sourceURIToNewLocationMap, s))
                    :
                    // custom prefix is present - add the custom prefix
                    (customSchemaNamePrefix + getScheamLocationWithDot(
                            sourceURIToNewLocationMap, s));
            xmlSchemaExternal.setSchemaLocation(newscheamlocation);
            importedScheams.put(schemaLocation, newscheamlocation);
        }
    }

	private Object getScheamLocationWithDot(
			Hashtable sourceURIToNewLocationMap, XmlSchema s) {
		String o = (String) sourceURIToNewLocationMap.get(s.getSourceURI());
		if (o != null && o.indexOf(".") < 0) {
			return o + ".xsd";
		}
		return o;
	}

	/**
	 * Swap the key,value pairs
	 * 
	 * @param originalTable
	 */
	private Map swapMappingTable(Map originalTable) {
		HashMap swappedTable = new HashMap(originalTable.size());
		Iterator keys = originalTable.keySet().iterator();
		Object key;
		while (keys.hasNext()) {
			key = keys.next();
			swappedTable.put(originalTable.get(key), key);
		}

		return swappedTable;
	}

	public boolean isClientSide() {
		return clientSide;
	}

	public void setClientSide(boolean clientSide) {
		this.clientSide = clientSide;
	}

	public boolean isElementFormDefault() {
		return elementFormDefault;
	}

	public void setElementFormDefault(boolean elementFormDefault) {
		this.elementFormDefault = elementFormDefault;
	}

	/**
	 * User can set a parameter in services.xml saying he want to show the
	 * original wsdl that he put into META-INF once someone ask for ?wsdl so if
	 * you want to use your own wsdl then add following parameter into
	 * services.xml <parameter name="useOriginalwsdl">true</parameter>
	 */
	public boolean isUseUserWSDL() {
		Parameter parameter = getParameter("useOriginalwsdl");
		if (parameter != null) {
			String value = (String) parameter.getValue();
			if ("true".equals(value)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * By default the port address in user WSDLs is modified, set the following
	 * parameter to override this behaviour <parameter
	 * name="modifyUserWSDLPortAddress">false</parameter>
	 */
	public boolean isModifyUserWSDLPortAddress() {
		Parameter parameter = getParameter("modifyUserWSDLPortAddress");
		if (parameter != null) {
			String value = (String) parameter.getValue();
			if ("false".equals(value)) {
				return false;
			}
		}
		return true;
	}

	public ServiceLifeCycle getServiceLifeCycle() {
		return serviceLifeCycle;
	}

	public void setServiceLifeCycle(ServiceLifeCycle serviceLifeCycle) {
		this.serviceLifeCycle = serviceLifeCycle;
	}

	public Map getP2nMap() {
		return p2nMap;
	}

	public void setP2nMap(Map p2nMap) {
		this.p2nMap = p2nMap;
	}

	public ObjectSupplier getObjectSupplier() {
		return objectSupplier;
	}

	public void setObjectSupplier(ObjectSupplier objectSupplier) {
		this.objectSupplier = objectSupplier;
	}

	public TypeTable getTypeTable() {
		return typeTable;
	}

	public void setTypeTable(TypeTable typeTable) {
		this.typeTable = typeTable;
	}

	/**
	 * Find a data locator from the available data locators (both configured and
	 * default ones) to retrieve Metadata or data specified in the request.
	 * 
	 * @param request
	 *            an {@link DataRetrievalRequest} object
	 * @param msgContext
	 *            message context
	 * @return array of {@link Data} object for the request.
	 * @throws AxisFault
	 */

	public Data[] getData(DataRetrievalRequest request,
			MessageContext msgContext) throws AxisFault {

		Data[] data;
		String dialect = request.getDialect();
		AxisDataLocator dataLocator = null;
		int nextDataLocatorIndex = 0;
		int totalLocators = availableDataLocatorTypes.length;
		for (int i = 0; i < totalLocators; i++) {
			dataLocator = getDataLocator(availableDataLocatorTypes[i], dialect);
			if (dataLocator != null) {
				nextDataLocatorIndex = i + 1;
				break;
			}
		}

		if (dataLocator == null) {
			return null;
		}

		data = dataLocator.getData(request, msgContext);
		// Null means Data Locator not understood request. Automatically find
		// Data Locator in the hierarchy to process the request.
		if (data == null) {
			if (nextDataLocatorIndex < totalLocators) {
				data = bubbleupDataLocators(nextDataLocatorIndex, request,
						msgContext);
			}

		}
		return data;
	}

	/*
	 * To search the next Data Locator from the available Data Locators that
	 * understood the data retrieval request.
	 */
	private Data[] bubbleupDataLocators(int nextIndex,
			DataRetrievalRequest request, MessageContext msgContext)
			throws AxisFault {
		Data[] data = null;
		if (nextIndex < availableDataLocatorTypes.length) {
			AxisDataLocator dataLocator = getDataLocator(
					availableDataLocatorTypes[nextIndex], request.getDialect());
			nextIndex++;
			if (dataLocator != null) {
				data = dataLocator.getData(request, msgContext);
				if (data == null) {
					data = bubbleupDataLocators(nextIndex, request, msgContext);
				} else {
					return data;
				}

			} else {
				data = bubbleupDataLocators(nextIndex, request, msgContext);
			}

		}
		return data;
	}

	/**
	 * Save data Locator configured at service level for this Axis Service
	 * 
	 * @param dialect-
	 *            an absolute URI represents the Dialect i.e. WSDL, Policy,
	 *            Schema or "ServiceLevel" for non-dialect service level data
	 *            locator.
	 * @param dataLocatorClassName -
	 *            class name of the Data Locator configured to support data
	 *            retrieval for the specified dialect.
	 */
	public void addDataLocatorClassNames(String dialect,
			String dataLocatorClassName) {
		dataLocatorClassNames.put(dialect, dataLocatorClassName);
	}

	/*
	 * Get data locator instance based on the LocatorType and dialect.
	 */
	public AxisDataLocator getDataLocator(LocatorType locatorType,
			String dialect) throws AxisFault {
		AxisDataLocator locator;
		if (locatorType == LocatorType.SERVICE_DIALECT) {
			locator = getServiceDataLocator(dialect);
		} else if (locatorType == LocatorType.SERVICE_LEVEL) {
			locator = getServiceDataLocator(DRConstants.SERVICE_LEVEL);
		} else if (locatorType == LocatorType.GLOBAL_DIALECT) {
			locator = getGlobalDataLocator(dialect);
		} else if (locatorType == LocatorType.GLOBAL_LEVEL) {
			locator = getGlobalDataLocator(DRConstants.GLOBAL_LEVEL);
		} else if (locatorType == LocatorType.DEFAULT_AXIS) {
			locator = getDefaultDataLocator();
		} else {
			locator = getDefaultDataLocator();
		}

		return locator;
	}

	// Return default Axis2 Data Locator
	private AxisDataLocator getDefaultDataLocator()
			throws DataRetrievalException {

		if (defaultDataLocator == null) {
			defaultDataLocator = new AxisDataLocatorImpl(this);
		}

		defaultDataLocator.loadServiceData();

		return defaultDataLocator;
	}

	/*
	 * Checks if service level data locator configured for specified dialect.
	 * Returns an instance of the data locator if exists, and null otherwise.
	 */
	private AxisDataLocator getServiceDataLocator(String dialect)
			throws AxisFault {
		AxisDataLocator locator;
		locator = (AxisDataLocator) dataLocators.get(dialect);
		if (locator == null) {
			String className = (String) dataLocatorClassNames.get(dialect);
			if (className != null) {
				locator = loadDataLocator(className);
				dataLocators.put(dialect, locator);
			}

		}

		return locator;

	}

	/*
	 * Checks if global level data locator configured for specified dialect.
	 * @param dialect- an absolute URI represents the Dialect i.e. WSDL, Policy,
	 * Schema or "GlobalLevel" for non-dialect Global level data locator.
	 * Returns an instance of the data locator if exists, and null otherwise.
	 */

	public AxisDataLocator getGlobalDataLocator(String dialect)
			throws AxisFault {
		AxisConfiguration axisConfig = getAxisConfiguration();
		AxisDataLocator locator = null;
		if (axisConfig != null) {
			locator = axisConfig.getDataLocator(dialect);
			if (locator == null) {
				String className = axisConfig.getDataLocatorClassName(dialect);
				if (className != null) {
					locator = loadDataLocator(className);
					axisConfig.addDataLocator(dialect, locator);
				}
			}
		}

		return locator;

	}

	protected AxisDataLocator loadDataLocator(String className)
			throws AxisFault {

		AxisDataLocator locator;

		try {
			Class dataLocator;
			dataLocator = Class.forName(className, true, serviceClassLoader);
			locator = (AxisDataLocator) dataLocator.newInstance();
		} catch (ClassNotFoundException e) {
			throw AxisFault.makeFault(e);
		} catch (IllegalAccessException e) {
			throw AxisFault.makeFault(e);
		} catch (InstantiationException e) {
			throw AxisFault.makeFault(e);

		}

		return locator;
	}

	/**
	 * Set the map of WSDL message element QNames to AxisOperations for this
	 * service. This map is used during SOAP Body-based routing for
	 * document/literal bare services to match the first child element of the
	 * SOAP Body element to an operation. (Routing for RPC and document/literal
	 * wrapped services occurs via the operationsAliasesMap.) <p/> From section
	 * 4.7.6 of the WS-I BP 1.1: the "operation signature" is "the fully
	 * qualified name of the child element of SOAP body of the SOAP input
	 * message described by an operation in a WSDL binding," and thus this map
	 * must be from a QName to an operation.
	 * 
	 * @param messageElementQNameToOperationMap
	 *            The map from WSDL message element QNames to AxisOperations.
	 */
	public void setMessageElementQNameToOperationMap(
			Map messageElementQNameToOperationMap) {
		this.messageElementQNameToOperationMap = messageElementQNameToOperationMap;
	}

	/**
	 * Look up an AxisOperation for this service based off of an element QName
	 * from a WSDL message element.
	 * 
	 * @param messageElementQName
	 *            The QName to search for.
	 * @return The AxisOperation registered to the QName or null if no match was
	 *         found.
	 * @see #setMessageElementQNameToOperationMap(Map)
	 */
	public AxisOperation getOperationByMessageElementQName(
			QName messageElementQName) {
		return (AxisOperation) messageElementQNameToOperationMap
				.get(messageElementQName);
	}

	/**
	 * Add an entry to the map between element QNames in WSDL messages and
	 * AxisOperations for this service.
	 * 
	 * @param messageElementQName
	 *            The QName of the element on the input message that maps to the
	 *            given operation.
	 * @param operation
	 *            The AxisOperation to be mapped to.
	 * @see #setMessageElementQNameToOperationMap(Map)
	 */
	public void addMessageElementQNameToOperationMapping(
			QName messageElementQName, AxisOperation operation) {
		// when setting an operation we have to set it only if the
		// messegeElementQName does not
		// exists in the map.
		// does exists means there are two or more operations which has the same
		// input element (in doc/literal
		// this is possible. In this case better to set it as null without
		// giving
		// a random operation.
		if (messageElementQNameToOperationMap.containsKey(messageElementQName)
				&& messageElementQNameToOperationMap.get(messageElementQName) != operation) {
			messageElementQNameToOperationMap.put(messageElementQName, null);
		} else {
			messageElementQNameToOperationMap.put(messageElementQName,
					operation);
		}

	}

	// @deprecated - use getEndpointURL in axisEndpoint
	public String getEndpointURL() {
		return endpointURL;
	}

	// @deprecated - use setEndpointURL in axisEndpoint
	public void setEndpointURL(String endpointURL) {
		this.endpointURL = endpointURL;
	}

	// TODO : Explain what goes in this map!
	public Map<String, AxisEndpoint> getEndpoints() {
		return endpointMap;
	}

	public boolean isCustomWsdl() {
		return customWsdl;
	}

	public void setCustomWsdl(boolean customWsdl) {
		this.customWsdl = customWsdl;
	}

	public List getOperationsNameList() {
		return operationsNameList;
	}

	public void setOperationsNameList(List operationsNameList) {
		this.operationsNameList = operationsNameList;
	}

	public AxisServiceGroup getAxisServiceGroup() {
		return (AxisServiceGroup) parent;
	}

	public void setParent(AxisServiceGroup parent) {
		this.parent = parent;
	}

	public String toString() {
		return getName();
	}

	public ExcludeInfo getExcludeInfo() {
		return excludeInfo;
	}

	public void setExcludeInfo(ExcludeInfo excludeInfo) {
		this.excludeInfo = excludeInfo;
	}

	public void registerPolicy(String key, Policy policy) {
		policyMap.put(key, policy);
	}

	public Policy lookupPolicy(String key) {
		return (Policy) policyMap.get(key);
	}
    
    /**
     * Add a ServiceContextListener
     * @param scl
     */
    public void addMessageContextListener(MessageContextListener scl) {
        messageContextListeners.add(scl);
    }
    
    /**
     * Remove a ServiceContextListener
     * @param scl
     */
    public void removeMessageContextListener(MessageContextListener scl) {
        messageContextListeners.remove(scl);
    }
    
    /**
     * @param cls Class of ServiceContextListener
     * @return true if ServiceContextLister is in the list
     */
    public boolean hasMessageContextListener(Class cls) {
        for (int i=0; i<messageContextListeners.size(); i++) {
            if (messageContextListeners.get(i).getClass() == cls) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * Signal an Attach ServiceContext Event
     * @param sc ServiceContext
     * @param mc MessageContext
     */
    public void attachServiceContextEvent(ServiceContext sc, MessageContext mc) {
        for (int i=0; i<messageContextListeners.size(); i++) {
            messageContextListeners.get(i).attachServiceContextEvent(sc, mc);
        }
    }
    
    /**
     * Signal an Attach Envelope Event
     * @param mc MessageContext
     */
    public void attachEnvelopeEvent(MessageContext mc) {
        for (int i=0; i<messageContextListeners.size(); i++) {
            messageContextListeners.get(i).attachEnvelopeEvent(mc);
        }
    }
}
