All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.axis2.description.AxisOperation Maven / Gradle / Ivy

Go to download

Core Parts of Axis2. This includes Axis2 engine, Client API, Addressing support, etc.,

There is a newer version: 1.8.2
Show newest version
/*
 * 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 java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Set;

import javax.xml.namespace.QName;

import org.apache.axiom.util.UIDGenerator;
import org.apache.axis2.AxisFault;
import org.apache.axis2.client.OperationClient;
import org.apache.axis2.client.Options;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.context.ServiceContext;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.engine.AxisError;
import org.apache.axis2.engine.MessageReceiver;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.phaseresolver.PhaseResolver;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class AxisOperation extends AxisDescription
        implements WSDLConstants {

    public static final String STYLE_RPC = "rpc";
    public static final String STYLE_MSG = "msg";
    public static final String STYLE_DOC = "doc";

    private static final Log log = LogFactory.getLog(AxisOperation.class);
    /** message exchange pattern */
    private int mep = WSDLConstants.MEP_CONSTANT_INVALID;

    // to hide control operation , operation which added by RM like module
    private boolean controlOperation = false;
    private String style = STYLE_DOC;

    // to store mepURL
    protected String mepURI;

    private MessageReceiver messageReceiver;

    private HashMap moduleConfigmap;

    // To store deploy-time module refs
    private ArrayList modulerefs;

    private ArrayList faultMessages;

    private QName name;

    private ArrayList wsamappingList;
    private String outputAction;
    private LinkedHashMap faultActions = new LinkedHashMap();

    private String soapAction;


    /** Default constructor */
    public AxisOperation() {
        mepURI = WSDL2Constants.MEP_URI_IN_OUT;
        modulerefs = new ArrayList();
        moduleConfigmap = new HashMap();
        faultMessages = new ArrayList();
        //setup a temporary name
        QName tmpName = new QName(this.getClass().getName() + "_" + UIDGenerator.generateUID());
        this.setName(tmpName);
    }

    public AxisOperation(QName name) {
        this();
        this.setName(name);
    }

    public abstract void addMessage(AxisMessage message, String label);

    /**
     * Adds a message context into an operation context. Depending on MEPs, this method has to be
     * overridden. Depending on the MEP operation description know how to fill the message context
     * map in operationContext. As an example, if the MEP is IN-OUT then depending on messagable
     * operation description should know how to keep them in correct locations.
     *
     * @param msgContext MessageContext
     * @param opContext  OperationContext
     * @throws AxisFault AxisFault
     */
    public abstract void addMessageContext(MessageContext msgContext, OperationContext opContext)
            throws AxisFault;

    public abstract void addFaultMessageContext(MessageContext msgContext,
                                                OperationContext opContext)
            throws AxisFault;

    public void addModule(String moduleName) {
        modulerefs.add(moduleName);
    }

    /**
     * Adds module configuration, if there is moduleConfig tag in operation.
     *
     * @param moduleConfiguration a ModuleConfiguration which will be added (by name)
     */
    public void addModuleConfig(ModuleConfiguration moduleConfiguration) {
        moduleConfigmap.put(moduleConfiguration.getModuleName(), moduleConfiguration);
    }

    /**
     * This is called when a module is engaged on this operation.  Handle operation-specific tasks.
     *
     * @param axisModule AxisModule being engaged
     * @param engager    the AxisDescription where the engage occurred - could be us or a parent
     * @throws AxisFault
     */
    public final void onEngage(AxisModule axisModule, AxisDescription engager) throws AxisFault {
        // Am I the source of this engagement?
        boolean selfEngaged = (engager == this);

        // If I'm not, the operations will already have been added by someone above, so don't
        // do it again.
        if (selfEngaged) {
            AxisService service = getAxisService();
            if (service != null) {
                service.addModuleOperations(axisModule);
            }
        }
        AxisConfiguration axisConfig = getAxisConfiguration();
        PhaseResolver phaseResolver = new PhaseResolver(axisConfig);
        phaseResolver.engageModuleToOperation(this, axisModule);
    }

    protected void onDisengage(AxisModule module) {
        AxisService service = getAxisService();
        if (service == null) return;

        AxisConfiguration axisConfiguration = service.getAxisConfiguration();
        PhaseResolver phaseResolver = new PhaseResolver(axisConfiguration);
        if (!service.isEngaged(module.getName()) &&
            (axisConfiguration != null && !axisConfiguration.isEngaged(module.getName()))) {
            phaseResolver.disengageModuleFromGlobalChains(module);
        }
        phaseResolver.disengageModuleFromOperationChain(module, this);

        //removing operations added at the time of module engagemnt
        HashMap moduleOperations = module.getOperations();
        if (moduleOperations != null) {
            Iterator moduleOperations_itr = moduleOperations.values().iterator();
            while (moduleOperations_itr.hasNext()) {
                AxisOperation operation = moduleOperations_itr.next();
                service.removeOperation(operation.getName());
            }
        }
    }


//  Note - removed this method which was dead code.
//    private AxisOperation copyOperation(AxisOperation axisOperation) throws AxisFault {

    /**
     * Returns as existing OperationContext related to this message if one exists.
     * 

* TODO - why both this and findOperationContext()? (GD) * * @param msgContext the MessageContext for which we'd like an OperationContext * @return the OperationContext, or null * @throws AxisFault */ public OperationContext findForExistingOperationContext(MessageContext msgContext) throws AxisFault { OperationContext operationContext; if ((operationContext = msgContext.getOperationContext()) != null) { return operationContext; } // If this message is not related to another one, or it is but not one emitted // from the same operation, don't further look for an operation context or fault. if (null != msgContext.getRelatesTo()) { // So this message may be part of an ongoing MEP ConfigurationContext configContext = msgContext.getConfigurationContext(); operationContext = configContext.getOperationContext(msgContext.getRelatesTo().getValue()); if (null == operationContext && log.isDebugEnabled()) { log.debug(msgContext.getLogIDString() + " Cannot correlate inbound message RelatesTo value [" + msgContext.getRelatesTo() + "] to in-progree MEP"); } } return operationContext; } /** * Finds an OperationContext for an incoming message. An incoming message can be of two states. *

* 1)This is a new incoming message of a given MEP. 2)This message is a part of an MEP which has * already begun. *

* The method is special cased for the two MEPs *

* #IN_ONLY #IN_OUT *

* for two reasons. First reason is the wide usage and the second being that the need for the * MEPContext to be saved for further incoming messages. *

* In the event that MEP of this operation is different from the two MEPs defaulted above the * decision of creating a new or this message relates to a MEP which already in business is * decided by looking at the WSA Relates TO of the incoming message. * * @param msgContext MessageContext to search * @param serviceContext ServiceContext (TODO - why pass this? (GD)) * @return the active OperationContext */ public OperationContext findOperationContext(MessageContext msgContext, ServiceContext serviceContext) throws AxisFault { OperationContext operationContext; if (null == msgContext.getRelatesTo()) { // Its a new incoming message so get the factory to create a new // one operationContext = serviceContext.createOperationContext(this); } else { // So this message is part of an ongoing MEP ConfigurationContext configContext = msgContext.getConfigurationContext(); operationContext = configContext.getOperationContext(msgContext.getRelatesTo().getValue()); if (null == operationContext) { throw new AxisFault(Messages.getMessage("cannotCorrelateMsg", this.name.toString(), msgContext.getRelatesTo().getValue())); } } return operationContext; } public void registerOperationContext(MessageContext msgContext, OperationContext operationContext) throws AxisFault { msgContext.setAxisOperation(this); msgContext.getConfigurationContext().registerOperationContext(msgContext.getMessageID(), operationContext); operationContext.addMessageContext(msgContext); msgContext.setOperationContext(operationContext); if (operationContext.isComplete()) { operationContext.cleanup(); } } public void registerMessageContext(MessageContext msgContext, OperationContext operationContext) throws AxisFault { msgContext.setAxisOperation(this); operationContext.addMessageContext(msgContext); msgContext.setOperationContext(operationContext); if (operationContext.isComplete()) { operationContext.cleanup(); } } /** * Maps the String URI of the Message exchange pattern to an integer. Further, in the first * lookup, it will cache the looked up value so that the subsequent method calls are extremely * efficient. * * @return an MEP constant from WSDLConstants */ public int getAxisSpecificMEPConstant() { if (this.mep != WSDLConstants.MEP_CONSTANT_INVALID) { return this.mep; } int temp = WSDLConstants.MEP_CONSTANT_INVALID; if (WSDL2Constants.MEP_URI_IN_OUT.equals(mepURI)) { temp = WSDLConstants.MEP_CONSTANT_IN_OUT; } else if (WSDL2Constants.MEP_URI_IN_ONLY.equals(mepURI)) { temp = WSDLConstants.MEP_CONSTANT_IN_ONLY; } else if (WSDL2Constants.MEP_URI_IN_OPTIONAL_OUT.equals(mepURI)) { temp = WSDLConstants.MEP_CONSTANT_IN_OPTIONAL_OUT; } else if (WSDL2Constants.MEP_URI_OUT_IN.equals(mepURI)) { temp = WSDLConstants.MEP_CONSTANT_OUT_IN; } else if (WSDL2Constants.MEP_URI_OUT_ONLY.equals(mepURI)) { temp = WSDLConstants.MEP_CONSTANT_OUT_ONLY; } else if (WSDL2Constants.MEP_URI_OUT_OPTIONAL_IN.equals(mepURI)) { temp = WSDLConstants.MEP_CONSTANT_OUT_OPTIONAL_IN; } else if (WSDL2Constants.MEP_URI_ROBUST_IN_ONLY.equals(mepURI)) { temp = WSDLConstants.MEP_CONSTANT_ROBUST_IN_ONLY; } else if (WSDL2Constants.MEP_URI_ROBUST_OUT_ONLY.equals(mepURI)) { temp = WSDLConstants.MEP_CONSTANT_ROBUST_OUT_ONLY; } if (temp == WSDLConstants.MEP_CONSTANT_INVALID) { throw new AxisError(Messages.getMessage("mepmappingerror")); } this.mep = temp; return this.mep; } /* * (non-Javadoc) * * @see org.apache.axis2.description.AxisService#getEngadgedModules() */ public abstract AxisMessage getMessage(String label); public String getMessageExchangePattern() { return mepURI; } public MessageReceiver getMessageReceiver() { return messageReceiver; } public ModuleConfiguration getModuleConfig(String moduleName) { return moduleConfigmap.get(moduleName); } public ArrayList getModuleRefs() { return modulerefs; } public QName getName() { return name; } public abstract ArrayList getPhasesInFaultFlow(); public abstract ArrayList getPhasesOutFaultFlow(); public abstract ArrayList getPhasesOutFlow(); public abstract ArrayList getRemainingPhasesInFlow(); public String getStyle() { return style; } public ArrayList getWSAMappingList() { return wsamappingList; } public boolean isControlOperation() { return controlOperation; } // to check whether a given parameter is locked public boolean isParameterLocked(String parameterName) { // checking the locked value of parent boolean locked = false; if (getParent() != null) { locked = getParent().isParameterLocked(parameterName); } if (locked) { return true; } else { Parameter parameter = getParameter(parameterName); return (parameter != null) && parameter.isLocked(); } } public void setControlOperation(boolean controlOperation) { this.controlOperation = controlOperation; } public void setMessageExchangePattern(String mepURI) { this.mepURI = mepURI; } public void setMessageReceiver(MessageReceiver messageReceiver) { this.messageReceiver = messageReceiver; } public void setName(QName name) { this.name = name; } public abstract void setPhasesInFaultFlow(ArrayList list); public abstract void setPhasesOutFaultFlow(ArrayList list); public abstract void setPhasesOutFlow(ArrayList list); public abstract void setRemainingPhasesInFlow(ArrayList list); public void setStyle(String style) { if (!"".equals(style)) { this.style = style; } } public void setWsamappingList(ArrayList wsamappingList) { if (log.isDebugEnabled()) { log.debug("setWsamappinglist"); } this.wsamappingList = wsamappingList; if (wsamappingList != null && !wsamappingList.isEmpty()) { if (log.isDebugEnabled()) { log.debug(" wsa action is " + (String)wsamappingList.get(0)); } } } /** * Return an OperationClient suitable for this AxisOperation. * * @param sc active ServiceContext * @param options active Options * @return an OperationClient set up appropriately for this operation */ public abstract OperationClient createClient(ServiceContext sc, Options options); public Object getKey() { return this.name; } public ArrayList getFaultMessages() { return faultMessages; } public void setFaultMessages(AxisMessage faultMessage) { faultMessage.setParent(this); faultMessages.add(faultMessage); if (getFaultAction(faultMessage.getName()) == null) { addFaultAction(faultMessage.getName(), "urn:" + name.getLocalPart() + faultMessage.getName()); } } public void setSoapAction(String soapAction) { if(log.isDebugEnabled()) { log.debug("Entry: AxisOperation::setSoapAction, previous soapAction: " + this.soapAction + " updated soapAction: " + soapAction); } this.soapAction = soapAction; if(log.isDebugEnabled()) { log.debug("Exit: AxisOperation::setSoapAction"); } } /* * Convenience method to access the WS-A Input Action per the * WS-A spec. Effectively use the soapAction if available else * use the first entry in the WSA Mapping list. * * Use getSoapAction when you want to get the soap action and this * when you want to get the wsa input action. */ public String getInputAction() { if(log.isDebugEnabled()) { log.debug("Entry: AxisOperation::getInputAction"); } String result = null; if (soapAction != null && !"".equals(soapAction)) { if(log.isDebugEnabled()) { log.debug("Debug: AxisOperation::getInputAction - using soapAction"); // so we know which path was taken // log wsa map to see if it matches or is set if (wsamappingList != null && !wsamappingList.isEmpty()) { log.debug(" but WSA map indicates " + (String)wsamappingList.get(0)); } } result = soapAction; } else { if (wsamappingList != null && !wsamappingList.isEmpty()) { if(log.isDebugEnabled()) { log.debug("Debug: AxisOperation::getInputAction - using wsamappingList"); } result = wsamappingList.get(0); } } if(log.isDebugEnabled()) { log.debug("Exit: AxisOperation::getInputAction " + result); } return result; } public String getOutputAction() { return outputAction; } public void setOutputAction(String act) { outputAction = act; } public void addFaultAction(String faultName, String action) { faultActions.put(faultName, action); } public void removeFaultAction(String faultName) { faultActions.remove(faultName); } public String getFaultAction(String faultName) { return faultActions.get(faultName); } public String[] getFaultActionNames() { Set keys = faultActions.keySet(); String[] faultActionNames = new String[keys.size()]; faultActionNames = keys.toArray(faultActionNames); return faultActionNames; } public String getFaultAction() { String result = null; Iterator iter = faultActions.values().iterator(); if (iter.hasNext()) { result = iter.next(); } return result; } /** * Get the messages referenced by this operation * * @return an Iterator of all the AxisMessages we deal with */ public Iterator getMessages() { return (Iterator)getChildren(); } /** * Typesafe access to parent service * * @return the AxisService which contains this AxisOperation */ public AxisService getAxisService() { return (AxisService)getParent(); } public String getSoapAction() { if(log.isDebugEnabled()) { log.debug("AxisOperation::getSoapAction " + soapAction); } /* * This AxisOperation instance may be used for the client OUT-IN or for * the server IN-OUT. If the below code were changed to getInputActions, and the * result of getInputAction were put in the SOAP action header on a client outbound * message, the server would receive an INCORRECT SOAP action header. We should leave * this as 'return soapAction;' OR make it client/server aware. */ return soapAction; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy