001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019:
020: package org.apache.axis2.client;
021:
022: import org.apache.axiom.om.OMElement;
023: import org.apache.axiom.om.util.UUIDGenerator;
024: import org.apache.axis2.AxisFault;
025: import org.apache.axis2.addressing.EndpointReference;
026: import org.apache.axis2.client.async.Callback;
027: import org.apache.axis2.client.async.AxisCallback;
028: import org.apache.axis2.context.ConfigurationContext;
029: import org.apache.axis2.context.MessageContext;
030: import org.apache.axis2.context.OperationContext;
031: import org.apache.axis2.context.ServiceContext;
032: import org.apache.axis2.description.AxisOperation;
033: import org.apache.axis2.description.ClientUtils;
034: import org.apache.axis2.description.TransportOutDescription;
035: import org.apache.axis2.i18n.Messages;
036: import org.apache.axis2.util.TargetResolver;
037: import org.apache.axis2.wsdl.WSDLConstants;
038:
039: import java.util.Iterator;
040: import java.util.Map;
041:
042: /**
043: * An operation client is the way an advanced user interacts with Axis2. Actual
044: * operation clients understand a specific MEP and hence their behavior is
045: * defined by their MEP. To interact with an operation client, you first get one
046: * from a specific AxisOperation. Then you set the messages into it one by one
047: * (whatever is available). Then, when you call execute() the client will
048: * execute what it can at that point. If executing the operation client results
049: * in a new message being created, then if a message receiver is registered with
050: * the client then the message will be delivered to that client.
051: */
052: public abstract class OperationClient {
053:
054: protected AxisOperation axisOp;
055:
056: protected ServiceContext sc;
057:
058: protected Options options;
059:
060: protected OperationContext oc;
061:
062: protected Callback callback;
063:
064: protected AxisCallback axisCallback;
065:
066: /*
067: * indicates whether the MEP execution has completed (and hence ready for
068: * resetting)
069: */
070: protected boolean completed;
071:
072: protected OperationClient(AxisOperation axisOp, ServiceContext sc,
073: Options options) {
074: this .axisOp = axisOp;
075: this .sc = sc;
076: this .options = new Options(options);
077: completed = false;
078: oc = sc.createOperationContext(axisOp);
079: }
080:
081: /**
082: * Sets the options that should be used for this particular client. This
083: * resets the entire set of options to use the new options - so you'd lose
084: * any option cascading that may have been set up.
085: *
086: * @param options the options
087: */
088: public void setOptions(Options options) {
089: this .options = options;
090: }
091:
092: /**
093: * Return the options used by this client. If you want to set a single
094: * option, then the right way is to do getOptions() and set specific
095: * options.
096: *
097: * @return the options, which will never be null.
098: */
099: public Options getOptions() {
100: return options;
101: }
102:
103: /**
104: * Add a message context to the client for processing. This method must not
105: * process the message - it only records it in the operation client.
106: * Processing only occurs when execute() is called.
107: *
108: * @param messageContext the message context
109: * @throws AxisFault if this is called inappropriately.
110: */
111: public abstract void addMessageContext(MessageContext messageContext)
112: throws AxisFault;
113:
114: /**
115: * Return a message from the client - will return null if the requested
116: * message is not available.
117: *
118: * @param messageLabel the message label of the desired message context
119: * @return the desired message context or null if its not available.
120: * @throws AxisFault if the message label is invalid
121: */
122: public abstract MessageContext getMessageContext(String messageLabel)
123: throws AxisFault;
124:
125: /**
126: * Set the callback to be executed when a message comes into the MEP and the
127: * operation client is executed. This is the way the operation client
128: * provides notification that a message has been received by it. Exactly
129: * when its executed and under what conditions is a function of the specific
130: * operation client.
131: *
132: * @param callback the callback to be used when the client decides its time to
133: * use it
134: * @deprecated Please use the AxisCallback interface rather than Callback, which has been deprecated
135: */
136: public abstract void setCallback(Callback callback);
137:
138: /**
139: * Set the callback to be executed when a message comes into the MEP and the
140: * operation client is executed. This is the way the operation client
141: * provides notification that a message has been received by it. Exactly
142: * when its executed and under what conditions is a function of the specific
143: * operation client.
144: *
145: * @param callback the callback to be used when the client decides its time to
146: * use it
147: */
148: public final void setCallback(AxisCallback callback) {
149: axisCallback = callback;
150: }
151:
152: /**
153: * Execute the MEP. This method is final and only serves to set (if appropriate)
154: * the lastOperationContext on the ServiceContext, and then it calls
155: * executeImpl(), which does the actual work.
156: *
157: * @param block Indicates whether execution should block or return ASAP. What
158: * block means is of course a function of the specific operation
159: * client.
160: * @throws AxisFault if something goes wrong during the execution of the operation
161: * client.
162: */
163: public final void execute(boolean block) throws AxisFault {
164: sc.setLastOperationContext(oc);
165: executeImpl(block);
166: }
167:
168: /**
169: * Execute the MEP. What this does depends on the specific operation client.
170: * The basic idea is to have the operation client execute and do something
171: * with the messages that have been added to it so far. For example, if its
172: * an Out-In MEP, then if the Out message has been set, then executing the
173: * client asks it to send the message and get the In message, possibly using
174: * a different thread.
175: *
176: * @param block Indicates whether execution should block or return ASAP. What
177: * block means is of course a function of the specific operation
178: * client.
179: * @throws AxisFault if something goes wrong during the execution of the operation
180: * client.
181: */
182: public abstract void executeImpl(boolean block) throws AxisFault;
183:
184: /**
185: * Reset the operation client to a clean status after the MEP has completed.
186: * This is how you can reuse an operation client. NOTE: this does not reset
187: * the options; only the internal state so the client can be used again.
188: *
189: * @throws AxisFault if reset is called before the MEP client has completed an
190: * interaction.
191: */
192: public void reset() throws AxisFault {
193: if (!completed) {
194: throw new AxisFault(Messages.getMessage("cannotreset"));
195: }
196: oc = null;
197: completed = false;
198: }
199:
200: /**
201: * To close the transport if necessary , can call this method. The main
202: * usage of this method is when client uses two tarnsports for sending and
203: * receiving , and we need to remove entries for waiting calls in the
204: * transport listener queue.
205: * Note : DO NOT call this method if you are not using two transports to
206: * send and receive
207: *
208: * @param msgCtxt : MessageContext# which has all the transport information
209: * @throws AxisFault : throws AxisFault if something goes wrong
210: */
211: public void complete(MessageContext msgCtxt) throws AxisFault {
212: TransportOutDescription trsout = msgCtxt.getTransportOut();
213: if (trsout != null) {
214: trsout.getSender().cleanup(msgCtxt);
215: }
216: }
217:
218: /**
219: * To get the operation context of the operation client
220: *
221: * @return OperationContext
222: */
223: public OperationContext getOperationContext() {
224: return oc;
225: }
226:
227: /**
228: * Create a message ID for the given message context if needed. If user gives an option with
229: * MessageID then just copy that into MessageContext , and with that there can be multiple
230: * message with same MessageID unless user call setOption for each invocation.
231: * <p/>
232: * If user want to give message ID then the better way is to set the message ID in the option and
233: * call setOption for each invocation then the right thing will happen.
234: * <p/>
235: * If user does not give a message ID then the new one will be created and set that into Message
236: * Context.
237: *
238: * @param mc the message context whose id is to be set
239: */
240: protected void setMessageID(MessageContext mc) {
241: // now its the time to put the parameters set by the user in to the
242: // correct places and to the
243: // if there is no message id still, set a new one.
244: String messageId = options.getMessageId();
245: if (messageId == null || "".equals(messageId)) {
246: messageId = UUIDGenerator.getUUID();
247: }
248: mc.setMessageID(messageId);
249: }
250:
251: protected void addReferenceParameters(MessageContext msgctx) {
252: EndpointReference to = msgctx.getTo();
253: if (options.isManageSession()
254: || (options.getParent() != null && options.getParent()
255: .isManageSession())) {
256: EndpointReference tepr = sc.getTargetEPR();
257: if (tepr != null) {
258: Map map = tepr.getAllReferenceParameters();
259: if (map != null) {
260: Iterator valuse = map.values().iterator();
261: while (valuse.hasNext()) {
262: Object refparaelement = valuse.next();
263: if (refparaelement instanceof OMElement) {
264: to
265: .addReferenceParameter((OMElement) refparaelement);
266: }
267: }
268: }
269: }
270: }
271: }
272:
273: /**
274: * prepareMessageContext gets a fresh new MessageContext ready to be sent.
275: * It sets up the necessary properties, transport information, etc.
276: *
277: * @param configurationContext the active ConfigurationContext
278: * @param mc the MessageContext to be configured
279: * @throws AxisFault if there is a problem
280: */
281: protected void prepareMessageContext(
282: ConfigurationContext configurationContext, MessageContext mc)
283: throws AxisFault {
284: // set options on the message context
285: if (mc.getSoapAction() == null || "".equals(mc.getSoapAction())) {
286: mc.setSoapAction(options.getAction());
287: }
288:
289: mc.setOptions(new Options(options));
290: mc.setAxisMessage(axisOp
291: .getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE));
292:
293: // do Target Resolution
294: TargetResolver targetResolver = configurationContext
295: .getAxisConfiguration().getTargetResolverChain();
296: if (targetResolver != null) {
297: targetResolver.resolveTarget(mc);
298: }
299: // if the transport to use for sending is not specified, try to find it
300: // from the URL
301: TransportOutDescription senderTransport = options
302: .getTransportOut();
303: if (senderTransport == null) {
304: EndpointReference toEPR = (options.getTo() != null) ? options
305: .getTo()
306: : mc.getTo();
307: senderTransport = ClientUtils.inferOutTransport(
308: configurationContext.getAxisConfiguration(), toEPR,
309: mc);
310: }
311: mc.setTransportOut(senderTransport);
312: if (options.getParent() != null
313: && options.getParent().isManageSession()) {
314: mc.getOptions().setManageSession(true);
315: } else if (options.isManageSession()) {
316: mc.getOptions().setManageSession(true);
317: }
318: addReferenceParameters(mc);
319: }
320: }
|