blob: ef994629677c00b3e9bb40fdb89eb8095d4546ee [file] [log] [blame]
/*
* Copyright 2004,2006 The Apache Software Foundation.
*
* Licensed 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.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.modules.Module;
import org.apache.axis2.phaseresolver.PhaseResolver;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.xml.namespace.QName;
import java.util.*;
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);
private int mep = WSDL20_2004Constants.MEP_CONSTANT_INVALID;
public static final String SOAP_ACTION = "soapaction";
// to store engaged modules
private ArrayList engagedModules = new ArrayList();
// to hide control operation , operation which added by RM like module
private boolean controlOperation = false;
private String style = STYLE_DOC;
// to store mepURL
private 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 HashMap faultActions = new HashMap();
private String soapAction;
public AxisOperation() {
mepURI = WSDL20_2004Constants.MEP_URI_IN_OUT;
modulerefs = new ArrayList();
moduleConfigmap = new HashMap();
faultMessages = new ArrayList();
}
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 <code>MessageContext</code>
* @param opContext <code>OperationContext</code>
* @throws AxisFault <code>AxisFault</code>
*/
public abstract void addMessageContext(MessageContext msgContext, OperationContext opContext)
throws AxisFault;
public abstract void addFaultMessageContext(MessageContext msgContext, OperationContext opContext)
throws AxisFault;
public void addModule(QName moduleName) {
modulerefs.add(moduleName);
}
/**
* Adds module configuration, if there is moduleConfig tag in operation.
*
* @param moduleConfiguration
*/
public void addModuleConfig(ModuleConfiguration moduleConfiguration) {
moduleConfigmap.put(moduleConfiguration.getModuleName(), moduleConfiguration);
}
/**
* Engages a module. It is required to use this method.
*
* @param moduleref
* @throws AxisFault
*/
public final void engageModule(AxisModule moduleref, AxisConfiguration axisConfig)
throws AxisFault {
ArrayList moduleOperations = engageModuleToOperation(moduleref, axisConfig);
AxisService service = (AxisService) getParent();
if (service != null) {
for (int i = 0; i < moduleOperations.size(); i++) {
AxisOperation axisOperation = (AxisOperation) moduleOperations.get(i);
service.addOperation(axisOperation);
}
}
}
private ArrayList engageModuleToOperation(AxisModule moduleref, AxisConfiguration axisConfig) throws AxisFault {
if (moduleref == null) {
return null;
}
Iterator module_itr = engagedModules.iterator();
boolean isEngagable;
QName moduleName = moduleref.getName();
while (module_itr.hasNext()) {
AxisModule module = (AxisModule) module_itr.next();
QName modu = module.getName();
isEngagable = org.apache.axis2.util.Utils.checkVersion(moduleName, modu);
if (!isEngagable) {
return new ArrayList();
}
}
PhaseResolver phaseResolver = new PhaseResolver(axisConfig);
phaseResolver.engageModuleToOperation(this, moduleref);
Module module = moduleref.getModule();
if (module != null) {
module.engageNotify(this);
}
engagedModules.add(moduleref);
return addModuleOperations(moduleref, axisConfig, (AxisService) getParent());
}
public void disengageModule(AxisModule module) {
if (module != null) {
if (getParent() != null) {
AxisService service = (AxisService) getParent();
AxisConfiguration axiConfiguration = service.getAxisConfiguration();
PhaseResolver phaseResolver = new PhaseResolver(axiConfiguration);
if (service.isEngaged(module.getName())) {
phaseResolver.disengageModuleFromOperationChain(module, this);
} else if (axiConfiguration != null &&
axiConfiguration.isEngaged(module.getName())) {
phaseResolver.disengageModuleFromOperationChain(module, this);
} else {
if (axiConfiguration != null) {
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 = (AxisOperation) moduleOperations_itr.next();
service.removeOperation(operation.getName());
}
}
}
}
engagedModules.remove(module);
log.debug("removed module from engaged modules list "
+ module.getName().getLocalPart());
}
}
/**
* To remove module from engage module list
*
* @param module
*/
public void removeFromEngagedModuleList(AxisModule module) {
engagedModules.remove(module);
log.debug("removed module from engaged modules list " + module.getName().getLocalPart());
}
/**
* Adds an operation to a service if a module is required to do so.
*
* @param module
*/
public ArrayList addModuleOperations(AxisModule module, AxisConfiguration axisConfig,
AxisService service)
throws AxisFault {
HashMap map = module.getOperations();
Collection col = map.values();
PhaseResolver phaseResolver = new PhaseResolver(axisConfig);
//this array list is return , to avoid concurrent modifications , in the deployment engine
ArrayList ops = new ArrayList();
for (Iterator iterator = col.iterator(); iterator.hasNext();) {
AxisOperation axisOperation = copyOperation((AxisOperation) iterator.next());
axisOperation.setParent(service);
ArrayList wsamappings = axisOperation.getWsamappingList();
if (service.getOperation(axisOperation.getName()) == null) {
// this operation is a control operation.
axisOperation.setControlOperation(true);
Module moduleclazz = module.getModule();
if (moduleclazz != null) {
moduleclazz.engageNotify(axisOperation);
}
phaseResolver.engageModuleToOperation(axisOperation, module);
ops.add(axisOperation);
if (wsamappings != null) {
for (int j = 0; j < wsamappings.size(); j++) {
String mapping = (String) wsamappings.get(j);
service.mapActionToOperation(mapping, axisOperation);
}
}
}
}
return ops;
}
/**
* 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 parameters = axisOperation.getParameters().iterator();
while (parameters.hasNext()) {
Parameter parameter = (Parameter) parameters.next();
operation.addParameter(parameter);
}
operation.setWsamappingList(axisOperation.getWsamappingList());
operation.setOutputAction(axisOperation.getOutputAction());
String[] faultActionNames = axisOperation.getFaultActionNames();
for (int i = 0; i < faultActionNames.length; i++) {
operation.addFaultAction(faultActionNames[i], axisOperation.getFaultAction(faultActionNames[i]));
}
operation.setRemainingPhasesInFlow(axisOperation.getRemainingPhasesInFlow());
operation.setPhasesInFaultFlow(axisOperation.getPhasesInFaultFlow());
operation.setPhasesOutFaultFlow(axisOperation.getPhasesOutFaultFlow());
operation.setPhasesOutFlow(axisOperation.getPhasesOutFlow());
return operation;
}
/**
* Returns as existing OperationContext related to this message if one exists.
*
* @param msgContext
* @return Returns OperationContext.
* @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("Cannot correlate inbound message RelatesTo value [" + msgContext.getRelatesTo() + "] to in-progree MEP");
}
}
return operationContext;
}
/**
* Finds a MEPContext for an incoming message. An incoming message can be
* of two states.
* <p/>
* 1)This is a new incoming message of a given MEP. 2)This message is a
* part of an MEP which has already begun.
* <p/>
* The method is special cased for the two MEPs
* <p/>
* #IN_ONLY #IN_OUT
* <p/>
* 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.
* <p/>
* 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
*/
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 = new OperationContext(this, serviceContext);
} 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 a integer.
* Further, in the first lookup, it will cache the looked
* up value so that the subsequent method calls are extremely efficient.
*/
public int getAxisSpecifMEPConstant() {
if (this.mep != WSDL20_2004Constants.MEP_CONSTANT_INVALID) {
return this.mep;
}
int temp = WSDL20_2004Constants.MEP_CONSTANT_INVALID;
if (WSDL20_2004Constants.MEP_URI_IN_OUT.equals(mepURI) || WSDL20_2006Constants.MEP_URI_IN_OUT.equals(mepURI)) {
temp = WSDL20_2004Constants.MEP_CONSTANT_IN_OUT;
} else if (WSDL20_2004Constants.MEP_URI_IN_ONLY.equals(mepURI) || WSDL20_2006Constants.MEP_URI_IN_ONLY.equals(mepURI)) {
temp = WSDL20_2004Constants.MEP_CONSTANT_IN_ONLY;
} else if (WSDL20_2004Constants.MEP_URI_IN_OPTIONAL_OUT.equals(mepURI) || WSDL20_2006Constants.MEP_URI_IN_OPTIONAL_OUT.equals(mepURI)) {
temp = WSDL20_2004Constants.MEP_CONSTANT_IN_OPTIONAL_OUT;
} else if (WSDL20_2004Constants.MEP_URI_OUT_IN.equals(mepURI) || WSDL20_2006Constants.MEP_URI_OUT_IN.equals(mepURI)) {
temp = WSDL20_2004Constants.MEP_CONSTANT_OUT_IN;
} else if (WSDL20_2004Constants.MEP_URI_OUT_ONLY.equals(mepURI) || WSDL20_2006Constants.MEP_URI_OUT_ONLY.equals(mepURI)) {
temp = WSDL20_2004Constants.MEP_CONSTANT_OUT_ONLY;
} else if (WSDL20_2004Constants.MEP_URI_OUT_OPTIONAL_IN.equals(mepURI) || WSDL20_2006Constants.MEP_URI_OUT_OPTIONAL_IN.equals(mepURI)) {
temp = WSDL20_2004Constants.MEP_CONSTANT_OUT_OPTIONAL_IN;
} else if (WSDL20_2004Constants.MEP_URI_ROBUST_IN_ONLY.equals(mepURI) || WSDL20_2006Constants.MEP_URI_ROBUST_IN_ONLY.equals(mepURI)) {
temp = WSDL20_2004Constants.MEP_CONSTANT_ROBUST_IN_ONLY;
} else if (WSDL20_2004Constants.MEP_URI_ROBUST_OUT_ONLY.equals(mepURI) || WSDL20_2006Constants.MEP_URI_ROBUST_OUT_ONLY.equals(mepURI)) {
temp = WSDL20_2004Constants.MEP_CONSTANT_ROBUST_OUT_ONLY;
}
if (temp == WSDL20_2004Constants.MEP_CONSTANT_INVALID) {
throw new AxisError(Messages.getMessage("mepmappingerror"));
}
this.mep = temp;
return this.mep;
}
/*
* (non-Javadoc)
*
* @see org.apache.axis2.description.AxisService#getEngadgedModules()
*/
/**
* Method getEngagedModules.
*/
public Collection getEngagedModules() {
return engagedModules;
}
public abstract AxisMessage getMessage(String label);
public String getMessageExchangePattern() {
return mepURI;
}
public MessageReceiver getMessageReceiver() {
return messageReceiver;
}
public ModuleConfiguration getModuleConfig(QName moduleName) {
return (ModuleConfiguration) 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) {
this.wsamappingList = wsamappingList;
}
/**
*
*/
public OperationClient createClient(ServiceContext sc, Options options) {
throw new UnsupportedOperationException(Messages.getMessage("mepnotyetimplemented", mepURI));
}
public Object getKey() {
return this.name;
}
public ArrayList getFaultMessages() {
return faultMessages;
}
public void setFaultMessages(AxisMessage faultMessage) {
faultMessages.add(faultMessage);
}
public String getSoapAction() {
return soapAction;
}
public void setSoapAction(String soapAction) {
this.soapAction = soapAction;
}
public String getInputAction() {
String result = this.soapAction;
if (result == null || "".equals(result)) {
if (wsamappingList != null && !wsamappingList.isEmpty()) {
result = wsamappingList.get(0).toString();
}
}
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 (String) faultActions.get(faultName);
}
public String[] getFaultActionNames() {
Set keys = faultActions.keySet();
String[] faultActionNames = new String[keys.size()];
faultActionNames = (String[]) keys.toArray(faultActionNames);
return faultActionNames;
}
public String getFaultAction() {
String result = null;
Iterator iter = faultActions.values().iterator();
if (iter.hasNext()) {
result = (String) iter.next();
}
return result;
}
public boolean isEngaged(QName moduleName) {
Iterator engagedModuleItr = engagedModules.iterator();
while (engagedModuleItr.hasNext()) {
AxisModule axisModule = (AxisModule) engagedModuleItr.next();
if (axisModule.getName().getLocalPart().equals(moduleName.getLocalPart())) {
return true;
}
}
return false;
}
}