/*
 * 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.jsr181.WebMethodAnnotation;
import org.apache.axis2.jsr181.JSR181Helper;
import org.apache.axis2.addressing.AddressingHelper;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.addressing.AddressingConstants;
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.woden.WSDLSource;
import org.apache.woden.wsdl20.Description;
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.extensions.UnknownExtensibilityElement;
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.URISyntaxException;
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;
    
    // Excluded operations name list to know which operations to exclude.
    private List excludeOperationsNameList;

	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();
		this.excludeOperationsNameList = 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;
	}

	@SuppressWarnings("deprecation")
    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 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);
                        //If there is already an operation with this action
						//mapping (e.g. if the service has a matching operation)
						//then we're going to check to see if the module's
						//operation says that it's OK to be overridden and
						//if so, we'll simply ignore the mapping, otherwise
						//we continue as before
						AxisOperation mappedOperation = getOperationByAction(mapping);
						if ((mappedOperation != null)
						    && (axisOperation.isParameterTrue(DeploymentConstants.TAG_ALLOWOVERRIDE))) {
						  if (log.isDebugEnabled()) {
						    log
						    .debug("addModuleOperations: Mapping already exists for action: "
						           + mapping
						           + " to operation: "
						           + axisOperation
						           + " named: "
						           + axisOperation.getName()
						           + " and an override is allowed, so the module mapping for module: "
						           + module.getName()
						           + " is being ignored.");
						    log.debug(JavaUtils.callStackToString());
						  }
						} else {
						  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);
	}

    /**
     * Adds operation name to exclude list.
     * 
     * @param operation operation name to add to exclude list
     * 
     */
    public void addExcludeOperationName(String operation){        
        excludeOperationsNameList.add(operation);       
    }
    
    /**
     * Removes operation name from exclude list.
     * 
     * @param operation operation name to remove from exclude list
     * 
     */
    public void removeExcludeOperationName(String operation){        
        excludeOperationsNameList.remove(operation);       
    }
    
    /**
     * Returns whether operation name is in exclude list. 
     * 
     * @param operation name to check if operation is in the exlude list.
     * @return boolean indicating whether operation name is in exlude list. 
     */
    public boolean isExcludedOperation(String operation){        
        return excludeOperationsNameList.contains(operation);       
    }
	
	/*
	 * (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());
              log.debug(JavaUtils.callStackToString());
		}
                      
		//If there is already an operation with this action
		//mapping then we're going to check to see if the
		//operation says that it's OK to be overridden and
		//if so, we'll simply ignore the mapping, otherwise
		//we continue as before
		AxisOperation mappedOperation = getOperationByAction(action);
		if ((mappedOperation != null)
		    && (axisOperation.isParameterTrue(DeploymentConstants.TAG_ALLOWOVERRIDE))) {
		  if (log.isDebugEnabled()) {
		    log
		    .debug("addModuleOperations: Mapping already exists for action: "
		           + action
		           + " to operation: "
		           + axisOperation
		           + " named: "
		           + axisOperation.getName()
		           + " and an override is allowed, so the mapping is being ignored.");
		    log.debug(JavaUtils.callStackToString());
		  }
		  return;		
		}

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

	/**
	 * Prints the schema to the given output stream.
	 * @param out The output stream for the data to be written. NOTE: the stream is not closed after the operation, 
	 *            it is the responsibility of the caller to close the stream after usage.
	 * @throws AxisFault
	 */
	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;
	}

	/**
	 * Prints the given definition object.
	 * @param definition The definition.
	 * @param out The output stream the data to be written to. NOTE: the stream is not closed after the operation, 
	 *            it is the responsibility of the caller to close the stream after usage.
	 * @param requestIP The host IP address.
	 * @throws AxisFault
	 * @throws WSDLException
	 */
	private synchronized void printDefinitionObject(Definition definition, OutputStream out,
			String requestIP) throws AxisFault, WSDLException {
        // Synchronized this method to fix the NullPointer exception occurred when load is high.
        // This error happens because wsdl4j is not thread safe and we are using same WSDL Definition for printing the
        // WSDL.
        // Please refer AXIS2-4511,AXIS2-4517,AXIS2-3276.
		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 {
			printUserWSDL(out, wsdlName, null);
	}

	/**
	 * Prints the user WSDL.
	 * @param out The output stream for the data to be written. NOTE: the stream is not closed after the operation, 
	 *            it is the responsibility of the caller to close the stream after usage.
	 * @param wsdlName The name of the WSDL.
	 * @param ip The host IP address.
	 * @throws AxisFault
	 */
	public void printUserWSDL(OutputStream out, String wsdlName, String ip)
			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, ip);
			} 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, NOTE: the stream is not closed after the operation, 
	 *            it is the responsibility of the caller to close the stream after usage.
	 * @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();
				return 1;
			}
		}

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

		// a name is present - try to pump the requested schema
        if ((xsd != null) && (!"".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();
            } 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();
				}
			} else {
				String xsdNotFound = "<error>"
						+ "<description>Unable to access schema for this service</description>"
						+ "</error>";
				out.write(xsdNotFound.getBytes());
				out.flush();
			}
		}
		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. NOTE: the stream is not closed after the operation, 
	 *            it is the responsibility of the caller to close the stream after usage.
	 * @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, requestIP);
			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;
		}

        if (isSetEndpointsToAllUsedBindings()) {
            Utils.setEndpointsToAllUsedBindings(this);
        }

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

    /**
     * users can use this parameter when they supply a wsdl file with the .aar file
     * but wants to generate the endpoints for all available transports. here it assume
     * that the user has not set the useOriginalwsdl
     * @return
     */
	public boolean isSetEndpointsToAllUsedBindings() {
		Parameter parameter = getParameter("setEndpointsToAllUsedBindings");
		if (parameter != null) {
			String value = (String) parameter.getValue();
			if ("true".equals(value)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Print the WSDL with a default URL. This will be called only during
	 * codegen time.
	 * 
	 * @param out The output stream for the data to be written. NOTE: the stream is not closed after the operation, 
	 *            it is the responsibility of the caller to close the stream after usage.
	 * @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(requestIP));
							} 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(requestIP));
								} 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(requestIP));
							} 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(requestIP));
							} else {
								((HTTPAddress) extensibilityEle)
										.setLocationURI(getLocationURI(
												calculateEPRs(requestIP),
												exsistingAddress));
							}
						}
					} else if (extensibilityEle instanceof UnknownExtensibilityElement){
                        UnknownExtensibilityElement unknownExtensibilityElement = (UnknownExtensibilityElement) extensibilityEle;
                        Element element = unknownExtensibilityElement.getElement();
                        if (AddressingConstants.ENDPOINT_REFERENCE.equals(element.getLocalName())){
                            NodeList nodeList = element.getChildNodes();
                            Node node = null;
                            Element currentElement = null;
                            for (int j = 0; j < nodeList.getLength(); j++) {
                                node = nodeList.item(j);
                                if (node instanceof Element){
                                    currentElement = (Element) node;
                                    if (AddressingConstants.EPR_ADDRESS.equals(currentElement.getLocalName())) {
                                        String exsistingAddress = currentElement.getTextContent();
                                        if (requestIP == null) {
                                            if (endpoint != null) {
                                                currentElement.setTextContent(endpoint.calculateEndpointURL());
                                            } else {
                                                currentElement.setTextContent(getLocationURI(getEPRs(), exsistingAddress));
                                            }
                                        } else {
                                            if (endpoint != null) {
                                                currentElement.setTextContent(endpoint.calculateEndpointURL(requestIP));
                                            } else {
                                                currentElement.setTextContent(getLocationURI(calculateEPRs(requestIP),exsistingAddress));
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
				}
			}
		}
	}

	/**
	 * 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) {
		    String existingProtocol = org.apache.axis2.util.Utils.getURIScheme(epr);
			if (existingProtocol != null) {
				for (int i = 0; i < eprs.length; i++) {
					if (existingProtocol.equals(org.apache.axis2.util.Utils.getURIScheme(eprs[i]))) {
						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");
		}
	}

	/**
	 * Retrieves the WSDL data associated with the given serviceURL.
	 * @param out The output stream for the WSDL data to be written, NOTE: the stream is not closed after the operation, 
	 *            it is the responsibility of the caller to close the stream after usage.
	 * @param serviceURL The fist element of this array i.e. serviceURL[0] is taken in retrieving the target service.
	 */
	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();
			} catch (Exception e) {
				throw AxisFault.makeFault(e);
			}
		}
	}

	/**
	 * Prints generic WSDL error to the given output stream.
	 * @param out The output stream the data to be written to. NOTE: the stream is not closed after the operation, 
	 *            it is the responsibility of the caller to close the stream after usage.
	 * @throws AxisFault
	 */
	private void printWSDLError(OutputStream out) throws AxisFault {
		printWSDLError(out, null);
	}

	/**
	 * Prints WSDL error condition that is given in the exception.
	 * @param out The output stream for the error message to be written. NOTE: the stream is not closed after the operation, 
	 *            it is the responsibility of the caller to close the stream after usage.
	 * @param e The exception describing the error condition.
	 * @throws AxisFault
	 */
	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();
		} 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 The output stream for the data to be written for. NOTE: the stream is not closed after the operation, 
	 *            it is the responsibility of the caller to close the stream after usage.
	 * @throws AxisFault
	 */
	public void printWSDL2(OutputStream out) throws AxisFault {
		printWSDL2(out, null);
	}

	/**
	 * Prints WSDL2.0 data for the service with the given host IP address.
	 * @param out The output stream for the data to be written for. NOTE: the stream is not closed after the operation, 
	 *            it is the responsibility of the caller to close the stream after usage.
	 * @param requestIP The host IP address.
	 * @throws AxisFault
	 */
	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();
		} catch (Exception e) {
			throw AxisFault.makeFault(e);
		}
	}

    /**
     * Produces a WSDL2 for this AxisService and prints it to the specified
     * OutputStream.
     * 
     * @param out
     *            destination stream. NOTE: the stream is not closed after the operation, 
	 *            it is the responsibility of the caller to close the stream after usage.
     * @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 {    
        // if the wsdl2 parameter is not empty or null in the requested URL, get the wsdl  from the META-INF and serve.
        //else construct the wsdl out of axis service and serve.
        if ((wsdl != null ) && (!"".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 = iterator.next();
            addSchema(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);
            String namespaceURI = doc.getDocumentElement().getNamespaceURI();
            if (Constants.NS_URI_WSDL11.equals(namespaceURI)) {
                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);
            } else if (Constants.NS_URI_WSDL20.equals(namespaceURI)) {
                org.apache.woden.WSDLReader reader = org.apache.woden.WSDLFactory.newInstance()
                        .newWSDLReader();
                WSDLSource source = reader.createWSDLSource();
                source.setSource(doc);
                source.setBaseURI(wsdlURL.toURI());
                Description description = reader.readWSDL(source);
                return createClientSideAxisService(description, wsdlServiceName, portName, options);
            } else {
                throw new AxisFault("No namespace found : Invalid WSDL");
            }
			
		} 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);
        } catch (org.apache.woden.WSDLException e) {
            log.error(e.getMessage(), e);
            throw AxisFault.makeFault(e);
        } catch (URISyntaxException 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());

		if (axisEndpoint != null) {
            options.setTo(new EndpointReference(axisEndpoint.getEndpointURL()));
			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];

            String methodName = jmethod.getName();
            WebMethodAnnotation methodAnnon = JSR181Helper.INSTANCE.getWebMethodAnnotation(jmethod);
            if (methodAnnon != null) {
                if (methodAnnon.getOperationName() != null){
                    methodName = methodAnnon.getOperationName();
                }
            }
			AxisOperation operation = axisService.getOperation(new QName(methodName));

			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);
					invalidOperationsAliases.remove(actionMapping);
				}
			}
			operationsAliasesMap.remove(operation.getName().getLocalPart());
			invalidOperationsAliases.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 {@link AxisEndpoint#getEndpointURL()}
	 */
	public String getEndpointURL() {
		return endpointURL;
	}

	/**
	 * @deprecated use {@link AxisEndpoint#setEndpointURL(String)}
	 */
	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);
        }
    }

    /**
     * returns a axisService given a input Stream of WSDL2.0 document.
     * 
     * @param Description
     *            WSDL description
     * @param wsdlServiceName
     * @param endPoint
     * @param options
     * @return
     * @throws AxisFault
     */
    public static AxisService createClientSideAxisService(Description description,
            QName wsdlServiceName, String endPoint, Options options) throws AxisFault {
        WSDL20ToAxisServiceBuilder serviceBuilder = new WSDL20ToAxisServiceBuilder(description,
                wsdlServiceName, endPoint);
        serviceBuilder.setServerSide(false);
        AxisService axisService = serviceBuilder.populateService();
        AxisEndpoint axisEndpoint = (AxisEndpoint) axisService.getEndpoint(axisService
                .getEndpointName());
        if (axisEndpoint != null) {
            options.setTo(new EndpointReference(axisEndpoint.getEndpointURL()));
            options.setSoapVersionURI((String) axisEndpoint.getBinding().getProperty(
                    WSDL2Constants.ATTR_WSOAP_VERSION));
        }
        return axisService;
    }
}
