Wed, 12 Jun 2013 14:47:09 +0100
8013021: Rebase 8005432 & 8003542 against the latest jdk8/jaxws
8003542: Improve processing of MTOM attachments
8005432: Update access to JAX-WS
Reviewed-by: mullan
1 /*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.xml.internal.ws.api.message;
28 import java.util.Iterator;
30 import javax.xml.namespace.QName;
31 import javax.xml.stream.XMLStreamException;
32 import javax.xml.ws.WebServiceException;
33 import javax.xml.ws.soap.SOAPBinding;
35 import com.sun.istack.internal.NotNull;
36 import com.sun.xml.internal.ws.addressing.WsaTubeHelper;
37 import com.sun.xml.internal.ws.api.SOAPVersion;
38 import com.sun.xml.internal.ws.api.WSBinding;
39 import com.sun.xml.internal.ws.api.addressing.AddressingPropertySet;
40 import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
41 import com.sun.xml.internal.ws.api.addressing.OneWayFeature;
42 import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
43 import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation;
44 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
45 import com.sun.xml.internal.ws.message.RelatesToHeader;
46 import com.sun.xml.internal.ws.message.StringHeader;
47 import com.sun.xml.internal.ws.resources.AddressingMessages;
48 import com.sun.xml.internal.ws.resources.ClientMessages;
50 public class AddressingUtils {
51 //TODO is MessageHeaders to be implicitly assumed? Or moved to utility class and taken out from interface?
52 public static void fillRequestAddressingHeaders(MessageHeaders headers, Packet packet, AddressingVersion av, SOAPVersion sv, boolean oneway, String action) {
53 fillRequestAddressingHeaders(headers, packet, av, sv, oneway, action, false);
54 }
55 public static void fillRequestAddressingHeaders(MessageHeaders headers, Packet packet, AddressingVersion av, SOAPVersion sv, boolean oneway, String action, boolean mustUnderstand) {
56 fillCommonAddressingHeaders(headers, packet, av, sv, action, mustUnderstand);
58 // wsa:ReplyTo
59 // null or "true" is equivalent to request/response MEP
60 if (!oneway) {
61 WSEndpointReference epr = av.anonymousEpr;
62 if (headers.get(av.replyToTag, false) == null) {
63 headers.add(epr.createHeader(av.replyToTag));
64 }
66 // wsa:FaultTo
67 if (headers.get(av.faultToTag, false) == null) {
68 headers.add(epr.createHeader(av.faultToTag));
69 }
71 // wsa:MessageID
72 if (packet.getMessage().getHeaders().get(av.messageIDTag, false) == null) {
73 if (headers.get(av.messageIDTag, false) == null) {
74 Header h = new StringHeader(av.messageIDTag, Message.generateMessageID());
75 headers.add(h);
76 }
77 }
78 }
79 }
80 // private void fillRequestAddressingHeaders(Packet packet, AddressingVersion av, SOAPVersion sv, OneWayFeature oneWayFeature, boolean oneway, String action);
81 public static void fillRequestAddressingHeaders(MessageHeaders headers, WSDLPort wsdlPort, WSBinding binding, Packet packet) {
82 if (binding == null) {
83 throw new IllegalArgumentException(AddressingMessages.NULL_BINDING());
84 }
86 if (binding.isFeatureEnabled(SuppressAutomaticWSARequestHeadersFeature.class)) {
87 return;
88 }
90 //See if WSA headers are already set by the user.
91 MessageHeaders hl = packet.getMessage().getHeaders();
92 String action = AddressingUtils.getAction(hl, binding.getAddressingVersion(), binding.getSOAPVersion());
93 if (action != null) {
94 //assume that all the WSA headers are set by the user
95 return;
96 }
97 AddressingVersion addressingVersion = binding.getAddressingVersion();
98 //seiModel is passed as null as it is not needed.
99 WsaTubeHelper wsaHelper = addressingVersion.getWsaHelper(wsdlPort, null, binding);
101 // wsa:Action
102 String effectiveInputAction = wsaHelper.getEffectiveInputAction(packet);
103 if (effectiveInputAction == null || effectiveInputAction.equals("") && binding.getSOAPVersion() == SOAPVersion.SOAP_11) {
104 throw new WebServiceException(ClientMessages.INVALID_SOAP_ACTION());
105 }
106 boolean oneway = !packet.expectReply;
107 if (wsdlPort != null) {
108 // if WSDL has <wsaw:Anonymous>prohibited</wsaw:Anonymous>, then throw an error
109 // as anonymous ReplyTo MUST NOT be added in that case. BindingProvider need to
110 // disable AddressingFeature and MemberSubmissionAddressingFeature and hand-craft
111 // the SOAP message with non-anonymous ReplyTo/FaultTo.
112 if (!oneway && packet.getMessage() != null && packet.getWSDLOperation() != null) {
113 WSDLBoundOperation wbo = wsdlPort.getBinding().get(packet.getWSDLOperation());
114 if (wbo != null && wbo.getAnonymous() == WSDLBoundOperation.ANONYMOUS.prohibited) {
115 throw new WebServiceException(AddressingMessages.WSAW_ANONYMOUS_PROHIBITED());
116 }
117 }
118 }
120 OneWayFeature oneWayFeature = binding.getFeature(OneWayFeature.class);
121 final AddressingPropertySet addressingPropertySet = packet.getSatellite(AddressingPropertySet.class);
122 oneWayFeature = addressingPropertySet == null ? oneWayFeature : new OneWayFeature(addressingPropertySet, addressingVersion);
124 if (oneWayFeature == null || !oneWayFeature.isEnabled()) {
125 // standard oneway
126 fillRequestAddressingHeaders(headers, packet, addressingVersion, binding.getSOAPVersion(), oneway, effectiveInputAction, AddressingVersion.isRequired(binding));
127 } else {
128 // custom oneway
129 fillRequestAddressingHeaders(headers, packet, addressingVersion, binding.getSOAPVersion(), oneWayFeature, oneway, effectiveInputAction);
130 }
131 }
133 public static String getAction(@NotNull MessageHeaders headers, @NotNull AddressingVersion av, @NotNull SOAPVersion sv) {
134 if (av == null) {
135 throw new IllegalArgumentException(AddressingMessages.NULL_ADDRESSING_VERSION());
136 }
138 String action = null;
139 Header h = getFirstHeader(headers, av.actionTag, true, sv);
140 if (h != null) {
141 action = h.getStringContent();
142 }
144 return action;
145 }
147 public static WSEndpointReference getFaultTo(@NotNull MessageHeaders headers, @NotNull AddressingVersion av, @NotNull SOAPVersion sv) {
148 if (av == null) {
149 throw new IllegalArgumentException(AddressingMessages.NULL_ADDRESSING_VERSION());
150 }
152 Header h = getFirstHeader(headers, av.faultToTag, true, sv);
153 WSEndpointReference faultTo = null;
154 if (h != null) {
155 try {
156 faultTo = h.readAsEPR(av);
157 } catch (XMLStreamException e) {
158 throw new WebServiceException(AddressingMessages.FAULT_TO_CANNOT_PARSE(), e);
159 }
160 }
162 return faultTo;
163 }
165 public static String getMessageID(@NotNull MessageHeaders headers, @NotNull AddressingVersion av, @NotNull SOAPVersion sv) {
166 if (av == null) {
167 throw new IllegalArgumentException(AddressingMessages.NULL_ADDRESSING_VERSION());
168 }
170 Header h = getFirstHeader(headers, av.messageIDTag, true, sv);
171 String messageId = null;
172 if (h != null) {
173 messageId = h.getStringContent();
174 }
176 return messageId;
177 }
178 public static String getRelatesTo(@NotNull MessageHeaders headers, @NotNull AddressingVersion av, @NotNull SOAPVersion sv) {
179 if (av == null) {
180 throw new IllegalArgumentException(AddressingMessages.NULL_ADDRESSING_VERSION());
181 }
183 Header h = getFirstHeader(headers, av.relatesToTag, true, sv);
184 String relatesTo = null;
185 if (h != null) {
186 relatesTo = h.getStringContent();
187 }
189 return relatesTo;
190 }
191 public static WSEndpointReference getReplyTo(@NotNull MessageHeaders headers, @NotNull AddressingVersion av, @NotNull SOAPVersion sv) {
192 if (av == null) {
193 throw new IllegalArgumentException(AddressingMessages.NULL_ADDRESSING_VERSION());
194 }
196 Header h = getFirstHeader(headers, av.replyToTag, true, sv);
197 WSEndpointReference replyTo;
198 if (h != null) {
199 try {
200 replyTo = h.readAsEPR(av);
201 } catch (XMLStreamException e) {
202 throw new WebServiceException(AddressingMessages.REPLY_TO_CANNOT_PARSE(), e);
203 }
204 } else {
205 replyTo = av.anonymousEpr;
206 }
208 return replyTo;
209 }
210 public static String getTo(MessageHeaders headers, AddressingVersion av, SOAPVersion sv) {
211 if (av == null) {
212 throw new IllegalArgumentException(AddressingMessages.NULL_ADDRESSING_VERSION());
213 }
215 Header h = getFirstHeader(headers, av.toTag, true, sv);
216 String to;
217 if (h != null) {
218 to = h.getStringContent();
219 } else {
220 to = av.anonymousUri;
221 }
223 return to;
224 }
226 public static Header getFirstHeader(MessageHeaders headers, QName name, boolean markUnderstood, SOAPVersion sv) {
227 if (sv == null) {
228 throw new IllegalArgumentException(AddressingMessages.NULL_SOAP_VERSION());
229 }
231 Iterator<Header> iter = headers.getHeaders(name.getNamespaceURI(), name.getLocalPart(), markUnderstood);
232 while (iter.hasNext()) {
233 Header h = iter.next();
234 if (h.getRole(sv).equals(sv.implicitRole)) {
235 return h;
236 }
237 }
239 return null;
240 }
242 private static void fillRequestAddressingHeaders(@NotNull MessageHeaders headers, @NotNull Packet packet, @NotNull AddressingVersion av, @NotNull SOAPVersion sv, @NotNull OneWayFeature oneWayFeature, boolean oneway, @NotNull String action) {
243 if (!oneway&&!oneWayFeature.isUseAsyncWithSyncInvoke() && Boolean.TRUE.equals(packet.isSynchronousMEP)) {
244 fillRequestAddressingHeaders(headers, packet, av, sv, oneway, action);
245 } else {
246 fillCommonAddressingHeaders(headers, packet, av, sv, action, false);
248 boolean isMessageIdAdded = false;
250 // wsa:ReplyTo
251 // add if it doesn't already exist and OneWayFeature requests a specific ReplyTo
252 if (headers.get(av.replyToTag, false) == null) {
253 WSEndpointReference replyToEpr = oneWayFeature.getReplyTo();
254 if (replyToEpr != null) {
255 headers.add(replyToEpr.createHeader(av.replyToTag));
256 // add wsa:MessageID only for non-null ReplyTo
257 if (packet.getMessage().getHeaders().get(av.messageIDTag, false) == null) {
258 // if header doesn't exist, method getID creates a new random id
259 String newID = oneWayFeature.getMessageId() == null ? Message.generateMessageID() : oneWayFeature.getMessageId();
260 headers.add(new StringHeader(av.messageIDTag, newID));
261 isMessageIdAdded = true;
262 }
263 }
264 }
266 // If the user sets a messageId, use it.
267 final String messageId = oneWayFeature.getMessageId();
268 if (!isMessageIdAdded && messageId != null) {
269 headers.add(new StringHeader(av.messageIDTag, messageId));
270 }
272 // wsa:FaultTo
273 // add if it doesn't already exist and OneWayFeature requests a specific FaultTo
274 if (headers.get(av.faultToTag, false) == null) {
275 WSEndpointReference faultToEpr = oneWayFeature.getFaultTo();
276 if (faultToEpr != null) {
277 headers.add(faultToEpr.createHeader(av.faultToTag));
278 // add wsa:MessageID only for non-null FaultTo
279 if (headers.get(av.messageIDTag, false) == null) {
280 headers.add(new StringHeader(av.messageIDTag, Message.generateMessageID()));
281 }
282 }
283 }
285 // wsa:From
286 if (oneWayFeature.getFrom() != null) {
287 headers.addOrReplace(oneWayFeature.getFrom().createHeader(av.fromTag));
288 }
290 // wsa:RelatesTo
291 if (oneWayFeature.getRelatesToID() != null) {
292 headers.addOrReplace(new RelatesToHeader(av.relatesToTag, oneWayFeature.getRelatesToID()));
293 }
294 }
295 }
297 /**
298 * Creates wsa:To, wsa:Action and wsa:MessageID header on the client
299 *
300 * @param packet request packet
301 * @param av WS-Addressing version
302 * @param sv SOAP version
303 * @param action Action Message Addressing Property value
304 * @throws IllegalArgumentException if any of the parameters is null.
305 */
306 private static void fillCommonAddressingHeaders(MessageHeaders headers, Packet packet, @NotNull AddressingVersion av, @NotNull SOAPVersion sv, @NotNull String action, boolean mustUnderstand) {
307 if (packet == null) {
308 throw new IllegalArgumentException(AddressingMessages.NULL_PACKET());
309 }
311 if (av == null) {
312 throw new IllegalArgumentException(AddressingMessages.NULL_ADDRESSING_VERSION());
313 }
315 if (sv == null) {
316 throw new IllegalArgumentException(AddressingMessages.NULL_SOAP_VERSION());
317 }
319 if (action == null && !sv.httpBindingId.equals(SOAPBinding.SOAP12HTTP_BINDING)) {
320 throw new IllegalArgumentException(AddressingMessages.NULL_ACTION());
321 }
323 // wsa:To
324 if (headers.get(av.toTag, false) == null) {
325 StringHeader h = new StringHeader(av.toTag, packet.endpointAddress.toString());
326 headers.add(h);
327 }
329 // wsa:Action
330 if (action != null) {
331 packet.soapAction = action;
332 if (headers.get(av.actionTag, false) == null) {
333 //As per WS-I BP 1.2/2.0, if one of the WSA headers is MU, then all WSA headers should be treated as MU.,
334 // so just set MU on action header
335 StringHeader h = new StringHeader(av.actionTag, action, sv, mustUnderstand);
336 headers.add(h);
337 }
338 }
339 }
342 }