KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > celtix > bus > ws > addressing > MAPAggregator


1 package org.objectweb.celtix.bus.ws.addressing;
2
3
4 import java.io.IOException JavaDoc;
5 import java.text.MessageFormat JavaDoc;
6 import java.util.HashMap JavaDoc;
7 import java.util.Iterator JavaDoc;
8 import java.util.Map JavaDoc;
9 import java.util.ResourceBundle JavaDoc;
10 import java.util.concurrent.atomic.AtomicBoolean JavaDoc;
11 import java.util.logging.Level JavaDoc;
12 import java.util.logging.Logger JavaDoc;
13
14 import javax.annotation.PostConstruct;
15 import javax.annotation.Resource;
16 import javax.wsdl.Port;
17 import javax.wsdl.extensions.ExtensibilityElement;
18 import javax.xml.ws.handler.LogicalHandler;
19 import javax.xml.ws.handler.LogicalMessageContext;
20 import javax.xml.ws.handler.MessageContext;
21
22
23 import org.objectweb.celtix.bindings.AbstractBindingBase;
24 import org.objectweb.celtix.bindings.ClientBinding;
25 import org.objectweb.celtix.bindings.JAXWSConstants;
26 import org.objectweb.celtix.bindings.ServerBinding;
27 import org.objectweb.celtix.bus.jaxws.EndpointImpl;
28 import org.objectweb.celtix.bus.jaxws.ServiceImpl;
29 import org.objectweb.celtix.common.logging.LogUtils;
30 import org.objectweb.celtix.configuration.Configuration;
31 import org.objectweb.celtix.configuration.ConfigurationBuilder;
32 import org.objectweb.celtix.configuration.ConfigurationBuilderFactory;
33 import org.objectweb.celtix.transports.ClientTransport;
34 import org.objectweb.celtix.transports.ServerTransport;
35 import org.objectweb.celtix.ws.addressing.AddressingProperties;
36 import org.objectweb.celtix.ws.addressing.AttributedURIType;
37 import org.objectweb.celtix.ws.addressing.EndpointReferenceType;
38 import org.objectweb.celtix.wsdl.EndpointReferenceUtils;
39
40
41 /**
42  * Logical Handler responsible for aggregating the Message Addressing
43  * Properties for outgoing messages.
44  */

45 public class MAPAggregator implements LogicalHandler<LogicalMessageContext> {
46
47     public static final String JavaDoc WSA_CONFIGURATION_URI =
48         "http://celtix.objectweb.org/bus/ws/addressing/wsa-config";
49     public static final String JavaDoc WSA_CONFIGURATION_ID = "wsa-handler";
50     
51     private static final Logger JavaDoc LOG =
52         LogUtils.getL7dLogger(MAPAggregator.class);
53     private static final ResourceBundle JavaDoc BUNDLE = LOG.getResourceBundle();
54     
55
56     protected final Map JavaDoc<String JavaDoc, String JavaDoc> messageIDs =
57         new HashMap JavaDoc<String JavaDoc, String JavaDoc>();
58     
59     /**
60      * resources injected by client/server endpoints
61      */

62     @Resource(name = JAXWSConstants.SERVER_BINDING_PROPERTY) protected ServerBinding serverBinding;
63     @Resource(name = JAXWSConstants.CLIENT_BINDING_PROPERTY) protected ClientBinding clientBinding;
64     @Resource(name = JAXWSConstants.CLIENT_TRANSPORT_PROPERTY) protected ClientTransport clientTransport;
65     @Resource(name = JAXWSConstants.SERVER_TRANSPORT_PROPERTY) protected ServerTransport serverTransport;
66
67     /**
68      * Whether the endpoint supports WS-Addressing.
69      */

70     private final AtomicBoolean JavaDoc usingAddressingDetermined = new AtomicBoolean JavaDoc(false);
71     private final AtomicBoolean JavaDoc usingAddressing = new AtomicBoolean JavaDoc(false);
72     
73     private Configuration configuration;
74
75     /**
76      * Constructor.
77      */

78     public MAPAggregator() {
79     }
80     
81     @PostConstruct
82     protected synchronized void initConfiguration() {
83         AbstractBindingBase binding = (AbstractBindingBase)
84             (clientBinding == null ? serverBinding : clientBinding);
85         Configuration busCfg = binding.getBus().getConfiguration();
86         ConfigurationBuilder builder = ConfigurationBuilderFactory.getBuilder();
87         Configuration parent;
88         org.objectweb.celtix.ws.addressing.EndpointReferenceType ref =
89             binding.getEndpointReference();
90
91         if (null != clientBinding) {
92             String JavaDoc id = EndpointReferenceUtils.getServiceName(ref).toString()
93                 + "/" + EndpointReferenceUtils.getPortName(ref);
94             parent = builder.getConfiguration(ServiceImpl.PORT_CONFIGURATION_URI,
95                                                                 id, busCfg);
96         } else {
97             parent = builder.getConfiguration(EndpointImpl.ENDPOINT_CONFIGURATION_URI, EndpointReferenceUtils
98                 .getServiceName(ref).toString(), busCfg);
99         }
100
101         configuration = builder.getConfiguration(WSA_CONFIGURATION_URI, WSA_CONFIGURATION_ID, parent);
102         if (null == configuration) {
103             configuration = builder.buildConfiguration(WSA_CONFIGURATION_URI, WSA_CONFIGURATION_ID, parent);
104             
105         }
106     }
107
108
109     /**
110      * Initialize the handler.
111      */

112     public void init(Map JavaDoc<String JavaDoc, Object JavaDoc> map) {
113     }
114     
115     /**
116      * Invoked for normal processing of inbound and outbound messages.
117      *
118      * @param context the messsage context
119      */

120     public boolean handleMessage(LogicalMessageContext context) {
121         return mediate(context);
122     }
123
124     /**
125      * Invoked for fault processing.
126      *
127      * @param context the messsage context
128      */

129     public boolean handleFault(LogicalMessageContext context) {
130         return mediate(context);
131     }
132
133     /**
134      * Called at the conclusion of a message exchange pattern just prior to
135      * the JAX-WS runtime dispatching a message, fault or exception.
136      *
137      * @param context the message context
138      */

139     public void close(MessageContext context) {
140     }
141
142     /**
143      * Release handler resources.
144      */

145     public void destroy() {
146     }
147
148     /**
149      * Determine if addressing is being used
150      *
151      * @param context the messsage context
152      * @pre message is outbound
153      */

154     private boolean usingAddressing(LogicalMessageContext context) {
155         boolean ret = false;
156         if (ContextUtils.isRequestor(context)) {
157             if (!usingAddressingDetermined.get()) {
158                 Port port = clientTransport == null ? null : clientTransport.getPort();
159                 if (port != null) {
160                     Iterator JavaDoc<?> portExts =
161                         port.getExtensibilityElements().iterator();
162                     Iterator JavaDoc<?> bindingExts =
163                         port.getBinding().getExtensibilityElements().iterator();
164                     ret = hasUsingAddressing(portExts)
165                         || hasUsingAddressing(bindingExts);
166                 } else {
167                     ret = ContextUtils.retrieveUsingAddressing(context);
168                 }
169                 setUsingAddressing(ret);
170             } else {
171                 ret = usingAddressing.get();
172             }
173         } else {
174             ret = getMAPs(context, false, false) != null;
175         }
176         return ret;
177     }
178
179     /**
180      * @param extensionElements iterator over extension elements
181      * @return true iff the UsingAddressing element is found
182      */

183     private boolean hasUsingAddressing(Iterator JavaDoc<?> extensionElements) {
184         boolean found = false;
185         while (extensionElements.hasNext() && !found) {
186             ExtensibilityElement ext =
187                 (ExtensibilityElement)extensionElements.next();
188             found = Names.WSAW_USING_ADDRESSING_QNAME.equals(ext.getElementType());
189
190         }
191         return found;
192     }
193
194     /**
195      * Mediate message flow.
196      *
197      * @param context the messsage context
198      * @return true if processing should continue on dispatch path
199      */

200     private boolean mediate(LogicalMessageContext context) {
201         boolean continueProcessing = true;
202         if (ContextUtils.isOutbound(context)) {
203             if (usingAddressing(context)) {
204                 // request/response MAPs must be aggregated
205
aggregate(context);
206             }
207         } else if (!ContextUtils.isRequestor(context)) {
208             // responder validates incoming MAPs
209
AddressingPropertiesImpl maps = getMAPs(context, false, false);
210             setUsingAddressing(true);
211             continueProcessing = validateIncomingMAPs(maps, context);
212             if (continueProcessing) {
213                 if (ContextUtils.isOneway(context)
214                     || !ContextUtils.isGenericAddress(maps.getReplyTo())) {
215                     ContextUtils.rebaseTransport(maps, context, serverBinding, serverTransport);
216                 }
217             } else {
218                 // validation failure => dispatch is aborted, response MAPs
219
// must be aggregated
220
aggregate(context);
221             }
222         }
223         return continueProcessing;
224     }
225
226     /**
227      * Perform MAP aggregation.
228      *
229      * @param context the messsage context
230      */

231     private void aggregate(LogicalMessageContext context) {
232         AddressingPropertiesImpl maps = assembleGeneric(context);
233         boolean isRequestor = ContextUtils.isRequestor(context);
234         addRoleSpecific(maps, isRequestor, context);
235         // outbound property always used to store MAPs, as this handler
236
// aggregates only when either:
237
// a) message really is outbound
238
// b) message is currently inbound, but we are about to abort dispatch
239
// due to an incoming MAPs validation failure, so the dispatch
240
// will shortly traverse the outbound path
241
ContextUtils.storeMAPs(maps, context, true, isRequestor, true);
242     }
243
244     /**
245      * Assemble the generic MAPs (for both requests and responses).
246      *
247      * @param context the messsage context
248      * @return AddressingProperties containing the generic MAPs
249      */

250     private AddressingPropertiesImpl assembleGeneric(MessageContext context) {
251         AddressingPropertiesImpl maps = getMAPs(context, true, true);
252         // MessageID
253
if (maps.getMessageID() == null) {
254             String JavaDoc messageID = ContextUtils.generateUUID();
255             maps.setMessageID(ContextUtils.getAttributedURI(messageID));
256         }
257         // To
258
if (maps.getTo() == null) {
259             // To cached in context by transport
260
EndpointReferenceType reference =
261                 clientTransport == null ? null : clientTransport.getTargetEndpoint();
262             maps.setTo(reference != null
263                        ? reference.getAddress()
264                        : ContextUtils.getAttributedURI(Names.WSA_NONE_ADDRESS));
265         }
266         // Action
267
if (ContextUtils.hasEmptyAction(maps)) {
268             maps.setAction(ContextUtils.getAction(context));
269         }
270         return maps;
271     }
272
273     /**
274      * Add MAPs which are specific to the requestor or responder role.
275      *
276      * @param maps the MAPs being assembled
277      * @param isRequestor true iff the current messaging role is that of
278      * requestor
279      * @param context the messsage context
280      */

281     private void addRoleSpecific(AddressingPropertiesImpl maps,
282                                  boolean isRequestor,
283                                  MessageContext context) {
284         if (isRequestor) {
285             // add request-specific MAPs
286
boolean isOneway = ContextUtils.isOneway(context);
287             // ReplyTo, set if null in MAPs or if set to a generic address
288
// (anonymous or none) that may not be appropriate for the
289
// current invocation
290
EndpointReferenceType replyTo = maps.getReplyTo();
291             if (ContextUtils.isGenericAddress(replyTo)) {
292                 
293                 try {
294                     replyTo = clientTransport == null ? null : clientTransport.getDecoupledEndpoint();
295                 } catch (IOException JavaDoc ex) {
296                     // ignore
297
replyTo = null;
298                 }
299                 
300                 if (replyTo == null || isOneway) {
301                     AttributedURIType address =
302                         ContextUtils.getAttributedURI(isOneway
303                                                       ? Names.WSA_NONE_ADDRESS
304                                                       : Names.WSA_ANONYMOUS_ADDRESS);
305                     replyTo =
306                         ContextUtils.WSA_OBJECT_FACTORY.createEndpointReferenceType();
307                     replyTo.setAddress(address);
308                 }
309                 maps.setReplyTo(replyTo);
310             }
311             if (!isOneway) {
312                 // REVISIT FaultTo if cached by transport in context
313
}
314             // cache correlation ID
315
if (ContextUtils.isOutbound(context)) {
316                 ContextUtils.storeCorrelationID(maps.getMessageID(), true, context);
317             }
318         } else {
319             // add response-specific MAPs
320
AddressingPropertiesImpl inMAPs = getMAPs(context, false, false);
321             maps.exposeAs(inMAPs.getNamespaceURI());
322             // To taken from ReplyTo in incoming MAPs
323
if (inMAPs.getReplyTo() != null) {
324                 maps.setTo(inMAPs.getReplyTo().getAddress());
325             }
326             // RelatesTo taken from MessageID in incoming MAPs
327
if (inMAPs.getMessageID() != null) {
328                 String JavaDoc inMessageID = inMAPs.getMessageID().getValue();
329                 maps.setRelatesTo(ContextUtils.getRelatesTo(inMessageID));
330             }
331         }
332     }
333
334     /**
335      * Get the starting point MAPs (either empty or those set explicitly
336      * by the application on the binding provider request context).
337      *
338      * @param context the messsage context
339      * @param isProviderContext true if the binding provider request context
340      * available to the client application as opposed to the message context
341      * visible to handlers
342      * @param isOutbound true iff the message is outbound
343      * @return AddressingProperties retrieved MAPs
344      */

345     private AddressingPropertiesImpl getMAPs(MessageContext context,
346                                              boolean isProviderContext,
347                                              boolean isOutbound) {
348
349         AddressingPropertiesImpl maps = null;
350         maps = ContextUtils.retrieveMAPs(context,
351                                          isProviderContext,
352                                          isOutbound);
353         LOG.log(Level.INFO, "MAPs retrieved from context {0}", maps);
354
355         if (maps == null && isProviderContext) {
356             maps = new AddressingPropertiesImpl();
357         }
358         return maps;
359     }
360
361     /**
362      * Validate incoming MAPs
363      * @param maps the incoming MAPs
364      * @param context the messsage context
365      * @return true if incoming MAPs are valid
366      * @pre inbound message, not requestor
367      */

368     private boolean validateIncomingMAPs(AddressingProperties maps, MessageContext context) {
369         if (null != configuration && configuration.getBoolean("allowDuplicates")) {
370             return true;
371         }
372         boolean valid = true;
373         if (maps != null) {
374             AttributedURIType messageID = maps.getMessageID();
375             if (messageID != null
376                 && messageIDs.put(messageID.getValue(),
377                                   messageID.getValue()) != null) {
378                 LOG.log(Level.WARNING,
379                         "DUPLICATE_MESSAGE_ID_MSG",
380                         messageID.getValue());
381                 String JavaDoc reason =
382                     BUNDLE.getString("DUPLICATE_MESSAGE_ID_MSG");
383                 String JavaDoc l7dReason =
384                     MessageFormat.format(reason, messageID.getValue());
385                 ContextUtils.storeMAPFaultName(Names.DUPLICATE_MESSAGE_ID_NAME,
386                                                context);
387                 ContextUtils.storeMAPFaultReason(l7dReason, context);
388                 valid = false;
389             }
390         }
391         return valid;
392     }
393     
394     /**
395      * Set using addressing flag.
396      *
397      * @param using true if addressing in use.
398      */

399     private void setUsingAddressing(boolean using) {
400         usingAddressing.set(using);
401         usingAddressingDetermined.set(true);
402     }
403 }
404
405
Popular Tags