Source code: org/apache/axis/client/AxisClient.java
1 /*
2 * Copyright 2001-2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.apache.axis.client ;
18
19 import javax.xml.namespace.QName;
20 import javax.xml.rpc.handler.HandlerChain;
21
22 import org.apache.axis.AxisEngine;
23 import org.apache.axis.AxisFault;
24 import org.apache.axis.Constants;
25 import org.apache.axis.EngineConfiguration;
26 import org.apache.axis.Handler;
27 import org.apache.axis.MessageContext;
28 import org.apache.axis.components.logger.LogFactory;
29 import org.apache.axis.configuration.EngineConfigurationFactoryFinder;
30 import org.apache.axis.handlers.HandlerInfoChainFactory;
31 import org.apache.axis.handlers.soap.MustUnderstandChecker;
32 import org.apache.axis.handlers.soap.SOAPService;
33 import org.apache.axis.utils.Messages;
34 import org.apache.commons.logging.Log;
35
36 /**
37 * Provides the equivalent of an "Axis engine" on the client side.
38 * Subclasses hardcode initialization & setup logic for particular
39 * client-side transports.
40 *
41 * @author Rob Jellinghaus (robj@unrealities.com)
42 * @author Doug Davis (dug@us.ibm.com)
43 * @author Glen Daniels (gdaniels@allaire.com)
44 */
45 public class AxisClient extends AxisEngine {
46 protected static Log log =
47 LogFactory.getLog(AxisClient.class.getName());
48
49 MustUnderstandChecker checker = new MustUnderstandChecker(null);
50
51 public AxisClient(EngineConfiguration config) {
52 super(config);
53 }
54
55 public AxisClient() {
56 this(EngineConfigurationFactoryFinder.newFactory().
57 getClientEngineConfig());
58 }
59
60 /**
61 * @return this instance, as this is the client engine
62 */
63 public AxisEngine getClientEngine () {
64 return this;
65 }
66
67 /**
68 * Main routine of the AXIS engine. In short we locate the appropriate
69 * handler for the desired service and invoke() it.
70 *
71 * @param msgContext the <code>MessageContext</code> to invoke relative
72 * to
73 * @throws AxisFault if anything goes wrong during invocation
74 */
75 public void invoke(MessageContext msgContext) throws AxisFault {
76 if (log.isDebugEnabled()) {
77 log.debug("Enter: AxisClient::invoke");
78 }
79 String hName = null;
80 Handler h = null;
81 HandlerChain handlerImpl = null;
82
83 // save previous context
84 MessageContext previousContext = getCurrentMessageContext();
85 try {
86 // set active context
87 setCurrentMessageContext(msgContext);
88 hName = msgContext.getStrProp(MessageContext.ENGINE_HANDLER);
89 if (log.isDebugEnabled()) {
90 log.debug("EngineHandler: " + hName);
91 }
92 if (hName != null) {
93 h = getHandler(hName);
94 if (h != null)
95 h.invoke(msgContext);
96 else
97 throw new AxisFault("Client.error",
98 Messages.getMessage("noHandler00",
99 hName),
100 null, null);
101 } else {
102 /* Now we do the 'real' work. The flow is basically: */
103 /* */
104 /* Service Specific Request Chain */
105 /* Global Request Chain */
106 /* Transport Request Chain - must have a send at the end */
107 /* Transport Response Chain */
108 /* Global Response Chain */
109 /* Service Specific Response Chain */
110 /* Protocol Specific-Handler/Checker */
111 /**************************************************************/
112 SOAPService service = null;
113 msgContext.setPastPivot(false);
114
115 /* Process the Service Specific Request Chain */
116 /**********************************************/
117 service = msgContext.getService();
118 if (service != null) {
119 h = service.getRequestHandler();
120 if (h != null)
121 h.invoke(msgContext);
122 }
123
124 /* Process the Global Request Chain */
125 /**********************************/
126 if ((h = getGlobalRequest()) != null)
127 h.invoke(msgContext);
128
129 /* Process the JAX-RPC Handlers - handleRequest.
130 * Make sure to set the pastPivot to true if this returns a
131 * false. In that case we do not invoke the transport request
132 * chain. Also note that if a a false was returned from the
133 * JAX-RPC handler chain, then the chain still holds the index
134 * of the handler that returned false. So when we invoke the
135 * handleResponse method of the chain, it will correctly call
136 * the handleResponse from that specific handler instance. So
137 * do not destroy the chain at this point - the chain will be
138 * destroyed in the finally block.
139 */
140 handlerImpl = getJAXRPChandlerChain(msgContext);
141 if (handlerImpl != null) {
142 try {
143 if (!handlerImpl.handleRequest(msgContext)) {
144 msgContext.setPastPivot(true);
145 }
146 } catch (RuntimeException re) {
147 handlerImpl.destroy(); // WS4EE 1.1 6.2.2.1 Handler Life Cycle. "RuntimeException" --> destroy handler
148 throw re;
149 }
150 }
151
152 /** Process the Transport Specific stuff
153 *
154 * NOTE: Somewhere in here there is a handler which actually
155 * sends the message and receives a response. Generally
156 * this is the pivot point in the Transport chain. But invoke
157 * this only if pivot point has not been set to false. This
158 * can be set to false if any of the JAX-RPC handler's
159 * handleRequest returned false.
160 */
161 if (!msgContext.getPastPivot()) {
162 hName = msgContext.getTransportName();
163 if (hName != null && (h = getTransport(hName)) != null) {
164 try {
165 h.invoke(msgContext);
166 } catch (AxisFault e) {
167 throw e;
168 }
169 } else {
170 throw new AxisFault(Messages.getMessage("noTransport00",
171 hName));
172 }
173 }
174
175 msgContext.setPastPivot(true);
176 if (!msgContext.isPropertyTrue(Call.ONE_WAY)) {
177 if ((handlerImpl != null) &&
178 !msgContext.isPropertyTrue(Call.ONE_WAY)) {
179 try {
180 handlerImpl.handleResponse(msgContext);
181 } catch (RuntimeException ex) {
182 handlerImpl.destroy(); // WS4EE 1.1 6.2.2.1 Handler Life Cycle. "RuntimeException" --> destroy handler
183 throw ex;
184 }
185 }
186
187 /* Process the Global Response Chain */
188 /***********************************/
189 if ((h = getGlobalResponse()) != null) {
190 h.invoke(msgContext);
191 }
192
193 /* Process the Service-Specific Response Chain */
194 /***********************************************/
195 if (service != null) {
196 h = service.getResponseHandler();
197 if (h != null) {
198 h.invoke(msgContext);
199 }
200 }
201
202 // Do SOAP Semantics checks here - this needs to be a call
203 // to a pluggable object/handler/something
204 if (msgContext.isPropertyTrue(Call.CHECK_MUST_UNDERSTAND,
205 true)) {
206 checker.invoke(msgContext);
207 }
208 }
209 }
210 } catch (Exception e) {
211 // Should we even bother catching it ?
212 if (e instanceof AxisFault) {
213 throw (AxisFault) e;
214 } else {
215 log.debug(Messages.getMessage("exception00"), e);
216 throw AxisFault.makeFault(e);
217 }
218 } finally {
219 if (handlerImpl != null) {
220 handlerImpl.destroy();
221 }
222 // restore previous state
223 setCurrentMessageContext(previousContext);
224 }
225 if (log.isDebugEnabled()) {
226 log.debug("Exit: AxisClient::invoke");
227 }
228 }
229
230 /**
231 * @param context Stores the Service, port QName and optionnaly a HandlerInfoChainFactory
232 * @return Returns a HandlerChain if one has been specified
233 */
234 protected HandlerChain getJAXRPChandlerChain(MessageContext context) {
235 java.util.List chain = null;
236 HandlerInfoChainFactory hiChainFactory = null;
237 boolean clientSpecified = false;
238
239 Service service = (Service) context.getProperty(Call.WSDL_SERVICE);
240 if(service == null) {
241 return null;
242 }
243
244 QName portName = (QName) context.getProperty(Call.WSDL_PORT_NAME);
245 if(portName == null) {
246 return null;
247 }
248
249 javax.xml.rpc.handler.HandlerRegistry registry;
250 registry = service.getHandlerRegistry();
251 if(registry != null) {
252 chain = registry.getHandlerChain(portName);
253 if ((chain != null) && (!chain.isEmpty())) {
254 hiChainFactory = new HandlerInfoChainFactory(chain);
255 clientSpecified = true;
256 }
257 }
258
259 // Otherwise, use the container support
260 if (!clientSpecified) {
261 SOAPService soapService = context.getService();
262 if (soapService != null) {
263 // A client configuration exists for this service. Check
264 // to see if there is a HandlerInfoChain configured on it.
265 hiChainFactory = (HandlerInfoChainFactory)
266 soapService.getOption(Constants.ATTR_HANDLERINFOCHAIN);
267 }
268 }
269
270 if (hiChainFactory == null) {
271 return null;
272 }
273
274 return hiChainFactory.createHandlerChain();
275 }
276
277 }