| /* |
| * 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.client; |
| |
| import org.apache.axiom.om.OMElement; |
| import org.apache.axiom.om.util.UUIDGenerator; |
| import org.apache.axis2.AxisFault; |
| import org.apache.axis2.addressing.EndpointReference; |
| import org.apache.axis2.client.async.AxisCallback; |
| import org.apache.axis2.client.async.Callback; |
| 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.description.AxisOperation; |
| import org.apache.axis2.description.ClientUtils; |
| import org.apache.axis2.description.TransportOutDescription; |
| import org.apache.axis2.i18n.Messages; |
| import org.apache.axis2.util.TargetResolver; |
| import org.apache.axis2.wsdl.WSDLConstants; |
| |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import javax.xml.namespace.QName; |
| |
| /** |
| * An operation client is the way an advanced user interacts with Axis2. Actual |
| * operation clients understand a specific MEP and hence their behavior is |
| * defined by their MEP. To interact with an operation client, you first get one |
| * from a specific AxisOperation. Then you set the messages into it one by one |
| * (whatever is available). Then, when you call execute() the client will |
| * execute what it can at that point. If executing the operation client results |
| * in a new message being created, then if a message receiver is registered with |
| * the client then the message will be delivered to that client. |
| */ |
| public abstract class OperationClient { |
| |
| protected AxisOperation axisOp; |
| |
| protected ServiceContext sc; |
| |
| protected Options options; |
| |
| protected OperationContext oc; |
| |
| protected Callback callback; |
| |
| protected AxisCallback axisCallback; |
| |
| /* |
| * indicates whether the MEP execution has completed (and hence ready for |
| * resetting) |
| */ |
| protected boolean completed; |
| |
| protected OperationClient(AxisOperation axisOp, ServiceContext sc, Options options) { |
| this.axisOp = axisOp; |
| this.sc = sc; |
| this.options = new Options(options); |
| completed = false; |
| oc = sc.createOperationContext(axisOp); |
| } |
| |
| /** |
| * Sets the options that should be used for this particular client. This |
| * resets the entire set of options to use the new options - so you'd lose |
| * any option cascading that may have been set up. |
| * |
| * @param options the options |
| */ |
| public void setOptions(Options options) { |
| this.options = options; |
| } |
| |
| /** |
| * Return the options used by this client. If you want to set a single |
| * option, then the right way is to do getOptions() and set specific |
| * options. |
| * |
| * @return the options, which will never be null. |
| */ |
| public Options getOptions() { |
| return options; |
| } |
| |
| /** |
| * Add a message context to the client for processing. This method must not |
| * process the message - it only records it in the operation client. |
| * Processing only occurs when execute() is called. |
| * |
| * @param messageContext the message context |
| * @throws AxisFault if this is called inappropriately. |
| */ |
| public abstract void addMessageContext(MessageContext messageContext) throws AxisFault; |
| |
| /** |
| * Return a message from the client - will return null if the requested |
| * message is not available. |
| * |
| * @param messageLabel the message label of the desired message context |
| * @return the desired message context or null if its not available. |
| * @throws AxisFault if the message label is invalid |
| */ |
| public abstract MessageContext getMessageContext(String messageLabel) |
| throws AxisFault; |
| |
| /** |
| * Set the callback to be executed when a message comes into the MEP and the |
| * operation client is executed. This is the way the operation client |
| * provides notification that a message has been received by it. Exactly |
| * when its executed and under what conditions is a function of the specific |
| * operation client. |
| * |
| * @param callback the callback to be used when the client decides its time to |
| * use it |
| * @deprecated Please use the AxisCallback interface rather than Callback, which has been deprecated |
| */ |
| public abstract void setCallback(Callback callback); |
| |
| /** |
| * Set the callback to be executed when a message comes into the MEP and the |
| * operation client is executed. This is the way the operation client |
| * provides notification that a message has been received by it. Exactly |
| * when its executed and under what conditions is a function of the specific |
| * operation client. |
| * |
| * @param callback the callback to be used when the client decides its time to |
| * use it |
| */ |
| public final void setCallback(AxisCallback callback) { |
| axisCallback = callback; |
| } |
| |
| /** |
| * Execute the MEP. This method is final and only serves to set (if appropriate) |
| * the lastOperationContext on the ServiceContext, and then it calls |
| * executeImpl(), which does the actual work. |
| * |
| * @param block Indicates whether execution should block or return ASAP. What |
| * block means is of course a function of the specific operation |
| * client. |
| * @throws AxisFault if something goes wrong during the execution of the operation |
| * client. |
| */ |
| public final void execute(boolean block) throws AxisFault { |
| sc.setLastOperationContext(oc); |
| executeImpl(block); |
| } |
| |
| /** |
| * Execute the MEP. What this does depends on the specific operation client. |
| * The basic idea is to have the operation client execute and do something |
| * with the messages that have been added to it so far. For example, if its |
| * an Out-In MEP, then if the Out message has been set, then executing the |
| * client asks it to send the message and get the In message, possibly using |
| * a different thread. |
| * |
| * @param block Indicates whether execution should block or return ASAP. What |
| * block means is of course a function of the specific operation |
| * client. |
| * @throws AxisFault if something goes wrong during the execution of the operation |
| * client. |
| */ |
| public abstract void executeImpl(boolean block) throws AxisFault; |
| |
| /** |
| * Reset the operation client to a clean status after the MEP has completed. |
| * This is how you can reuse an operation client. NOTE: this does not reset |
| * the options; only the internal state so the client can be used again. |
| * |
| * @throws AxisFault if reset is called before the MEP client has completed an |
| * interaction. |
| */ |
| public void reset() throws AxisFault { |
| if (!completed) { |
| throw new AxisFault(Messages.getMessage("cannotreset")); |
| } |
| oc = null; |
| completed = false; |
| } |
| |
| |
| /** |
| * To close the transport if necessary , can call this method. The main |
| * usage of this method is when client uses two tarnsports for sending and |
| * receiving , and we need to remove entries for waiting calls in the |
| * transport listener queue. |
| * Note : DO NOT call this method if you are not using two transports to |
| * send and receive |
| * |
| * @param msgCtxt : MessageContext# which has all the transport information |
| * @throws AxisFault : throws AxisFault if something goes wrong |
| */ |
| public void complete(MessageContext msgCtxt) throws AxisFault { |
| TransportOutDescription trsout = msgCtxt.getTransportOut(); |
| if (trsout != null) { |
| trsout.getSender().cleanup(msgCtxt); |
| } |
| } |
| |
| |
| /** |
| * To get the operation context of the operation client |
| * |
| * @return OperationContext |
| */ |
| public OperationContext getOperationContext() { |
| return oc; |
| } |
| |
| /** |
| * Create a message ID for the given message context if needed. If user gives an option with |
| * MessageID then just copy that into MessageContext , and with that there can be multiple |
| * message with same MessageID unless user call setOption for each invocation. |
| * <p/> |
| * If user want to give message ID then the better way is to set the message ID in the option and |
| * call setOption for each invocation then the right thing will happen. |
| * <p/> |
| * If user does not give a message ID then the new one will be created and set that into Message |
| * Context. |
| * |
| * @param mc the message context whose id is to be set |
| */ |
| protected void setMessageID(MessageContext mc) { |
| // now its the time to put the parameters set by the user in to the |
| // correct places and to the |
| // if there is no message id still, set a new one. |
| String messageId = options.getMessageId(); |
| if (messageId == null || "".equals(messageId)) { |
| messageId = UUIDGenerator.getUUID(); |
| } |
| mc.setMessageID(messageId); |
| } |
| |
| protected void addReferenceParameters(MessageContext msgctx) { |
| EndpointReference to = msgctx.getTo(); |
| if (options.isManageSession() || (options.getParent() != null && |
| options.getParent().isManageSession())) { |
| EndpointReference tepr = sc.getTargetEPR(); |
| if (tepr != null) { |
| Map<QName, OMElement> map = tepr.getAllReferenceParameters(); |
| if (map != null) { |
| Iterator<OMElement> valuse = map.values().iterator(); |
| while (valuse.hasNext()) { |
| Object refparaelement = valuse.next(); |
| if (refparaelement instanceof OMElement) { |
| to.addReferenceParameter((OMElement) refparaelement); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * prepareMessageContext gets a fresh new MessageContext ready to be sent. |
| * It sets up the necessary properties, transport information, etc. |
| * |
| * @param configurationContext the active ConfigurationContext |
| * @param mc the MessageContext to be configured |
| * @throws AxisFault if there is a problem |
| */ |
| protected void prepareMessageContext(ConfigurationContext configurationContext, |
| MessageContext mc) |
| throws AxisFault { |
| // set options on the message context |
| if (mc.getSoapAction() == null || "".equals(mc.getSoapAction())) { |
| mc.setSoapAction(options.getAction()); |
| } |
| |
| mc.setOptions(new Options(options)); |
| mc.setAxisMessage(axisOp.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE)); |
| |
| // do Target Resolution |
| TargetResolver targetResolver = |
| configurationContext.getAxisConfiguration().getTargetResolverChain(); |
| if (targetResolver != null) { |
| targetResolver.resolveTarget(mc); |
| } |
| // if the transport to use for sending is not specified, try to find it |
| // from the URL |
| TransportOutDescription senderTransport = options.getTransportOut(); |
| if (senderTransport == null) { |
| EndpointReference toEPR = (options.getTo() != null) ? options |
| .getTo() : mc.getTo(); |
| senderTransport = ClientUtils.inferOutTransport(configurationContext |
| .getAxisConfiguration(), toEPR, mc); |
| } |
| mc.setTransportOut(senderTransport); |
| if (options.getParent() !=null && options.getParent().isManageSession()) { |
| mc.getOptions().setManageSession(true); |
| } else if (options.isManageSession()) { |
| mc.getOptions().setManageSession(true); |
| } |
| addReferenceParameters(mc); |
| } |
| } |