1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.axis.message.addressing.handler;
17
18 import org.apache.axis.AxisFault;
19 import org.apache.axis.Message;
20 import org.apache.axis.MessageContext;
21 import org.apache.axis.AxisEngine;
22 import org.apache.axis.client.Call;
23 import org.apache.axis.client.Service;
24 import org.apache.axis.message.SOAPEnvelope;
25 import org.apache.axis.message.SOAPBodyElement;
26 import org.apache.axis.message.RPCElement;
27 import org.apache.axis.message.SOAPFault;
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.AddressingVersion;
34 import org.apache.axis.message.addressing.AttributedURI;
35 import org.apache.axis.message.addressing.AddressingHeaders;
36 import org.apache.axis.message.addressing.Constants;
37 import org.apache.axis.message.addressing.EndpointReference;
38 import org.apache.axis.message.addressing.EndpointReferenceType;
39 import org.apache.axis.message.addressing.MessageID;
40 import org.apache.axis.message.addressing.To;
41 import org.apache.axis.message.addressing.AddressingHeaderFault;
42 import org.apache.axis.message.addressing.util.AddressingUtils;
43 import org.apache.axis.types.URI;
44
45 import org.apache.commons.logging.Log;
46 import org.apache.commons.logging.LogFactory;
47
48 import javax.xml.namespace.QName;
49 import java.util.ArrayList;
50 import java.util.List;
51 import java.util.StringTokenizer;
52
53
54
55
56
57
58
59 public class AddressingHandler extends BasicHandler implements Constants {
60
61
62
63
64 private static final long serialVersionUID = 831310304473973743L;
65
66
67
68
69 protected static final Log LOG = LogFactory.getLog(AddressingHandler.class);
70
71
72
73
74 private static UUIDGen uuidGen = UUIDGenFactory.getUUIDGen();
75
76
77
78
79
80
81
82
83 private List<QName> refPropQNames;
84
85
86
87
88 private String actor;
89
90
91
92
93 private boolean removeHeaders = false;
94
95
96
97
98 private boolean allowNonSpecificActions = false;
99
100
101
102
103
104
105 private static final String OPT_CATCH_OWN_FAULTS = "handler.catchOwnFaults";
106
107
108
109
110 public AddressingHandler() {
111 }
112
113
114
115
116 @Override
117 public void init() {
118 super.init();
119 initializeReferencePropertyNames();
120 initializeRemoveHeaders();
121 initializeActor();
122 initializeAllowNonSpecificActions();
123
124
125 Boolean catchOwnFaults = (Boolean)getOption(OPT_CATCH_OWN_FAULTS);
126 if (catchOwnFaults == null) {
127 setOption(OPT_CATCH_OWN_FAULTS, Boolean.TRUE);
128 }
129 }
130
131
132
133
134 protected void initializeActor() {
135 actor = (String) getOption("actor");
136 }
137
138
139
140
141 private void initializeRemoveHeaders() {
142 String property = (String) getOption("removeHeaders");
143 this.removeHeaders = "true".equalsIgnoreCase(property);
144 }
145
146
147
148
149 private void initializeAllowNonSpecificActions() {
150 String property = (String) getOption("allowNonSpecificActions");
151 this.allowNonSpecificActions = "true".equalsIgnoreCase(property);
152 }
153
154
155
156
157 public void invoke(MessageContext msgContext) throws AxisFault {
158 boolean setMustUnderstand =
159 msgContext.isPropertyTrue(ENV_ADDRESSING_SET_MUST_UNDERSTAND);
160
161 try {
162 if (msgContext.isClient()) {
163 if (!msgContext.getPastPivot()) {
164 processClientRequest(msgContext, setMustUnderstand);
165 } else {
166 processClientResponse(msgContext);
167 }
168 } else {
169 if (!msgContext.getPastPivot()) {
170 processServerRequest(msgContext);
171 } else {
172 processServerResponse(msgContext, setMustUnderstand);
173 }
174 }
175 } catch (Exception e) {
176 LOG.error("Exception in AddressingHandler", e);
177 throw AxisFault.makeFault(e);
178 }
179 }
180
181
182
183
184 public void onFault(MessageContext msgContext) {
185 if (msgContext.isClient()) {
186 return;
187 }
188 try {
189 processFault(msgContext);
190 } catch (Exception e) {
191 LOG.error("Exception in AddressingHandler", e);
192 }
193 }
194
195
196
197
198
199
200
201 protected void processFault(MessageContext ctx) throws Exception {
202 Message msg = ctx.getResponseMessage();
203 if (msg == null) {
204 return;
205 }
206
207 AddressingVersion version = AddressingUtils.getAddressingVersion(ctx);
208
209 SOAPFault el = (SOAPFault)msg.getSOAPEnvelope().getFirstBody();
210 if (el.getFault().getFaultCode().equals(
211 ctx.getSOAPConstants().getMustunderstandFaultQName())) {
212 return;
213 }
214
215 AddressingHeaders reqHeaders =
216 (AddressingHeaders) ctx.getProperty(ENV_ADDRESSING_REQUEST_HEADERS);
217
218 if (reqHeaders == null) {
219
220 return;
221 }
222
223 AddressingHeaders resHeaders = AddressingUtils.getResponseHeaders(ctx);
224
225
226 EndpointReference fromEPR = resHeaders.getFrom();
227 if (fromEPR == null) {
228 To toURI = reqHeaders.getTo();
229 if (toURI != null) {
230 fromEPR = new EndpointReference(toURI);
231 fromEPR.setProperties(reqHeaders.getReferenceProperties());
232 resHeaders.setFrom(fromEPR);
233 }
234 }
235 URI actionURI = new URI(version.getFaultActionURI(), allowNonSpecificActions);
236 resHeaders.setAction(actionURI);
237
238
239 MessageID msgID = reqHeaders.getMessageID();
240 if (msgID != null) {
241 resHeaders.addRelatesTo(msgID.toString(), version.getResponseRelationshipType());
242 }
243
244
245 msgID = new MessageID(new URI("uuid:" + uuidGen.nextUUID()));
246 resHeaders.setMessageID(msgID);
247
248
249 EndpointReferenceType faultTo = reqHeaders.getFaultTo();
250 if (faultTo == null) {
251 faultTo = reqHeaders.getReplyTo();
252 }
253
254 if (faultTo != null) {
255 resHeaders.setReferenceProperties(faultTo.getProperties());
256 resHeaders.setReferenceParameters(faultTo.getParameters());
257
258
259
260
261 AttributedURI address = faultTo.getAddress();
262 if (address != null) {
263 String uri = address.toString();
264
265
266
267
268 if (uri != null
269 && !uri.equals(version.getAnonymousRoleURI())) {
270
271 if (!uri.equals(URI_NONE_W3C_CR)) {
272 forwardMessage(faultTo, msg);
273 }
274
275
276
277
278
279
280 ctx.setResponseMessage(null);
281 ctx.setProperty("axis.DontEmitFault", Boolean.TRUE);
282 return;
283 }
284 }
285 }
286
287
288
289 resHeaders.toEnvelope(msg.getSOAPEnvelope());
290 }
291
292
293
294
295
296
297
298 protected void processClientRequest(MessageContext ctx, boolean setMustUnderstand)
299 throws Exception {
300
301 boolean sendDefaultFrom = ctx.isPropertyTrue(SEND_DEFAULT_FROM, true);
302 boolean sendDefaultMessageID = ctx.isPropertyTrue(SEND_DEFAULT_MESSAGEID, true);
303 boolean sendDefaultTo = ctx.isPropertyTrue(SEND_DEFAULT_TO, true);
304
305 AddressingHeaders sharedHeaders = (AddressingHeaders) ctx
306 .getProperty(ENV_ADDRESSING_SHARED_HEADERS);
307
308 AddressingHeaders headers = AddressingUtils.getRequestHeaders(ctx);
309
310 headers.setSetMustUnderstand(setMustUnderstand);
311
312
313 if (headers.getMessageID() == null && sendDefaultMessageID) {
314 MessageID id = new MessageID(new URI("uuid:" + uuidGen.nextUUID()));
315 headers.setMessageID(id);
316 }
317
318
319 To to = headers.getTo();
320 if (to == null && sendDefaultTo) {
321 if (sharedHeaders != null) {
322
323 headers.setTo(sharedHeaders.getTo());
324 } else {
325 headers.setTo(new To(ctx.getStrProp(MessageContext.TRANS_URL)));
326 }
327 }
328
329
330 String action = ctx.getSOAPActionURI();
331 if (action != null) {
332 URI actionURI = new URI(action, allowNonSpecificActions);
333 headers.setAction(new Action(actionURI));
334 } else {
335 Action act = headers.getAction();
336 if (act == null) {
337 URI actionURI = new URI("http://apache.org/axis/defaultAction");
338 headers.setAction(new Action(actionURI));
339 }
340
341 ctx.setUseSOAPAction(true);
342
343 ctx.setSOAPActionURI(headers.getAction().toString());
344 }
345
346
347 if (headers.getFrom() == null && sendDefaultFrom) {
348 String from = ctx.getStrProp(ENV_ADDRESSING_FROM_URI);
349 if (from == null) {
350 from = AddressingUtils.getAddressingVersion().getAnonymousRoleURI();
351 }
352 headers.setFrom(new EndpointReference(from));
353 }
354
355
356 if (ctx.isPropertyTrue(ENV_ADDRESSING_SEND_REPLYTO) && headers.getReplyTo() == null) {
357 String replyTo = ctx.getStrProp(ENV_ADDRESSING_REPLYTO_URI);
358 if (replyTo != null) {
359 headers.setReplyTo(new EndpointReference(replyTo));
360 } else {
361 headers.setReplyTo(headers.getFrom());
362 }
363 }
364
365
366 if (headers.getFaultTo() == null) {
367 String faultTo = ctx.getStrProp(ENV_ADDRESSING_FAULTTO_URI);
368 if (faultTo != null) {
369 headers.setFaultTo(new EndpointReference(faultTo));
370 }
371 }
372
373 if (sharedHeaders != null) {
374 headers.setReferenceProperties(sharedHeaders.getReferenceProperties());
375 }
376 Message msg = ctx.getRequestMessage();
377 headers.toEnvelope(msg.getSOAPEnvelope(), this.actor);
378 }
379
380
381
382
383
384
385
386 protected void processClientResponse(MessageContext ctx) throws Exception {
387
388 Message msg = ctx.getResponseMessage();
389 if (msg == null) {
390 return;
391 }
392
393 AddressingHeaders headers = new AddressingHeaders(
394 msg.getSOAPEnvelope(), this.actor,
395 true, this.removeHeaders, false, this.allowNonSpecificActions,
396 this.refPropQNames);
397 ctx.setProperty(ENV_ADDRESSING_RESPONSE_HEADERS, headers);
398 }
399
400
401
402
403
404
405
406 protected void processServerRequest(MessageContext ctx) throws Exception {
407
408 boolean isAddrRequired = ctx.isPropertyTrue(ENV_ADDRESSING_REQUIRED, true);
409
410 Message msg = ctx.getRequestMessage();
411 if (msg == null) {
412 return;
413 }
414 AddressingHeaders headers = new AddressingHeaders(
415 msg.getSOAPEnvelope(), this.actor,
416 true, this.removeHeaders, false, this.allowNonSpecificActions,
417 this.refPropQNames);
418
419 AxisFault fault = headers.getAddrHeaderFault();
420
421 if (isAddrRequired && headers.getAction() == null) {
422 if (ctx.getProperty(ENV_ADDRESSING_NAMESPACE_URI) == null) {
423 ctx.setProperty(ENV_ADDRESSING_NAMESPACE_URI, NS_URI_ADDRESSING_2005_08);
424 }
425 fault = new AddressingHeaderFault("No Action header",
426 AddressingHeaderFault.HEADER_REQUIRED, "Action");
427 LOG.debug("WS-A request to endpoint " + headers.getTo()
428 + " is missing the required wsa:Action header.");
429 }
430
431 ctx.setProperty(ENV_ADDRESSING_REQUEST_HEADERS, headers);
432
433 if (fault != null) {
434 throw fault;
435 }
436
437
438
439
440 if (ctx.getService() == null && ctx.getTargetService() == null) {
441 setTargetService(ctx, headers);
442
443 if (ctx.getService() != null) {
444 resetOperations(ctx);
445 }
446 }
447 }
448
449
450
451
452
453
454
455 protected void resetOperations(MessageContext ctx) throws AxisFault {
456 resetContextOperations(ctx);
457 }
458
459
460
461
462
463
464
465
466 public static void resetContextOperations(MessageContext ctx) throws AxisFault {
467 Message msg = ctx.getCurrentMessage();
468 if (msg == null) {
469 return;
470 }
471 SOAPEnvelope env = msg.getSOAPEnvelope();
472 if (env == null) {
473 return;
474 }
475 SOAPBodyElement bodyElement = env.getFirstBody();
476 if (bodyElement != null && bodyElement instanceof RPCElement) {
477 RPCElement element = (RPCElement) bodyElement;
478
479 element.updateOperationsByQName();
480 OperationDesc[] operations = element.getOperations();
481
482 if (operations == null) {
483 element.updateOperationsByName();
484 } else if (operations.length == 1) {
485 ctx.setOperation(operations[0]);
486 }
487 } else {
488 msg.getSOAPPartAsString();
489 }
490 }
491
492
493
494
495
496
497
498
499 protected void setTargetService(MessageContext ctx, AddressingHeaders headers)
500 throws Exception {
501 To toURI = headers.getTo();
502 if (toURI == null) {
503 return;
504 }
505 String to = toURI.getPath();
506 if (to == null) {
507 return;
508 }
509
510 int i = to.lastIndexOf('/');
511 ctx.setTargetService(to.substring(i + 1));
512 }
513
514
515
516
517
518
519
520
521 protected void processServerResponse(MessageContext ctx,
522 boolean setMustUnderstand) throws Exception {
523
524 Message msg = ctx.getResponseMessage();
525 if (msg == null) {
526 return;
527 }
528
529 AddressingVersion version = AddressingUtils.getAddressingVersion();
530
531 AddressingHeaders reqHeaders = (AddressingHeaders) ctx
532 .getProperty(ENV_ADDRESSING_REQUEST_HEADERS);
533
534 if (reqHeaders == null) {
535
536 return;
537 }
538
539 AddressingHeaders resHeaders = AddressingUtils.getResponseHeaders(ctx);
540
541 resHeaders.setSetMustUnderstand(setMustUnderstand);
542
543
544 EndpointReference fromEPR = resHeaders.getFrom();
545 if (fromEPR == null) {
546 To toURI = reqHeaders.getTo();
547 if (toURI != null) {
548 fromEPR = new EndpointReference(toURI);
549 fromEPR.setProperties(reqHeaders.getReferenceProperties());
550 resHeaders.setFrom(fromEPR);
551 }
552 }
553
554
555 Action action = resHeaders.getAction();
556 if (action == null) {
557 String respAction = ctx.getStrProp(ENV_ADDRESSING_RESP_ACTION);
558 if (respAction == null) {
559
560 action = reqHeaders.getAction();
561 if (action != null) {
562 URI actionURI = new URI(action.toString() + "Response",
563 allowNonSpecificActions);
564 resHeaders.setAction(new Action(actionURI));
565 }
566 } else {
567 resHeaders.setAction(new Action(new URI(respAction)));
568 }
569 }
570
571 if (resHeaders.getFrom() == null && reqHeaders.getFrom() != null) {
572 resHeaders.setTo(reqHeaders.getFrom().getAddress());
573 } else {
574 resHeaders.setTo(new To(version.getAnonymousRoleURI()));
575 }
576
577
578 MessageID msgID = reqHeaders.getMessageID();
579 if (msgID != null) {
580 resHeaders.addRelatesTo(msgID.toString(), version.getResponseRelationshipType());
581 }
582
583
584 msgID = new MessageID(new URI("uuid:" + uuidGen.nextUUID()));
585 resHeaders.setMessageID(msgID);
586
587
588 EndpointReferenceType replyTo = reqHeaders.getReplyTo();
589 if (replyTo != null) {
590 resHeaders.setReferenceProperties(replyTo.getProperties());
591 resHeaders.setReferenceParameters(replyTo.getParameters());
592
593 AttributedURI address = replyTo.getAddress();
594 if (address != null) {
595 String uri = address.toString();
596 if (uri != null && !uri.equals(version.getAnonymousRoleURI())) {
597 if (!uri.equals(URI_NONE_W3C_CR)) {
598
599 forwardMessage(replyTo, msg);
600 }
601
602 ctx.setResponseMessage(null);
603 } else {
604 resHeaders.toEnvelope(msg.getSOAPEnvelope(), this.actor);
605 }
606 }
607 } else {
608 resHeaders.toEnvelope(msg.getSOAPEnvelope(), this.actor);
609 }
610 }
611
612
613
614
615
616
617
618
619 protected void forwardMessage(EndpointReferenceType epr, Message msg)
620 throws Exception {
621 AttributedURI address = epr.getAddress();
622
623 AddressingHeaders headers = null;
624 MessageContext ctx = msg.getMessageContext();
625 if (ctx != null) {
626 headers = (AddressingHeaders) ctx
627 .getProperty(ENV_ADDRESSING_RESPONSE_HEADERS);
628 }
629 if (headers == null) {
630 headers = new AddressingHeaders();
631 headers.setTo(address);
632 headers.setReferenceProperties(epr.getProperties());
633 headers.setReferenceParameters(epr.getParameters());
634 }
635
636 Service service = getService(ctx);
637
638 Call c = (Call) service.createCall();
639 c.setSOAPVersion((ctx == null)
640 ? org.apache.axis.Constants.DEFAULT_SOAP_VERSION
641 : ctx.getSOAPConstants());
642 c.setTargetEndpointAddress(address.toString());
643 c.setRequestMessage(msg);
644 c.setProperty(ENV_ADDRESSING_REQUEST_HEADERS, headers);
645 c.setProperty(ENV_ADDRESSING_NAMESPACE_URI, AddressingUtils
646 .getAddressingNamespaceURI(ctx));
647 if (ctx != null) {
648 c.setProperty(AxisEngine.PROP_SEND_XSI, ctx
649 .getProperty(AxisEngine.PROP_SEND_XSI));
650 c.setOperationStyle(ctx.getOperationStyle());
651 c.setOperationUse(ctx.getOperationUse());
652 }
653 configureCall(c, ctx);
654 try {
655 c.invoke();
656 } catch (AxisFault axisFault) {
657
658
659
660 LOG.error(axisFault.dumpToString());
661 }
662 }
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677 protected Service getService(MessageContext ctx) {
678 return new Service();
679 }
680
681
682
683
684
685
686
687
688
689 protected void configureCall(Call call, MessageContext oldContext) {
690 }
691
692
693
694
695
696
697
698 private void initializeReferencePropertyNames() {
699
700
701
702
703 String refPropNames = (String) getOption("referencePropertyNames");
704 if (refPropNames == null) {
705 this.refPropQNames = new ArrayList<QName>();
706 } else if (refPropNames.equals("*")) {
707 this.refPropQNames = null;
708 } else {
709 this.refPropQNames = new ArrayList<QName>();
710 StringTokenizer tkn = new StringTokenizer(refPropNames, ",");
711 while (tkn.hasMoreTokens()) {
712 String qnameString = tkn.nextToken().trim();
713 try {
714 QName qname = QName.valueOf(qnameString);
715 refPropQNames.add(qname);
716 } catch (Exception e) {
717
718
719 LOG.debug("Invalid QName ignored: " + qnameString);
720 }
721 }
722 }
723 }
724
725 }