summaryrefslogtreecommitdiffstats
path: root/sca-java-1.x/tags/java-M1-20060522/java/sca/bindings/binding.axis2/src/main/java/org/apache/tuscany/binding/axis2/util/WebServiceOperationMetaData.java
blob: 1ebca5d3fc2d80551a123bea6f9b324570442672 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
/**
 *
 *  Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.apache.tuscany.binding.axis2.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.wsdl.Binding;
import javax.wsdl.BindingInput;
import javax.wsdl.BindingOperation;
import javax.wsdl.BindingOutput;
import javax.wsdl.Input;
import javax.wsdl.Message;
import javax.wsdl.Operation;
import javax.wsdl.Output;
import javax.wsdl.Part;
import javax.wsdl.extensions.soap.SOAPBinding;
import javax.wsdl.extensions.soap.SOAPHeader;
import javax.wsdl.extensions.soap.SOAPOperation;
import javax.xml.namespace.QName;

/**
 * Metadata for a WSDL operation
 * 
 */
public class WebServiceOperationMetaData {
    // WSDL Binding and BindingOperation
    private Binding binding;

    private BindingOperation bindingOperation;

    // Fields to cache derived metadata
    private transient Set<Part> inputHeaderParts;

    private transient Set<Part> outputHeaderParts;

    private transient String style;

    private transient String use;

    private transient String soapAction;

    private transient List<Object> signature;

    private String encoding;

    private transient QName rpcOperationName;

    public WebServiceOperationMetaData(Binding binding, BindingOperation bindingOperation) {
        this.binding = binding;
        this.bindingOperation = bindingOperation;
    }

    public WebServiceOperationMetaData(Binding binding, BindingOperation bindingOperation, String style, String use, String encoding,
            String soapAction) {
        this.binding = binding;
        this.bindingOperation = bindingOperation;
        this.style = style;
        this.use = use;
        this.encoding = encoding;
        this.soapAction = soapAction;
    }

    public Set<Part> getInputHeaderParts() {
        if (inputHeaderParts == null) {
            // Build a set of header parts that we need to exclude
            inputHeaderParts = new HashSet<Part>();
            BindingInput bindingInput = bindingOperation.getBindingInput();

            if (bindingInput != null) {
                Operation operation = bindingOperation.getOperation();
                javax.wsdl.Message message = operation.getInput().getMessage();
                List elements = bindingInput.getExtensibilityElements();
                for (Iterator i = elements.iterator(); i.hasNext();) {
                    Object extensibilityElement = i.next();
                    Part part = getPartFromSOAPHeader(message, extensibilityElement);
                    if (part != null) {
                        inputHeaderParts.add(part);
                    }
                }
            }
        }
        return inputHeaderParts;
    }

    public Set<Part> getOutputHeaderParts() {
        if (outputHeaderParts == null) {
            // Build a set of header parts that we need to exclude
            outputHeaderParts = new HashSet<Part>();
            BindingOutput bindingOutput = bindingOperation.getBindingOutput();

            if (bindingOutput != null) {
                Operation operation = bindingOperation.getOperation();
                javax.wsdl.Message message = operation.getOutput().getMessage();
                List elements = bindingOutput.getExtensibilityElements();
                for (Iterator i = elements.iterator(); i.hasNext();) {
                    Object extensibilityElement = i.next();
                    Part part = getPartFromSOAPHeader(message, extensibilityElement);
                    if (part != null) {
                        outputHeaderParts.add(part);
                    }
                }
            }
        }
        return outputHeaderParts;
    }

    private Part getPartFromSOAPHeader(Message message, Object extensibilityElement) {
        Part part = null;
        if (extensibilityElement instanceof SOAPHeader) {
            SOAPHeader soapHeader = (SOAPHeader) extensibilityElement;
            QName msgName = soapHeader.getMessage();
            if (message.getQName().equals(msgName)) {
                part = message.getPart(soapHeader.getPart());
            }
        } else if (extensibilityElement instanceof SOAPHeader) {
            SOAPHeader soapHeader = (SOAPHeader) extensibilityElement;
            QName msgName = soapHeader.getMessage();
            if (message.getQName().equals(msgName)) {
                part = message.getPart(soapHeader.getPart());
            }
        }
        return part;
    }

    public String getStyle() {
        if (style == null) {
            SOAPOperation soapOperation = (SOAPOperation) WebServicePortMetaData.getExtensibilityElement(bindingOperation.getExtensibilityElements(),
                    SOAPOperation.class);
            if (soapOperation != null) {
                style = soapOperation.getStyle();
            }
            if (style == null) {
                SOAPBinding soapBinding = WebServicePortMetaData.getExtensibilityElement(binding.getExtensibilityElements(), SOAPBinding.class);
                if (soapBinding != null) {
                    style = soapBinding.getStyle();
                }
            }
            if (style == null) {
                style = "document";
            }
        }
        return style;
    }

    /**
     * Returns the SOAP action for the given operation.
     * 
     * @param wsdlBindingOperation
     * @return
     */
    public String getSOAPAction() {
        if (soapAction == null) {
            final List wsdlBindingOperationExtensions = bindingOperation.getExtensibilityElements();
            final SOAPOperation soapOp = WebServicePortMetaData.getExtensibilityElement(wsdlBindingOperationExtensions, SOAPOperation.class);
            if (soapOp != null) {
                soapAction = soapOp.getSoapActionURI();
            }
        }
        return soapAction;
    }

    public QName getRPCOperationName() {
        if (rpcOperationName == null) {
            javax.wsdl.extensions.soap.SOAPBody soapBody = getSOAPBody(true);
            String ns = (soapBody != null) ? soapBody.getNamespaceURI() : binding.getPortType().getQName().getNamespaceURI();
            String name = bindingOperation.getOperation().getName();
            rpcOperationName = new QName(ns, name);
        }
        return rpcOperationName;
    }

    private List<String> getSOAPBodyParts(boolean input) {
        javax.wsdl.extensions.soap.SOAPBody soapBody = getSOAPBody(input);
        if (soapBody != null) {
            List parts = soapBody.getParts();
            if (parts != null) {
                List<String> names = new ArrayList<String>();
                for (Iterator i = parts.iterator(); i.hasNext();) {
                    Object part = i.next();
                    if (part instanceof String) {
                        names.add((String) part);
                    } else if (part instanceof Part) {
                        names.add(((Part) part).getName());
                    }
                }
                return names;
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    private javax.wsdl.extensions.soap.SOAPBody getSOAPBody(boolean input) {
        List elements = null;
        if (input) {
            BindingInput bindingInput = bindingOperation.getBindingInput();
            if (bindingInput == null) {
                return null;
            }
            elements = bindingInput.getExtensibilityElements();
        } else {
            BindingOutput bindingOutput = bindingOperation.getBindingOutput();
            if (bindingOutput == null) {
                return null;
            }
            elements = bindingOutput.getExtensibilityElements();
        }
        javax.wsdl.extensions.soap.SOAPBody soapBody = WebServicePortMetaData.getExtensibilityElement(elements,
                javax.wsdl.extensions.soap.SOAPBody.class);
        return soapBody;
    }

    /**
     * Returns the use attribute
     * 
     * @param wsdlOperation
     * @return
     */
    public String getUse() {
        if (use == null) {
            javax.wsdl.extensions.soap.SOAPBody soapBody = getSOAPBody(true);
            if (soapBody != null) {
                use = soapBody.getUse();
            }
            if (use == null) {
                use = "literal";
            }
        }
        return use;
    }

    @SuppressWarnings("unchecked")
    public String getEncoding() {
        if (encoding == null) {
            javax.wsdl.extensions.soap.SOAPBody soapBody = getSOAPBody(true);
            if (soapBody != null) {
                List<String> styles = (List<String>) soapBody.getEncodingStyles();
                if (styles != null && !styles.isEmpty()) {
                    encoding = styles.get(0);
                }
            }
            if (encoding == null) {
                encoding = "";
            }
        }
        return encoding;
    }

    public boolean isDocLitWrapped() {
        boolean flag = getStyle().equals("document") && getUse().equals("literal");
        if (!flag) {
            return false;
        }
        Message msg = getMessage(true);
        if (msg == null) {
            return false;
        }
        List parts = msg.getOrderedParts(null);
        if (parts.size() != 1) {
            return false;
        }
        Part part = (Part) parts.get(0);
        QName element = part.getElementName();
        if (element == null) {
            return false;
        }
        return element.getLocalPart().equals(bindingOperation.getOperation().getName());
    }

    /*
     * public SOAPMediator createMediator(boolean serverMode) throws SOAPException { // create a new mediator for each invoke for thread-safety
     * boolean rpcStyle = getStyle().equals("rpc"); boolean rpcEncoded = isEncoded();
     * 
     * SOAPMediator mediator = null;
     * 
     * if (!rpcStyle) { // Document mediator = new SOAPDocumentLiteralMediatorImpl(this, serverMode); } else { if (!rpcEncoded) mediator = new
     * SOAPRPCLiteralMediatorImpl(this, serverMode); // RPC-literal else mediator = new SOAPRPCEncodedMediatorImpl(this, serverMode); // RPC-encoded }
     * return mediator; }
     */

    /**
     * Get the operation signature from the WSDL operation
     * 
     * @param wsdlBinding
     * @param bindingOperation
     * @return
     */
    public List<?> getOperationSignature() {
        if (signature == null) {
            signature = new ArrayList<Object>();

            Operation operation = bindingOperation.getOperation();
            if (operation == null) {
                return signature;
            }

            final Input input = operation.getInput();
            if (input == null) {
                return signature;
            }

            String sstyle = getStyle();

            if ("rpc".equals(sstyle)) {
                Collection partNames = input.getMessage().getParts().values();
                for (Iterator i = partNames.iterator(); i.hasNext();) {
                    Part part = (Part) i.next();
                    signature.add(part.getName());
                }
            } else {
                /*
                 * WS-I Basic Profile 1.1 4.7.6 Operation Signatures Definition: operation signature
                 * 
                 * The profile defines the "operation signature" to be the fully qualified name of the child element of SOAP body of the SOAP input
                 * message described by an operation in a WSDL binding.
                 * 
                 * In the case of rpc-literal binding, the operation name is used as a wrapper for the part accessors. In the document-literal case,
                 * since a wrapper with the operation name is not present, the message signatures must be correctly designed so that they meet this
                 * requirement.
                 * 
                 * An endpoint that supports multiple operations must unambiguously identify the operation being invoked based on the input message
                 * that it receives. This is only possible if all the operations specified in the wsdl:binding associated with an endpoint have a
                 * unique operation signature.
                 * 
                 * R2710 The operations in a wsdl:binding in a DESCRIPTION MUST result in operation signatures that are different from one another.
                 */
                List<String> bodyParts = getSOAPBodyParts(true);

                Collection<?> parts = input.getMessage().getParts().values();
                // Exclude the parts to be transmitted in SOAP header
                if (bodyParts == null) {
                    parts.removeAll(getInputHeaderParts());
                }
                for (Iterator i = parts.iterator(); i.hasNext();) {
                    Part part = (Part) i.next();
                    if (bodyParts == null) {
                        // All parts
                        QName elementName = part.getElementName();
                        if (elementName == null) {
                            elementName = new QName("", part.getName());
                            // TODO: [rfeng] throw new
                            // ServiceRuntimeException("Message part for
                            // document style must refer to an XSD element
                            // using a QName: " + part);
                        }
                        signature.add(elementName);
                    } else {
                        // "parts" in soap:body
                        if (bodyParts.contains(part.getName())) {
                            QName elementName = part.getElementName();
                            if (elementName == null) {
                                elementName = new QName("", part.getName());
                                // TODO: [rfeng] throw new
                                // ServiceRuntimeException("Message part for
                                // document style must refer to an XSD
                                // element using a QName: " + part);
                            }
                            signature.add(elementName);
                        }

                    }
                }
            }
        }
        return signature;
    }

    public Message getMessage(boolean isInput) {
        Operation operation = bindingOperation.getOperation();
        if (operation == null) {
            return null;
        }

        if (isInput) {
            final Input input = operation.getInput();
            return input == null ? null : input.getMessage();
        } else {
            final Output output = operation.getOutput();
            return output == null ? null : output.getMessage();
        }
    }

    public Part getInputPart(int index) {
        Part part = null;
        Message message = getMessage(true);
        if (message == null) {
            return part;
        }

        List parts = message.getOrderedParts(null);
        return (Part) parts.get(index);

    }

    public Part getOutputPart(int index) {
        Part part = null;
        Message message = getMessage(false);
        if (message == null) {
            return part;
        }

        List parts = message.getOrderedParts(null);
        return (Part) parts.get(index);

    }

    /**
     * Get a list of indexes for each part in the SOAP body
     * 
     * @param isInput
     *            TODO
     * @return
     */
    public List<Integer> getBodyPartIndexes(boolean isInput) {
        List<Integer> indexes = new ArrayList<Integer>();

        Message message = getMessage(isInput);
        if (message == null) {
            return indexes;
        }

        List<String> bodyParts = getSOAPBodyParts(isInput);
        List parts = message.getOrderedParts(null);
        Set headerParts = isInput ? getInputHeaderParts() : getOutputHeaderParts();

        int index = 0;
        for (Iterator i = parts.iterator(); i.hasNext(); index++) {
            Part part = (Part) i.next();
            if (headerParts.contains(part)) {
                continue;
            }
            if (bodyParts == null) {
                // All parts
                indexes.add(index);
            } else {
                // "parts" in soap:body
                if (bodyParts.contains(part.getName())) {
                    indexes.add(index);
                }
            }
        }
        return indexes;
    }

    /**
     * Get the corresponding index for a part in the SOAP header by element name
     * 
     * @param elementName
     * @param isInput
     *            TODO
     * @return
     */
    public int getHeaderPartIndex(QName elementName, boolean isInput) {

        Message message = getMessage(isInput);
        if (message == null) {
            return -1;
        }

        List parts = message.getOrderedParts(null);
        Set headerParts = isInput ? getInputHeaderParts() : getOutputHeaderParts();

        int index = 0;
        for (Iterator i = parts.iterator(); i.hasNext(); index++) {
            Part part = (Part) i.next();
            // Test if the part is in header section
            if (headerParts.contains(part) && elementName.equals(part.getElementName())) {
                return index;
            }
        }
        return -1;
    }

    public BindingOperation getBindingOperation() {
        return bindingOperation;
    }

}