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 */ 25 26package com.sun.xml.internal.ws.api.message; 27 28import java.util.Iterator; 29 30import javax.xml.namespace.QName; 31import javax.xml.stream.XMLStreamException; 32import javax.xml.ws.WebServiceException; 33import javax.xml.ws.soap.SOAPBinding; 34 35import com.sun.istack.internal.NotNull; 36import com.sun.xml.internal.ws.addressing.WsaTubeHelper; 37import com.sun.xml.internal.ws.api.SOAPVersion; 38import com.sun.xml.internal.ws.api.WSBinding; 39import com.sun.xml.internal.ws.api.addressing.AddressingPropertySet; 40import com.sun.xml.internal.ws.api.addressing.AddressingVersion; 41import com.sun.xml.internal.ws.api.addressing.OneWayFeature; 42import com.sun.xml.internal.ws.api.addressing.WSEndpointReference; 43import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation; 44import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; 45import com.sun.xml.internal.ws.message.RelatesToHeader; 46import com.sun.xml.internal.ws.message.StringHeader; 47import com.sun.xml.internal.ws.resources.AddressingMessages; 48import com.sun.xml.internal.ws.resources.ClientMessages; 49 50public 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); 57 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 } 65 66 // wsa:FaultTo 67 if (headers.get(av.faultToTag, false) == null) { 68 headers.add(epr.createHeader(av.faultToTag)); 69 } 70 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 } 85 86 if (binding.isFeatureEnabled(SuppressAutomaticWSARequestHeadersFeature.class)) { 87 return; 88 } 89 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); 100 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 } 119 120 OneWayFeature oneWayFeature = binding.getFeature(OneWayFeature.class); 121 final AddressingPropertySet addressingPropertySet = packet.getSatellite(AddressingPropertySet.class); 122 oneWayFeature = addressingPropertySet == null ? oneWayFeature : new OneWayFeature(addressingPropertySet, addressingVersion); 123 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 } 132 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 } 137 138 String action = null; 139 Header h = getFirstHeader(headers, av.actionTag, true, sv); 140 if (h != null) { 141 action = h.getStringContent(); 142 } 143 144 return action; 145 } 146 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 } 151 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 } 161 162 return faultTo; 163 } 164 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 } 169 170 Header h = getFirstHeader(headers, av.messageIDTag, true, sv); 171 String messageId = null; 172 if (h != null) { 173 messageId = h.getStringContent(); 174 } 175 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 } 182 183 Header h = getFirstHeader(headers, av.relatesToTag, true, sv); 184 String relatesTo = null; 185 if (h != null) { 186 relatesTo = h.getStringContent(); 187 } 188 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 } 195 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 } 207 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 } 214 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 } 222 223 return to; 224 } 225 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 } 230 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 } 238 239 return null; 240 } 241 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); 247 248 boolean isMessageIdAdded = false; 249 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 } 265 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 } 271 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 } 284 285 // wsa:From 286 if (oneWayFeature.getFrom() != null) { 287 headers.addOrReplace(oneWayFeature.getFrom().createHeader(av.fromTag)); 288 } 289 290 // wsa:RelatesTo 291 if (oneWayFeature.getRelatesToID() != null) { 292 headers.addOrReplace(new RelatesToHeader(av.relatesToTag, oneWayFeature.getRelatesToID())); 293 } 294 } 295 } 296 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 } 310 311 if (av == null) { 312 throw new IllegalArgumentException(AddressingMessages.NULL_ADDRESSING_VERSION()); 313 } 314 315 if (sv == null) { 316 throw new IllegalArgumentException(AddressingMessages.NULL_SOAP_VERSION()); 317 } 318 319 if (action == null && !sv.httpBindingId.equals(SOAPBinding.SOAP12HTTP_BINDING)) { 320 throw new IllegalArgumentException(AddressingMessages.NULL_ACTION()); 321 } 322 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 } 328 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 } 340 341 342} 343