1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.axis.message.addressing.handler;
19
20 import org.apache.axis.AxisFault;
21 import org.apache.axis.Message;
22 import org.apache.axis.MessageContext;
23 import org.apache.axis.client.Call;
24 import org.apache.axis.client.Service;
25 import org.apache.axis.message.SOAPEnvelope;
26 import org.apache.axis.message.SOAPBodyElement;
27 import org.apache.axis.message.RPCElement;
28 import org.apache.axis.description.OperationDesc;
29 import org.apache.axis.components.uuid.UUIDGen;
30 import org.apache.axis.components.uuid.UUIDGenFactory;
31 import org.apache.axis.handlers.BasicHandler;
32 import org.apache.axis.message.addressing.Action;
33 import org.apache.axis.message.addressing.AttributedURI;
34 import org.apache.axis.message.addressing.AddressingHeaders;
35 import org.apache.axis.message.addressing.Constants;
36 import org.apache.axis.message.addressing.EndpointReference;
37 import org.apache.axis.message.addressing.EndpointReferenceType;
38 import org.apache.axis.message.addressing.MessageID;
39 import org.apache.axis.message.addressing.To;
40 import org.apache.axis.message.addressing.util.AddressingUtils;
41 import org.apache.axis.types.URI;
42
43 import org.apache.commons.logging.Log;
44 import org.apache.commons.logging.LogFactory;
45
46 import javax.xml.namespace.QName;
47 import java.util.ArrayList;
48 import java.util.List;
49 import java.util.StringTokenizer;
50
51 /***
52 * Class AddressingHandler
53 *
54 * @author Davanum Srinivas (dims@yahoo.com)
55 */
56 public class AddressingHandler extends BasicHandler {
57
58 protected static Log log =
59 LogFactory.getLog(AddressingHandler.class.getName());
60
61
62 private static UUIDGen uuidGen = UUIDGenFactory.getUUIDGen();
63
64
65
66
67
68 private List refPropQNames;
69
70 private String actor;
71
72 private boolean removeHeaders = false;
73
74 public AddressingHandler() {}
75
76 /***
77 * Initialize the addressing handler.
78 */
79 public void init() {
80 super.init();
81 initializeReferencePropertyNames();
82 initializeRemoveHeaders();
83 initializeActor();
84 }
85
86 protected void initializeActor() {
87 actor = (String) getOption("actor");
88 }
89
90 private void initializeRemoveHeaders() {
91 String property = (String) getOption("removeHeaders");
92 this.removeHeaders = "true".equalsIgnoreCase(property);
93 }
94
95 /***
96 * Method invoke
97 *
98 * @param msgContext
99 * @throws AxisFault
100 */
101 public void invoke(MessageContext msgContext) throws AxisFault {
102 boolean setMustUnderstand =
103 msgContext.isPropertyTrue(Constants.ENV_ADDRESSING_SET_MUST_UNDERSTAND);
104
105 try {
106 if (msgContext.isClient()) {
107 if (!msgContext.getPastPivot()) {
108 processClientRequest(msgContext, setMustUnderstand);
109 } else {
110 processClientResponse(msgContext);
111 }
112 } else {
113 if (!msgContext.getPastPivot()) {
114 processServerRequest(msgContext);
115 } else {
116 processServerResponse(msgContext, setMustUnderstand);
117 }
118 }
119 } catch (Exception e) {
120 log.error("Exception in AddressingHandler", e);
121 throw AxisFault.makeFault(e);
122 }
123 }
124
125 public void onFault(MessageContext msgContext) {
126 if (msgContext.isClient()) {
127 return;
128 }
129 try {
130 processFault(msgContext);
131 } catch (Exception e) {
132 log.error("Exception in AddressingHandler", e);
133 }
134 }
135
136 protected void processFault(MessageContext msgContext)
137 throws Exception {
138 AddressingHeaders reqHeaders =
139 (AddressingHeaders) msgContext.getProperty(
140 Constants.ENV_ADDRESSING_REQUEST_HEADERS
141 );
142
143 if (reqHeaders == null) {
144
145 return;
146 }
147
148 AddressingHeaders resHeaders =
149 AddressingUtils.getResponseHeaders(msgContext);
150
151
152 EndpointReference fromEPR = resHeaders.getFrom();
153 if (fromEPR == null) {
154 To toURI = reqHeaders.getTo();
155 if (toURI != null) {
156 fromEPR = new EndpointReference(toURI);
157 fromEPR.setProperties(reqHeaders.getReferenceProperties());
158 resHeaders.setFrom(fromEPR);
159 }
160 }
161
162
163 if (Constants.NS_URI_ADDRESSING_DEFAULT.equals(Constants.NS_URI_ADDRESSING_2004_03)) {
164 resHeaders.setAction(new Action(new URI(Constants.FAULT_ACTION)));
165 }
166
167 MessageID msgID = null;
168
169
170 msgID = reqHeaders.getMessageID();
171 if (msgID != null) {
172 resHeaders.addRelatesTo(msgID.toString(),
173 Constants.QNAME_RESPONSE);
174 }
175
176
177 msgID = new MessageID(new URI("uuid:" + uuidGen.nextUUID()));
178 resHeaders.setMessageID(msgID);
179
180
181 Message msg = msgContext.getCurrentMessage();
182 if (msg == null) {
183 return;
184 }
185
186 resHeaders.toEnvelope(msg.getSOAPEnvelope());
187
188
189 EndpointReferenceType faultTo = reqHeaders.getFaultTo();
190 if (faultTo != null) {
191 AttributedURI address = faultTo.getAddress();
192 if (address != null) {
193 String uri = address.toString();
194 if (uri != null) {
195
196 forwardMessage(faultTo, msg);
197
198
199 msgContext.setCurrentMessage(null);
200 }
201 }
202 }
203 }
204
205 /***
206 * Method processClientRequest
207 *
208 * @param msgContext
209 */
210 protected void processClientRequest(MessageContext msgContext,
211 boolean setMustUnderstand)
212 throws Exception {
213
214 AddressingHeaders sharedHeaders =
215 (AddressingHeaders) msgContext.getProperty(
216 Constants.ENV_ADDRESSING_SHARED_HEADERS
217 );
218
219 AddressingHeaders headers =
220 AddressingUtils.getRequestHeaders(msgContext);
221
222 headers.setSetMustUnderstand(setMustUnderstand);
223
224
225 if (headers.getMessageID() == null) {
226 MessageID id =
227 new MessageID(new URI("uuid:" + uuidGen.nextUUID()));
228 headers.setMessageID(id);
229 }
230
231
232 To to = headers.getTo();
233 if (to == null) {
234 if (sharedHeaders != null) {
235
236 headers.setTo(sharedHeaders.getTo());
237 } else {
238 headers.setTo(new To(msgContext.getStrProp(MessageContext.TRANS_URL)));
239 }
240 }
241
242
243 String action = msgContext.getSOAPActionURI();
244 if (action != null) {
245 headers.setAction(new Action(new URI(action)));
246 } else if(headers.getAction() != null) {
247 msgContext.setUseSOAPAction(true);
248
249 msgContext.setSOAPActionURI(headers.getAction().toString());
250 }
251
252
253 if (headers.getFrom() == null) {
254 String from =
255 msgContext.getStrProp(Constants.ENV_ADDRESSING_FROM_URI);
256 if (from != null) {
257 headers.setFrom(new EndpointReference(from));
258 } else {
259 headers.setFrom(new EndpointReference(
260 Constants.NS_URI_ANONYMOUS));
261 }
262 }
263
264
265 if (msgContext.isPropertyTrue(Constants.ENV_ADDRESSING_SEND_REPLYTO)) {
266 if (headers.getReplyTo() == null) {
267 String replyTo = msgContext.getStrProp(Constants.ENV_ADDRESSING_REPLYTO_URI);
268 if (replyTo != null) {
269 headers.setReplyTo(new EndpointReference(replyTo));
270 } else {
271 headers.setReplyTo(headers.getFrom());
272 }
273 }
274 }
275
276
277 if (headers.getFaultTo() == null) {
278 String faultTo =
279 msgContext.getStrProp(Constants.ENV_ADDRESSING_FAULTTO_URI);
280 if (faultTo != null) {
281 headers.setFaultTo(new EndpointReference(faultTo));
282 }
283 }
284
285 if (sharedHeaders != null) {
286 headers.setReferenceProperties(sharedHeaders.getReferenceProperties());
287 }
288 Message msg = msgContext.getRequestMessage();
289 headers.toEnvelope(msg.getSOAPEnvelope(), this.actor);
290 }
291
292 /***
293 * Method processClientResponse
294 *
295 * @param msgContext
296 */
297 protected void processClientResponse(MessageContext msgContext)
298 throws Exception {
299
300 Message msg = msgContext.getResponseMessage();
301 if (msg == null) {
302 return;
303 }
304
305 AddressingHeaders headers =
306 new AddressingHeaders(msg.getSOAPEnvelope(),
307 this.actor,
308 true,
309 this.removeHeaders,
310 false,
311 this.refPropQNames);
312 msgContext.setProperty(Constants.ENV_ADDRESSING_RESPONSE_HEADERS,
313 headers);
314 }
315
316 /***
317 * Method processServerRequest
318 *
319 * @param msgContext
320 * @throws Exception
321 */
322 protected void processServerRequest(MessageContext msgContext)
323 throws Exception {
324 Message msg = msgContext.getRequestMessage();
325 if (msg == null) {
326 return;
327 }
328 AddressingHeaders headers =
329 new AddressingHeaders(msg.getSOAPEnvelope(),
330 this.actor,
331 true,
332 this.removeHeaders,
333 false,
334 this.refPropQNames);
335
336 if (headers.getTo()==null)
337 {
338
339 return;
340 }
341 if (headers.getAction()==null)
342 {
343
344 log.debug("WS-A request to endpoint " + headers.getTo() + " is missing the required wsa:Action header.");
345 }
346
347 msgContext.setProperty(Constants.ENV_ADDRESSING_REQUEST_HEADERS,
348 headers);
349
350
351
352
353 if (msgContext.getService() == null &&
354 msgContext.getTargetService() == null) {
355 setTargetService(msgContext, headers);
356
357 if (msgContext.getService() != null) {
358 resetOperations(msgContext);
359 }
360 }
361 }
362
363 protected void resetOperations(MessageContext msgContext)
364 throws AxisFault {
365 resetContextOperations(msgContext);
366 }
367
368
369
370 public static void resetContextOperations(MessageContext msgContext)
371 throws AxisFault {
372 Message msg = msgContext.getCurrentMessage();
373 if (msg == null) {
374 return;
375 }
376 SOAPEnvelope env = msg.getSOAPEnvelope();
377 if (env == null) {
378 return;
379 }
380 SOAPBodyElement bodyElement = env.getFirstBody();
381 if (bodyElement != null && bodyElement instanceof RPCElement) {
382 RPCElement element = (RPCElement)bodyElement;
383
384 element.updateOperationsByQName();
385 OperationDesc [] operations = element.getOperations();
386
387 if (operations == null) {
388 element.updateOperationsByName();
389 } else if (operations.length == 1) {
390 msgContext.setOperation(operations[0]);
391 }
392 } else {
393 msg.getSOAPPartAsString();
394 }
395 }
396
397 /***
398 * Can be overridden by subclasses to customize
399 * how the wsa:to header is interpreted
400 */
401 protected void setTargetService(MessageContext msgContext,
402 AddressingHeaders headers)
403 throws Exception {
404 To toURI = headers.getTo();
405 if (toURI == null) {
406 return;
407 }
408 String to = toURI.getPath();
409 if (to == null) {
410 return;
411 }
412
413 int i = to.lastIndexOf('/');
414 msgContext.setTargetService(to.substring(i + 1));
415 }
416
417 /***
418 * Method processServerResponse
419 *
420 * @param msgContext
421 */
422 protected void processServerResponse(MessageContext msgContext,
423 boolean setMustUnderstand)
424 throws Exception {
425
426 Message msg = msgContext.getResponseMessage();
427 if (msg == null) {
428 return;
429 }
430
431 AddressingHeaders reqHeaders =
432 (AddressingHeaders) msgContext.getProperty(
433 Constants.ENV_ADDRESSING_REQUEST_HEADERS
434 );
435
436 if (reqHeaders == null) {
437
438 return;
439 }
440
441 AddressingHeaders resHeaders =
442 AddressingUtils.getResponseHeaders(msgContext);
443
444 resHeaders.setSetMustUnderstand(setMustUnderstand);
445
446
447 EndpointReference fromEPR = resHeaders.getFrom();
448 if (fromEPR == null) {
449 To toURI = reqHeaders.getTo();
450 if (toURI != null) {
451 fromEPR = new EndpointReference(toURI);
452 fromEPR.setProperties(reqHeaders.getReferenceProperties());
453 resHeaders.setFrom(fromEPR);
454 }
455 }
456
457
458 Action action = resHeaders.getAction();
459 if (action == null) {
460
461 action = reqHeaders.getAction();
462 if (action != null) {
463 resHeaders.setAction(new Action(new URI(action.toString() +
464 "Response")));
465 }
466 }
467
468 if (resHeaders.getFrom() == null && reqHeaders.getFrom() != null) {
469 resHeaders.setTo(reqHeaders.getFrom().getAddress());
470 } else {
471 resHeaders.setTo(new To(Constants.NS_URI_ANONYMOUS));
472 }
473
474 MessageID msgID = null;
475
476
477 msgID = reqHeaders.getMessageID();
478 if (msgID != null) {
479 resHeaders.addRelatesTo(msgID.toString(),
480 Constants.QNAME_RESPONSE);
481 }
482
483
484 msgID = new MessageID(new URI("uuid:" + uuidGen.nextUUID()));
485 resHeaders.setMessageID(msgID);
486
487 resHeaders.toEnvelope(msg.getSOAPEnvelope(), this.actor);
488
489
490 EndpointReferenceType replyTo = reqHeaders.getReplyTo();
491 if (replyTo != null) {
492 AttributedURI address = replyTo.getAddress();
493 if (address != null) {
494 String uri = address.toString();
495 if (uri != null && !uri.equals(Constants.NS_URI_ANONYMOUS)) {
496
497 forwardMessage(replyTo, msg);
498
499
500 msgContext.setResponseMessage(null);
501 }
502 }
503 }
504 }
505
506 protected void forwardMessage(EndpointReferenceType epr,
507 Message msg)
508 throws Exception {
509 AttributedURI address = epr.getAddress();
510
511 AddressingHeaders headers = null;
512 MessageContext msgContext = msg.getMessageContext();
513 if (msgContext != null) {
514 headers = (AddressingHeaders) msgContext.getProperty(Constants.ENV_ADDRESSING_RESPONSE_HEADERS);
515 }
516 if (headers == null)
517 {
518 headers = new AddressingHeaders();
519 }
520
521 headers.setTo(address);
522 headers.setReferenceProperties(epr.getProperties());
523
524 Service service = getService(msgContext);
525
526 Call c = (Call) service.createCall();
527 c.setTargetEndpointAddress(address.toString());
528 c.setRequestMessage(msg);
529 c.setProperty(Constants.ENV_ADDRESSING_REQUEST_HEADERS, headers);
530 configureCall(c, msgContext);
531 c.invoke();
532 }
533
534 /***
535 * Override this method if you need something other than the default Service.<br>
536 * The service returned by this method is used in creating the new Call object.
537 * Something like: <br>
538 * <pre>
539 * Service service = getService(msgContext);
540 * Call call = service.createCall()
541 * call.setTargetEndpointAddress(toEndPointReference.getAddress().toString());
542 * </pre>
543 *
544 * @param msgContext
545 * @return
546 */
547 protected Service getService(MessageContext msgContext) {
548 return new Service();
549 }
550
551 /***
552 * Override this method to prepare the new call, for instance to add
553 * properties from the old MessageContext that may be needed by other
554 * handlers.
555 *
556 * @param call Call object about to be invoked
557 * @param oldContext MessageContext of the original request/response.
558 *
559 */
560 protected void configureCall(Call call, MessageContext oldContext) {
561 }
562
563 /***
564 * Retrieve QNames for reference properties from deployment
565 * and initialize the refPropQNames list which is the list
566 * of reference properties that this handler should care
567 * about.
568 */
569 private void initializeReferencePropertyNames() {
570
571
572
573
574 String refPropNames = (String) getOption("referencePropertyNames");
575 if (refPropNames == null) {
576 this.refPropQNames = new ArrayList();
577 } else if (refPropNames.equals("*")) {
578 this.refPropQNames = null;
579 } else {
580 this.refPropQNames = new ArrayList();
581 StringTokenizer tkn = new StringTokenizer(refPropNames, ",");
582 while (tkn.hasMoreTokens()) {
583 String qnameString = tkn.nextToken().trim();
584 try {
585 QName qname = QName.valueOf(qnameString);
586 refPropQNames.add(qname);
587 } catch (Exception e) {
588
589
590 }
591 }
592 }
593 }
594
595 }