blob: 43665f646bd3be3d53167a79e107eaf3ca44b054 [file] [log] [blame]
package org.apache.axis.context;
/*
* Copyright 2004,2005 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.
*/
import org.apache.axis.description.OperationDescription;
import org.apache.axis.engine.AxisError;
import org.apache.axis.engine.AxisFault;
import org.apache.wsdl.WSDLConstants;
import java.util.Map;
/**
* An OperationContext represents a running "instance" of an operation, which is
* represented by an OperationDescription object. This concept is needed to allow
* messages to be grouped into operations as in WSDL 2.0-speak operations are
* essentially arbitrary message exchange patterns. So as messages are being
* exchanged the OperationContext remembers the state of where in the message
* exchange pattern it is in.
* <p/>
* OperationContextFactory factory. The base implementation of OperationContext
* supports MEPs which have one input message and/or one output message. That
* is, it supports the all the MEPs that are in the WSDL 2.0 specification. In
* order to support another MEP one must extend this class and register its
* creation in the OperationContexFactory.
*/
public class OperationContext extends AbstractContext {
// the in and out messages that may be present
private MessageContext inMessageContext;
private MessageContext outMessageContext;
// the OperationDescription of which this is a running instance. The MEP of this
// OperationDescription must be one of the 8 predefined ones in WSDL 2.0.
private OperationDescription axisOperation;
private int operationMEP;
private boolean isComplete = false;
// this is the global MessageID -> OperationContext map which is stored in
// the EngineContext. We're caching it here for faster acccess.
private Map operationContextMap;
/**
* Construct a new OperationContext.
*
* @param axisOperation the OperationDescription whose running instances' state this
* OperationContext represents.
* @param serviceContext the parent ServiceContext representing any state related to
* the set of all operations of the service.
*/
public OperationContext(OperationDescription axisOperation,
ServiceContext serviceContext) {
super(serviceContext);
this.axisOperation = axisOperation;
this.operationMEP = axisOperation.getAxisSpecifMEPConstant();
this.operationContextMap = getServiceContext().getEngineContext()
.getOperationContextMap();
}
/**
* @return Returns the axisOperation.
*/
public OperationDescription getAxisOperation() {
return axisOperation;
}
/**
* Return the ServiceContext in which this OperationContext lives.
*
* @return parent ServiceContext
*/
public ServiceContext getServiceContext() {
return (ServiceContext) parent;
}
/**
* Return the EngineContext in which the parent ServiceContext lives.
*
* @return parent ServiceContext's parent EngineContext
*/
public ConfigurationContext getEngineContext() {
return (ConfigurationContext) parent.parent;
}
/**
* When a new message is added to the <code>MEPContext</code> the logic
* should be included remove the MEPContext from the table in the
* <code>EngineContext</code>. Example: IN_IN_OUT At the second IN
* message the MEPContext should be removed from the OperationDescription
*
* @param msgContext
*/
public synchronized void addMessageContext(MessageContext msgContext) throws AxisFault {
// this needs to store the msgContext in either inMessageContext or
// outMessageContext depending on the MEP of the OperationDescription
// and on the current state of the operation.
if (WSDLConstants.MEP_CONSTANT_IN_OUT == operationMEP
|| WSDLConstants.MEP_CONSTANT_IN_OPTIONAL_OUT == operationMEP
|| WSDLConstants.MEP_CONSTANT_ROBUST_IN_ONLY == operationMEP) {
if (inMessageContext == null) {
inMessageContext = msgContext;
} else {
outMessageContext = msgContext;
isComplete = true;
}
} else if (WSDLConstants.MEP_CONSTANT_IN_ONLY == operationMEP) {
inMessageContext = msgContext;
isComplete = true;
} else if (WSDLConstants.MEP_CONSTANT_OUT_ONLY == operationMEP) {
outMessageContext = msgContext;
isComplete = true;
} else if (WSDLConstants.MEP_CONSTANT_OUT_IN == operationMEP
|| WSDLConstants.MEP_CONSTANT_OUT_OPTIONAL_IN == operationMEP
|| WSDLConstants.MEP_CONSTANT_ROBUST_IN_ONLY == operationMEP) {
if (outMessageContext == null) {
outMessageContext = msgContext;
} else {
inMessageContext = msgContext;
isComplete = true;
}
} else {
// NOT REACHED: the factory created this context incorrectly
throw new AxisError("Invalid behavior of OperationContextFactory");
}
}
/**
* @param messageLabel
* @return
* @throws AxisFault
*/
public MessageContext getMessageContext(byte messageLabel) throws AxisFault {
if (messageLabel == WSDLConstants.MESSAGE_LABEL_IN) {
return inMessageContext;
} else if (messageLabel == WSDLConstants.MESSAGE_LABEL_OUT) {
return outMessageContext;
} else {
throw new AxisFault("Unrecognized message label: '" + messageLabel
+ "'");
}
}
/**
* Checks to see if the MEP is complete. i.e. whether all the messages that
* are associated with the MEP has arrived and MEP is complete.
*
* @return
*/
public boolean isComplete() {
return isComplete;
}
/**
* Removes the pointers to this <code>OperationContext</code> in the
* <code>EngineContext</code>'s OperationContextMap so that this
* <code>OperationContext</code> will eventually get garbage collected
* along with the <code>MessageContext</code>'s it contains. Note that if
* the caller wants to make sure its safe to clean up this OperationContext
* he should call isComplete() first. However, in cases like IN_OPTIONAL_OUT
* and OUT_OPTIONAL_IN, it is possibe this will get called without the MEP
* being complete due to the optional nature of the MEP.
*/
public void cleanup() {
if (null != this.inMessageContext) {
operationContextMap.remove(inMessageContext.getMessageID());
}
if (null != this.outMessageContext) {
operationContextMap.remove(outMessageContext.getMessageID());
}
}
// public MessageContext createMessageContext(AxisM){
//
// }
}