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.model.wsdl; 27 28import com.sun.istack.internal.Nullable; 29import com.sun.istack.internal.NotNull; 30import com.sun.xml.internal.ws.api.model.ParameterBinding; 31import com.sun.xml.internal.ws.api.model.wsdl.*; 32import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLBoundFault; 33import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLBoundOperation; 34import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLBoundPortType; 35import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLMessage; 36import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLModel; 37import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLOperation; 38import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLPart; 39import com.sun.xml.internal.ws.model.RuntimeModeler; 40 41import javax.jws.WebParam.Mode; 42import javax.jws.soap.SOAPBinding.Style; 43import javax.xml.namespace.QName; 44import javax.xml.stream.XMLStreamReader; 45 46import java.util.*; 47 48/** 49 * Implementation of {@link WSDLBoundOperation} 50 * 51 * @author Vivek Pandey 52 */ 53public final class WSDLBoundOperationImpl extends AbstractExtensibleImpl implements EditableWSDLBoundOperation { 54 private final QName name; 55 56 // map of wsdl:part to the binding 57 private final Map<String, ParameterBinding> inputParts; 58 private final Map<String, ParameterBinding> outputParts; 59 private final Map<String, ParameterBinding> faultParts; 60 private final Map<String, String> inputMimeTypes; 61 private final Map<String, String> outputMimeTypes; 62 private final Map<String, String> faultMimeTypes; 63 64 private boolean explicitInputSOAPBodyParts = false; 65 private boolean explicitOutputSOAPBodyParts = false; 66 private boolean explicitFaultSOAPBodyParts = false; 67 68 private Boolean emptyInputBody; 69 private Boolean emptyOutputBody; 70 private Boolean emptyFaultBody; 71 72 private final Map<String, EditableWSDLPart> inParts; 73 private final Map<String, EditableWSDLPart> outParts; 74 private final List<EditableWSDLBoundFault> wsdlBoundFaults; 75 private EditableWSDLOperation operation; 76 private String soapAction; 77 private ANONYMOUS anonymous; 78 79 private final EditableWSDLBoundPortType owner; 80 81 /** 82 * 83 * @param name wsdl:operation name qualified value 84 */ 85 public WSDLBoundOperationImpl(XMLStreamReader xsr, EditableWSDLBoundPortType owner, QName name) { 86 super(xsr); 87 this.name = name; 88 inputParts = new HashMap<String, ParameterBinding>(); 89 outputParts = new HashMap<String, ParameterBinding>(); 90 faultParts = new HashMap<String, ParameterBinding>(); 91 inputMimeTypes = new HashMap<String, String>(); 92 outputMimeTypes = new HashMap<String, String>(); 93 faultMimeTypes = new HashMap<String, String>(); 94 inParts = new HashMap<String, EditableWSDLPart>(); 95 outParts = new HashMap<String, EditableWSDLPart>(); 96 wsdlBoundFaults = new ArrayList<EditableWSDLBoundFault>(); 97 this.owner = owner; 98 } 99 100 @Override 101 public QName getName(){ 102 return name; 103 } 104 105 @Override 106 public String getSOAPAction() { 107 return soapAction; 108 } 109 110 public void setSoapAction(String soapAction) { 111 this.soapAction = soapAction!=null?soapAction:""; 112 } 113 114 @Override 115 public EditableWSDLPart getPart(String partName, Mode mode) { 116 if(mode==Mode.IN){ 117 return inParts.get(partName); 118 }else if(mode==Mode.OUT){ 119 return outParts.get(partName); 120 } 121 return null; 122 } 123 124 public void addPart(EditableWSDLPart part, Mode mode){ 125 if(mode==Mode.IN) 126 inParts.put(part.getName(), part); 127 else if(mode==Mode.OUT) 128 outParts.put(part.getName(), part); 129 } 130 131 /** 132 * Map of wsdl:input part name and the binding as {@link ParameterBinding} 133 * 134 * @return empty Map if there is no parts 135 */ 136 public Map<String, ParameterBinding> getInputParts() { 137 return inputParts; 138 } 139 140 /** 141 * Map of wsdl:output part name and the binding as {@link ParameterBinding} 142 * 143 * @return empty Map if there is no parts 144 */ 145 public Map<String, ParameterBinding> getOutputParts() { 146 return outputParts; 147 } 148 149 /** 150 * Map of wsdl:fault part name and the binding as {@link ParameterBinding} 151 * 152 * @return empty Map if there is no parts 153 */ 154 public Map<String, ParameterBinding> getFaultParts() { 155 return faultParts; 156 } 157 158 // TODO: what's the difference between this and inputParts/outputParts? 159 @Override 160 public Map<String, ? extends EditableWSDLPart> getInParts() { 161 return Collections.<String, EditableWSDLPart>unmodifiableMap(inParts); 162 } 163 164 @Override 165 public Map<String, ? extends EditableWSDLPart> getOutParts() { 166 return Collections.<String, EditableWSDLPart>unmodifiableMap(outParts); 167 } 168 169 @NotNull 170 @Override 171 public List<? extends EditableWSDLBoundFault> getFaults() { 172 return wsdlBoundFaults; 173 } 174 175 public void addFault(@NotNull EditableWSDLBoundFault fault){ 176 wsdlBoundFaults.add(fault); 177 } 178 179 180 /** 181 * Gets {@link ParameterBinding} for a given wsdl part in wsdl:input 182 * 183 * @param part Name of wsdl:part, must be non-null 184 * @return null if the part is not found. 185 */ 186 public ParameterBinding getInputBinding(String part){ 187 if(emptyInputBody == null){ 188 if(inputParts.get(" ") != null) 189 emptyInputBody = true; 190 else 191 emptyInputBody = false; 192 } 193 ParameterBinding block = inputParts.get(part); 194 if(block == null){ 195 if(explicitInputSOAPBodyParts || emptyInputBody) 196 return ParameterBinding.UNBOUND; 197 return ParameterBinding.BODY; 198 } 199 200 return block; 201 } 202 203 /** 204 * Gets {@link ParameterBinding} for a given wsdl part in wsdl:output 205 * 206 * @param part Name of wsdl:part, must be non-null 207 * @return null if the part is not found. 208 */ 209 public ParameterBinding getOutputBinding(String part){ 210 if(emptyOutputBody == null){ 211 if(outputParts.get(" ") != null) 212 emptyOutputBody = true; 213 else 214 emptyOutputBody = false; 215 } 216 ParameterBinding block = outputParts.get(part); 217 if(block == null){ 218 if(explicitOutputSOAPBodyParts || emptyOutputBody) 219 return ParameterBinding.UNBOUND; 220 return ParameterBinding.BODY; 221 } 222 223 return block; 224 } 225 226 /** 227 * Gets {@link ParameterBinding} for a given wsdl part in wsdl:fault 228 * 229 * @param part Name of wsdl:part, must be non-null 230 * @return null if the part is not found. 231 */ 232 public ParameterBinding getFaultBinding(String part){ 233 if(emptyFaultBody == null){ 234 if(faultParts.get(" ") != null) 235 emptyFaultBody = true; 236 else 237 emptyFaultBody = false; 238 } 239 ParameterBinding block = faultParts.get(part); 240 if(block == null){ 241 if(explicitFaultSOAPBodyParts || emptyFaultBody) 242 return ParameterBinding.UNBOUND; 243 return ParameterBinding.BODY; 244 } 245 246 return block; 247 } 248 249 /** 250 * Gets the MIME type for a given wsdl part in wsdl:input 251 * 252 * @param part Name of wsdl:part, must be non-null 253 * @return null if the part is not found. 254 */ 255 public String getMimeTypeForInputPart(String part){ 256 return inputMimeTypes.get(part); 257 } 258 259 /** 260 * Gets the MIME type for a given wsdl part in wsdl:output 261 * 262 * @param part Name of wsdl:part, must be non-null 263 * @return null if the part is not found. 264 */ 265 public String getMimeTypeForOutputPart(String part){ 266 return outputMimeTypes.get(part); 267 } 268 269 /** 270 * Gets the MIME type for a given wsdl part in wsdl:fault 271 * 272 * @param part Name of wsdl:part, must be non-null 273 * @return null if the part is not found. 274 */ 275 public String getMimeTypeForFaultPart(String part){ 276 return faultMimeTypes.get(part); 277 } 278 279 @Override 280 public EditableWSDLOperation getOperation() { 281 return operation; 282 } 283 284 285 @Override 286 public EditableWSDLBoundPortType getBoundPortType() { 287 return owner; 288 } 289 290 public void setInputExplicitBodyParts(boolean b) { 291 explicitInputSOAPBodyParts = b; 292 } 293 294 public void setOutputExplicitBodyParts(boolean b) { 295 explicitOutputSOAPBodyParts = b; 296 } 297 298 public void setFaultExplicitBodyParts(boolean b) { 299 explicitFaultSOAPBodyParts = b; 300 } 301 302 private Style style = Style.DOCUMENT; 303 public void setStyle(Style style){ 304 this.style = style; 305 } 306 307 @Override 308 public @Nullable QName getRequestPayloadName() { 309 if (emptyRequestPayload) 310 return null; 311 312 if (requestPayloadName != null) 313 return requestPayloadName; 314 315 if(style.equals(Style.RPC)){ 316 String ns = getRequestNamespace() != null ? getRequestNamespace() : name.getNamespaceURI(); 317 requestPayloadName = new QName(ns, name.getLocalPart()); 318 return requestPayloadName; 319 }else{ 320 QName inMsgName = operation.getInput().getMessage().getName(); 321 EditableWSDLMessage message = messages.get(inMsgName); 322 for(EditableWSDLPart part:message.parts()){ 323 ParameterBinding binding = getInputBinding(part.getName()); 324 if(binding.isBody()){ 325 requestPayloadName = part.getDescriptor().name(); 326 return requestPayloadName; 327 } 328 } 329 330 //Its empty payload 331 emptyRequestPayload = true; 332 } 333 //empty body 334 return null; 335 } 336 337 @Override 338 public @Nullable QName getResponsePayloadName() { 339 if (emptyResponsePayload) 340 return null; 341 342 if (responsePayloadName != null) 343 return responsePayloadName; 344 345 if(style.equals(Style.RPC)){ 346 String ns = getResponseNamespace() != null ? getResponseNamespace() : name.getNamespaceURI(); 347 responsePayloadName = new QName(ns, name.getLocalPart()+"Response"); 348 return responsePayloadName; 349 }else{ 350 QName outMsgName = operation.getOutput().getMessage().getName(); 351 EditableWSDLMessage message = messages.get(outMsgName); 352 for(EditableWSDLPart part:message.parts()){ 353 ParameterBinding binding = getOutputBinding(part.getName()); 354 if(binding.isBody()){ 355 responsePayloadName = part.getDescriptor().name(); 356 return responsePayloadName; 357 } 358 } 359 360 //Its empty payload 361 emptyResponsePayload = true; 362 } 363 //empty body 364 return null; 365 } 366 367 368 private String reqNamespace; 369 private String respNamespace; 370 371 /** 372 * For rpclit gives namespace value on soapbinding:body@namespace 373 * 374 * @return non-null for rpclit and null for doclit 375 * @see RuntimeModeler#processRpcMethod(JavaMethodImpl, String, String, Method) 376 */ 377 @Override 378 public String getRequestNamespace(){ 379 return (reqNamespace != null)?reqNamespace:name.getNamespaceURI(); 380 } 381 382 public void setRequestNamespace(String ns){ 383 reqNamespace = ns; 384 } 385 386 /** 387 * For rpclit gives namespace value on soapbinding:body@namespace 388 * 389 * @return non-null for rpclit and null for doclit 390 * @see RuntimeModeler#processRpcMethod(JavaMethodImpl, String, String, Method) 391 */ 392 @Override 393 public String getResponseNamespace(){ 394 return (respNamespace!=null)?respNamespace:name.getNamespaceURI(); 395 } 396 397 public void setResponseNamespace(String ns){ 398 respNamespace = ns; 399 } 400 401 EditableWSDLBoundPortType getOwner(){ 402 return owner; 403 } 404 405 private QName requestPayloadName; 406 private QName responsePayloadName; 407 private boolean emptyRequestPayload; 408 private boolean emptyResponsePayload; 409 private Map<QName, ? extends EditableWSDLMessage> messages; 410 411 public void freeze(EditableWSDLModel parent) { 412 messages = parent.getMessages(); 413 operation = owner.getPortType().get(name.getLocalPart()); 414 for(EditableWSDLBoundFault bf : wsdlBoundFaults){ 415 bf.freeze(this); 416 } 417 } 418 419 public void setAnonymous(ANONYMOUS anonymous) { 420 this.anonymous = anonymous; 421 } 422 423 /** 424 * @inheritDoc 425 */ 426 @Override 427 public ANONYMOUS getAnonymous() { 428 return anonymous; 429 } 430} 431