View Javadoc
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  
26  package com.sun.xml.internal.ws.model.wsdl;
27  
28  import com.sun.istack.internal.Nullable;
29  import com.sun.istack.internal.NotNull;
30  import com.sun.xml.internal.ws.api.model.ParameterBinding;
31  import com.sun.xml.internal.ws.api.model.wsdl.*;
32  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLBoundFault;
33  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLBoundOperation;
34  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLBoundPortType;
35  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLMessage;
36  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLModel;
37  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLOperation;
38  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLPart;
39  import com.sun.xml.internal.ws.model.RuntimeModeler;
40  
41  import javax.jws.WebParam.Mode;
42  import javax.jws.soap.SOAPBinding.Style;
43  import javax.xml.namespace.QName;
44  import javax.xml.stream.XMLStreamReader;
45  
46  import java.util.*;
47  
48  /**
49   * Implementation of {@link WSDLBoundOperation}
50   *
51   * @author Vivek Pandey
52   */
53  public 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 }