| /* |
| * 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.jaxws.core; |
| |
| import org.apache.axiom.om.util.DetachableInputStream; |
| import org.apache.axis2.AxisFault; |
| import org.apache.axis2.Constants; |
| import org.apache.axis2.description.AxisService; |
| import org.apache.axis2.jaxws.description.EndpointDescription; |
| import org.apache.axis2.jaxws.description.OperationDescription; |
| import org.apache.axis2.jaxws.handler.MEPContext; |
| import org.apache.axis2.jaxws.message.Message; |
| import org.apache.axis2.jaxws.message.util.MessageUtils; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| |
| import javax.xml.namespace.QName; |
| import javax.xml.ws.BindingProvider; |
| import javax.xml.ws.Service.Mode; |
| import javax.xml.ws.WebServiceException; |
| |
| import java.io.IOException; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| /** |
| * The <code>org.apache.axis2.jaxws.core.MessageContext</code> is an interface that extends the |
| * JAX-WS 2.0 <code>javax.xml.ws.handler.MessageContext</code> defined in the spec. This |
| * encapsulates all of the functionality needed of the MessageContext for the other JAX-WS spec |
| * pieces (the handlers for example) and also provides the needed bits of contextual information for |
| * the rest of the JAX-WS implementation. |
| * <p/> |
| * Specifically, this is responsible for providing APIs so that the client and server implementation |
| * portions can get to the Message, defined by the Message Model format and also any metadata that |
| * is available. |
| */ |
| public class MessageContext { |
| |
| private static Log log = LogFactory.getLog(MessageContext.class); |
| |
| private InvocationContext invocationCtx; |
| private org.apache.axis2.context.MessageContext axisMsgCtx; |
| private EndpointDescription endpointDesc; |
| private OperationDescription operationDesc; |
| private QName operationName; //FIXME: This should become the OperationDescription |
| private Message message; |
| private Mode mode; |
| private boolean isOutbound; // Outbound or inbound message context |
| private boolean isServer = false; // Indicate if server role, default is false |
| |
| /* |
| * JAXWS runtime uses a request and response mc, but we need to know the pair. |
| * We will use this mepCtx as a wrapper to the request and response message contexts |
| * where the requestMC and responseMC have the same parent MEPContext to |
| * preserve the relationship. |
| */ |
| private MEPContext mepCtx; |
| |
| // If a local exception is thrown, the exception is placed on the message context. |
| // It is not converted into a Message. |
| private Throwable localException = null; |
| private AxisFault causedByException = null; |
| |
| /** |
| * Construct a MessageContext without a prior Axis2 MessageContext |
| * (usage outbound dispatch/proxy) |
| */ |
| public MessageContext() { |
| axisMsgCtx = new org.apache.axis2.context.MessageContext(); |
| isOutbound = true; |
| } |
| |
| /** |
| * Construct a MessageContext with a prior MessageContext |
| * (usage inbound client/server or outbound server) |
| * @param mc |
| * @throws WebServiceException |
| */ |
| public MessageContext(org.apache.axis2.context.MessageContext mc) throws WebServiceException { |
| // Assume inbound (caller must setOutbound) |
| isOutbound = false; |
| |
| /* |
| * Instead of creating a member MEPContext object every time, we will |
| * rely on users of this MessageContext class to create a new |
| * MEPContext and call setMEPContext(MEPContext) |
| */ |
| |
| if (mc != null) { |
| axisMsgCtx = mc; |
| message = MessageUtils.getMessageFromMessageContext(mc); |
| if (message != null) { |
| message.setMessageContext(this); |
| } |
| } else { |
| axisMsgCtx = new org.apache.axis2.context.MessageContext(); |
| } |
| } |
| |
| public InvocationContext getInvocationContext() { |
| return invocationCtx; |
| } |
| |
| public void setInvocationContext(InvocationContext ic) { |
| invocationCtx = ic; |
| } |
| |
| public Map<String, Object> getProperties() { |
| // only use properties that are local to the axis2 MC, |
| // not the options bag. See org.apache.axis2.context.AbstractContext |
| Iterator names = axisMsgCtx.getPropertyNames(); |
| HashMap tempProps = new HashMap<String, Object>(); |
| for (; names.hasNext();) { |
| String name = (String)names.next(); |
| tempProps.put(name, axisMsgCtx.getProperty(name)); |
| } |
| //return new ReadOnlyProperties(tempProps); |
| return tempProps; |
| } |
| |
| public void setProperties(Map<String, Object> _properties) { |
| // make sure copy is made, not just reference: |
| _properties.put(org.apache.axis2.context.MessageContext.COPY_PROPERTIES, true); |
| axisMsgCtx.setProperties(_properties); |
| } |
| |
| public Object getProperty(String key) { |
| // only use properties that are local to the axis2 MC. |
| return axisMsgCtx.getLocalProperty(key, false); |
| } |
| |
| public boolean containsKey(Object key) { |
| // Only use properties that are local to the axis2 MC. |
| // @see getProperty(String key) |
| return (key instanceof String && getProperty((String)key) != null); |
| } |
| |
| // acts like Map.put(key, value) |
| public Object setProperty(String key, Object value) { |
| // only use properties that are local to the axis2 MC |
| Object retval = axisMsgCtx.getLocalProperty(key, false); |
| axisMsgCtx.setProperty(key, value); |
| return retval; |
| } |
| |
| public EndpointDescription getEndpointDescription() { |
| return endpointDesc; |
| } |
| |
| public void setEndpointDescription(EndpointDescription ed) { |
| endpointDesc = ed; |
| } |
| |
| public OperationDescription getOperationDescription() { |
| return operationDesc; |
| } |
| |
| public void setOperationDescription(OperationDescription od) { |
| operationDesc = od; |
| } |
| |
| public Mode getMode() { |
| return mode; |
| } |
| |
| public void setMode(Mode m) { |
| mode = m; |
| } |
| |
| //FIXME: This should become the OperationDescription |
| public QName getOperationName() { |
| return operationName; |
| } |
| |
| //FIXME: This should become the OperationDescription |
| public void setOperationName(QName op) { |
| operationName = op; |
| } |
| |
| public void setMessage(Message msg) { |
| message = msg; |
| msg.setMessageContext(this); |
| } |
| |
| public Message getMessage() { |
| return message; |
| } |
| |
| public org.apache.axis2.context.MessageContext getAxisMessageContext() { |
| return axisMsgCtx; |
| } |
| |
| public ClassLoader getClassLoader() { |
| AxisService svc = axisMsgCtx.getAxisService(); |
| if (svc != null) |
| return svc.getClassLoader(); |
| else |
| return null; |
| } |
| |
| /** |
| * Used to determine whether or not session state has been enabled. |
| * |
| * @return |
| */ |
| public boolean isMaintainSession() { |
| boolean maintainSession = false; |
| |
| Boolean value = (Boolean) getProperty(BindingProvider.SESSION_MAINTAIN_PROPERTY); |
| if (value != null && value.booleanValue()) { |
| maintainSession = true; |
| } |
| |
| return maintainSession; |
| } |
| |
| /** |
| * The local exception is the Throwable object held on the Message from a problem that occurred |
| * due to something other than the server. In other words, no message ever travelled across |
| * the wire. |
| * |
| * @return the Throwable object or null |
| */ |
| public Throwable getLocalException() { |
| return localException; |
| } |
| |
| /** |
| * The local exception is the Throwable object held on the Message from a problem that occurred |
| * due to something other than the server. In other words, no message ever travelled across the |
| * wire. |
| * |
| * @param t |
| * @see Throwable |
| */ |
| public void setLocalException(Throwable t) { |
| localException = t; |
| } |
| |
| /** |
| * @param t |
| */ |
| public void setCausedByException (AxisFault t){ |
| this.causedByException = t; |
| } |
| |
| /** |
| * @return |
| */ |
| public AxisFault getCausedByException(){ |
| return this.causedByException; |
| } |
| |
| |
| /** |
| * Set the wrapper MEPContext. Internally, this method also sets |
| * the MEPContext's children so the pointer is bi-directional; you can |
| * get the MEPContext from the MessageContext and vice-versa. |
| * |
| * @param mepCtx |
| */ |
| public void setMEPContext(MEPContext mepCtx) { |
| if (this.mepCtx == null) { |
| this.mepCtx = mepCtx; |
| // and set parent's child pointer |
| this.mepCtx.setResponseMessageContext(this); |
| } |
| } |
| |
| public MEPContext getMEPContext() { |
| if (mepCtx == null) { |
| setMEPContext(new MEPContext(this)); |
| } |
| return mepCtx; |
| } |
| |
| /** |
| * @return if outbound MessageContext |
| */ |
| public boolean isOutbound() { |
| return isOutbound; |
| } |
| |
| /** |
| * @param isOutbound true if outbound MessageContext |
| */ |
| public void setOutbound(boolean isOutbound) { |
| this.isOutbound = isOutbound; |
| } |
| |
| /** |
| * @return true if server role |
| */ |
| public boolean isServer() { |
| return isServer; |
| } |
| |
| /** |
| * Indicate if server role |
| * @param isServer |
| */ |
| public void setServer(boolean isServer) { |
| this.isServer = isServer; |
| } |
| |
| /** |
| * Free the resources associated with the incoming input stream. (i.e. HTTPInputStream) |
| * This allows the transport layer to free resources and pool connections |
| */ |
| public void freeInputStream() throws IOException { |
| |
| |
| // During builder processing, the original input stream was wrapped with |
| // a detachable input stream. The detachable input stream's detach method |
| // causes the original stream to be consumed and closed. |
| DetachableInputStream is = (DetachableInputStream) |
| getProperty(Constants.DETACHABLE_INPUT_STREAM); |
| if (is != null) { |
| if (log.isDebugEnabled()) { |
| log.debug("Detaching inbound input stream " + is); |
| } |
| is.detach(); |
| } |
| } |
| } |