001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * If you wish your version of this file to be governed by only the CDDL
025: * or only the GPL Version 2, indicate your decision by adding
026: * "[Contributor] elects to include this software in this distribution
027: * under the [CDDL or GPL Version 2] license." If you do not indicate a
028: * single choice of license, a recipient has the option to distribute
029: * your version of this file under either the CDDL, the GPL Version 2 or
030: * to extend the choice of license to its licensees as provided above.
031: * However, if you add GPL Version 2 code and therefore, elected the GPL
032: * Version 2 license, then the option applies only if the new code is
033: * made subject to such option by the copyright holder.
034: *
035: * Contributor(s):
036: *
037: * Portions Copyrighted 2008 Sun Microsystems, Inc.
038: */
039:
040: package org.netbeans.modules.xml.wsdl.model.extensions.soap.validation;
041:
042: import java.net.URI;
043: import java.net.URL;
044: import java.util.ArrayList;
045: import java.util.Collection;
046: import java.util.HashMap;
047: import java.util.Iterator;
048: import java.util.LinkedList;
049: import java.util.List;
050: import java.util.Map;
051: import org.netbeans.modules.xml.wsdl.model.Binding;
052: import org.netbeans.modules.xml.wsdl.model.BindingFault;
053: import org.netbeans.modules.xml.wsdl.model.BindingInput;
054: import org.netbeans.modules.xml.wsdl.model.BindingOperation;
055: import org.netbeans.modules.xml.wsdl.model.BindingOutput;
056: import org.netbeans.modules.xml.wsdl.model.Definitions;
057: import org.netbeans.modules.xml.wsdl.model.Message;
058: import org.netbeans.modules.xml.wsdl.model.OperationParameter;
059: import org.netbeans.modules.xml.wsdl.model.Part;
060: import org.netbeans.modules.xml.wsdl.model.Port;
061: import org.netbeans.modules.xml.wsdl.model.Service;
062: import org.netbeans.modules.xml.wsdl.model.WSDLComponent;
063: import org.netbeans.modules.xml.wsdl.model.WSDLModel;
064: import org.netbeans.modules.xml.wsdl.model.extensions.soap.SOAPAddress;
065: import org.netbeans.modules.xml.wsdl.model.extensions.soap.SOAPBinding;
066: import org.netbeans.modules.xml.wsdl.model.extensions.soap.SOAPBody;
067: import org.netbeans.modules.xml.wsdl.model.extensions.soap.SOAPComponent;
068: import org.netbeans.modules.xml.wsdl.model.extensions.soap.SOAPFault;
069: import org.netbeans.modules.xml.wsdl.model.extensions.soap.SOAPHeader;
070: import org.netbeans.modules.xml.wsdl.model.extensions.soap.SOAPHeaderBase;
071: import org.netbeans.modules.xml.wsdl.model.extensions.soap.SOAPHeaderFault;
072: import org.netbeans.modules.xml.wsdl.model.extensions.soap.SOAPMessageBase;
073: import org.netbeans.modules.xml.wsdl.model.extensions.soap.SOAPOperation;
074: import org.netbeans.modules.xml.xam.dom.NamedComponentReference;
075: import org.netbeans.modules.xml.xam.spi.Validation;
076: import org.netbeans.modules.xml.xam.spi.Validator;
077: import org.netbeans.modules.xml.xam.spi.Validator.ResultItem;
078: import org.openide.util.NbBundle;
079:
080: /**
081: *
082: * @author nang
083: */
084: public class SOAPComponentVisitor implements SOAPComponent.Visitor {
085: private static final String HTTP_DEFAULT_PORT_TOKEN = "${HttpDefaultPort}";
086: private static final String HTTPS_DEFAULT_PORT_TOKEN = "${HttpsDefaultPort}";
087:
088: private final SOAPComponentValidator mValidator;
089: private final Validation mValidation;
090: private final List<ResultItem> results;
091:
092: SOAPComponentVisitor(SOAPComponentValidator validator,
093: Validation validation) {
094: mValidator = validator;
095: mValidation = validation;
096: results = new LinkedList<ResultItem>();
097: }
098:
099: public List<ResultItem> getResultItems() {
100: return results;
101: }
102:
103: public void visit(WSDLModel wsdlModel) {
104: Definitions defs = wsdlModel.getDefinitions();
105: Iterator<Binding> bindings = defs.getBindings().iterator();
106: while (bindings.hasNext()) {
107: Binding binding = bindings.next();
108: int numSoapBindings = binding.getExtensibilityElements(
109: SOAPBinding.class).size();
110: if (numSoapBindings > 0 && numSoapBindings != 1) {
111: results
112: .add(new Validator.ResultItem(
113: mValidator,
114: Validator.ResultType.ERROR,
115: binding,
116: NbBundle
117: .getMessage(
118: SOAPComponentVisitor.class,
119: "SOAPBindingValidator.Only_one_binding_allowed")));
120: }
121: Iterator<SOAPBinding> soapBindings = binding
122: .getExtensibilityElements(SOAPBinding.class)
123: .iterator();
124: while (soapBindings.hasNext()) {
125: soapBindings.next().accept(this );
126: }
127: Iterator<BindingOperation> bindingOps = binding
128: .getBindingOperations().iterator();
129: while (bindingOps.hasNext()) {
130: BindingOperation bindingOp = bindingOps.next();
131: List soapOpsList = bindingOp
132: .getExtensibilityElements(SOAPOperation.class);
133: Iterator<SOAPOperation> soapOps = soapOpsList
134: .iterator();
135: while (soapOps.hasNext()) {
136: soapOps.next().accept(this );
137: }
138:
139: if (soapOpsList.size() > 0) {
140: BindingInput bindingInput = bindingOp
141: .getBindingInput();
142: if (bindingInput != null) {
143: visit(bindingInput);
144: }
145:
146: BindingOutput bindingOutput = bindingOp
147: .getBindingOutput();
148: if (bindingOutput != null) {
149: visit(bindingOutput);
150: }
151:
152: Iterator<BindingFault> bindingFaults = bindingOp
153: .getBindingFaults().iterator();
154: while (bindingFaults.hasNext()) {
155: BindingFault bindingFault = bindingFaults
156: .next();
157: int numSoapFaults = bindingFault
158: .getExtensibilityElements(
159: SOAPFault.class).size();
160: if (numSoapFaults == 0) {
161: results
162: .add(new Validator.ResultItem(
163: mValidator,
164: Validator.ResultType.ERROR,
165: bindingFault,
166: NbBundle
167: .getMessage(
168: SOAPComponentVisitor.class,
169: "SOAPFaultValidator.No_soap_fault_defined")));
170: }
171: if (numSoapFaults > 0 && numSoapFaults != 1) {
172:
173: results
174: .add(new Validator.ResultItem(
175: mValidator,
176: Validator.ResultType.ERROR,
177: bindingFault,
178: NbBundle
179: .getMessage(
180: SOAPComponentVisitor.class,
181: "SOAPFaultValidator.Only_one_fault_allowed")));
182: }
183:
184: Iterator<SOAPFault> soapFaults = bindingFault
185: .getExtensibilityElements(
186: SOAPFault.class).iterator();
187: while (soapFaults.hasNext()) {
188: SOAPFault soapFault = (SOAPFault) soapFaults
189: .next(); // should be only one defined
190: if (soapFault.getName() != null
191: && !soapFault.getName().equals(
192: bindingFault.getName())) {
193: results
194: .add(new Validator.ResultItem(
195: mValidator,
196: Validator.ResultType.ERROR,
197: bindingFault,
198: NbBundle
199: .getMessage(
200: SOAPComponentVisitor.class,
201: "SOAPFaultValidator.Fault_name_not_match")));
202: }
203: soapFault.accept(this );
204: }
205:
206: }
207: }
208: }
209: }
210: Iterator<Service> services = defs.getServices().iterator();
211: while (services.hasNext()) {
212: Iterator<Port> ports = services.next().getPorts()
213: .iterator();
214: while (ports.hasNext()) {
215: Port port = ports.next();
216: if (port.getBinding() != null) {
217: Binding binding = port.getBinding().get();
218: if (binding != null) {
219: int numRelatedSoapBindings = binding
220: .getExtensibilityElements(
221: SOAPBinding.class).size();
222: Iterator<SOAPAddress> soapAddresses = port
223: .getExtensibilityElements(
224: SOAPAddress.class).iterator();
225: if ((numRelatedSoapBindings > 0)
226: && (!soapAddresses.hasNext())) {
227: results
228: .add(new Validator.ResultItem(
229: mValidator,
230: Validator.ResultType.ERROR,
231: port,
232: NbBundle
233: .getMessage(
234: SOAPComponentVisitor.class,
235: "SOAPAddressValidator.Missing_SoapAddress")));
236: }
237:
238: if (port.getExtensibilityElements(
239: SOAPAddress.class).size() > 1) {
240: results
241: .add(new Validator.ResultItem(
242: mValidator,
243: Validator.ResultType.ERROR,
244: port,
245: NbBundle
246: .getMessage(
247: SOAPComponentVisitor.class,
248: "SOAPAddressValidator.Only_one_SoapAddress_allowed")));
249: }
250: while (soapAddresses.hasNext()) {
251: soapAddresses.next().accept(this );
252: }
253: }
254: }
255: }
256: }
257: }
258:
259: /////////////////////////////////////////////
260: ////
261: //// SOAPComponent.Visitor interface
262: ////
263: /////////////////////////////////////////////
264:
265: public void visit(SOAPHeader header) {
266: NamedComponentReference<Message> message = header.getMessage();
267: if (message == null) {
268: results.add(new Validator.ResultItem(mValidator,
269: Validator.ResultType.ERROR, header,
270: NbBundle.getMessage(SOAPComponentVisitor.class,
271: "SOAPHeaderValidator.Missing_message")));
272: }
273:
274: String part = header.getPart();
275: if (part == null) {
276: results
277: .add(new Validator.ResultItem(mValidator,
278: Validator.ResultType.ERROR, header,
279: NbBundle.getMessage(
280: SOAPComponentVisitor.class,
281: "SOAPHeaderValidator.Missing_part")));
282: }
283:
284: try {
285: SOAPMessageBase.Use use = header.getUse();
286: if (use == null) {
287: results.add(new Validator.ResultItem(mValidator,
288: Validator.ResultType.ERROR, header,
289: NbBundle.getMessage(SOAPComponentVisitor.class,
290: "SOAPHeaderValidator.Missing_use")));
291: }
292: } catch (Throwable th) {
293: results
294: .add(new Validator.ResultItem(
295: mValidator,
296: Validator.ResultType.ERROR,
297: header,
298: NbBundle
299: .getMessage(
300: SOAPComponentVisitor.class,
301: "SOAPHeaderValidator.Unsupported_header_use_attribute")));
302: }
303:
304: Collection<String> encodingStyles = header.getEncodingStyles();
305: if (encodingStyles != null) {
306: // This is optional. Don't verify contents at this point.
307: }
308:
309: String namespace = header.getNamespace();
310: if (namespace != null) {
311: // This is optional. We should verify that it is a valid URI, but
312: // I don't want to be too restrictive at this point.
313:
314: }
315: }
316:
317: public void visit(SOAPAddress address) {
318: String location = address.getLocation();
319: if (location == null) {
320: results.add(new Validator.ResultItem(mValidator,
321: Validator.ResultType.ERROR, address,
322: NbBundle.getMessage(SOAPComponentVisitor.class,
323: "SOAPAddressValidator.Missing_location")));
324: return;
325: }
326:
327: ////////////////////////////////////////////////////////
328: // GSR changed for Java EE Service Engine
329: // As instructed by Jerry Waldorf.
330: ////////////////////////////////////////////////////////
331: if ("REPLACE_WITH_ACTUAL_URL".equals(location)) {
332: return;
333: }
334:
335: ///////////////////////////////////////////////////////
336: // Check for valid tokens for default HTTP and HTTPS port
337: // Introduced to support clustering
338: ////////////////////////////////////////////////////////
339:
340: if (location.indexOf(HTTP_DEFAULT_PORT_TOKEN, 6) > 0) {
341: int colonIndex = -1;
342: int contextStartIndex = -1;
343:
344: if (location.startsWith("http")) {
345: // look for ${HttpDefaultPort} token
346: colonIndex = location.indexOf(":", 6);
347: contextStartIndex = location.indexOf("/", 7);
348:
349: if (HTTP_DEFAULT_PORT_TOKEN.equals(location.substring(
350: colonIndex + 1, contextStartIndex))) {
351: return;
352: } else {
353: results
354: .add(new Validator.ResultItem(
355: mValidator,
356: Validator.ResultType.ERROR,
357: address,
358: NbBundle
359: .getMessage(
360: SOAPComponentVisitor.class,
361: "SOAPAddressValidator.Unsupported_location_attribute")));
362: return;
363: }
364: }
365: }
366:
367: if (location.indexOf(HTTPS_DEFAULT_PORT_TOKEN, 7) > 0) {
368: int colonIndex = -1;
369: int contextStartIndex = -1;
370:
371: if (location.startsWith("https")) {
372: // look for ${HttpDefaultPort} token
373: colonIndex = location.indexOf(":", 7);
374: contextStartIndex = location.indexOf("/", 8);
375:
376: if (HTTPS_DEFAULT_PORT_TOKEN.equals(location.substring(
377: colonIndex + 1, contextStartIndex))) {
378: return;
379: } else {
380: results
381: .add(new Validator.ResultItem(
382: mValidator,
383: Validator.ResultType.ERROR,
384: address,
385: NbBundle
386: .getMessage(
387: SOAPComponentVisitor.class,
388: "SOAPAddressValidator.Unsupported_location_attribute")));
389: return;
390: }
391: }
392: }
393:
394: if (containsToken(location)) {
395: if (!isValidSoapAddressToken(location)) {
396: results
397: .add(new Validator.ResultItem(
398: mValidator,
399: Validator.ResultType.ERROR,
400: address,
401: NbBundle
402: .getMessage(
403: SOAPComponentVisitor.class,
404: "SOAPAddressValidator.Unsupported_Token_Format")));
405: return;
406: }
407: } else {
408: try {
409: URI uri = new URI(location);
410: String scheme = uri.getScheme();
411: if (!scheme.equalsIgnoreCase("http")
412: && !scheme.equalsIgnoreCase("https")) {
413: return;
414: }
415: URL url = uri.toURL();
416: } catch (Exception ex) {
417: results
418: .add(new Validator.ResultItem(
419: mValidator,
420: Validator.ResultType.ERROR,
421: address,
422: NbBundle
423: .getMessage(
424: SOAPComponentVisitor.class,
425: "SOAPAddressValidator.Unsupported_location_attribute")));
426: }
427: }
428: }
429:
430: public void visit(SOAPBinding binding) {
431: String transportURI = binding.getTransportURI();
432: if (transportURI == null) {
433: results
434: .add(new Validator.ResultItem(
435: mValidator,
436: Validator.ResultType.ERROR,
437: binding,
438: NbBundle
439: .getMessage(
440: SOAPComponentVisitor.class,
441: "SOAPBindingValidator.Transport_URI_required")));
442: } else if (!transportURI
443: .equals("http://schemas.xmlsoap.org/soap/http")) {
444: results
445: .add(new Validator.ResultItem(
446: mValidator,
447: Validator.ResultType.ERROR,
448: binding,
449: NbBundle
450: .getMessage(
451: SOAPComponentVisitor.class,
452: "SOAPBindingValidator.Unsupported_transport")));
453: }
454:
455: try {
456: SOAPBinding.Style style = binding.getStyle();
457: } catch (Throwable th) {
458: results
459: .add(new Validator.ResultItem(
460: mValidator,
461: Validator.ResultType.ERROR,
462: binding,
463: NbBundle
464: .getMessage(
465: SOAPComponentVisitor.class,
466: "SOAPBindingValidator.Unsupported_style_attribute")));
467: }
468: }
469:
470: public void visit(SOAPBody body) {
471: Collection<String> encodingStyles = body.getEncodingStyles();
472: if (encodingStyles != null) {
473: // This is optional. Don't verify contents at this point.
474: }
475:
476: String namespace = body.getNamespace();
477: if (namespace != null) {
478: // This is optional. We should verify that it is a valid URI, but
479: // I don't want to be too restrictive at this point.
480: }
481:
482: try {
483: SOAPMessageBase.Use use = body.getUse();
484: } catch (Throwable th) {
485: results
486: .add(new Validator.ResultItem(
487: mValidator,
488: Validator.ResultType.ERROR,
489: body,
490: NbBundle
491: .getMessage(
492: SOAPComponentVisitor.class,
493: "SOAPBodyValidator.Unsupported_use_attribute")));
494: }
495:
496: List<String> parts = body.getParts();
497: if (parts != null) {
498: // This is optional. Don't verify contents at this point.
499: }
500:
501: // Make sure that the Message definition exists
502: /*
503: WSDLComponent bindingMessage = body.getParent();
504: System.out.println("BindingMessage: " + bindingMessage);
505: if (bindingMessage instanceof BindingInput) {
506: BindingInput bindingInput = (BindingInput)bindingMessage;
507: System.out.println("BindingInput: " + bindingInput);
508: System.out.println("BindingInput Name: "+ bindingInput.getName());
509: System.out.println("Reference: " + bindingInput.getInput());
510: Input abstractInput = bindingInput.getInput().get();
511: if (abstractInput == null) {
512: results.add(
513: new Validator.ResultItem(this,
514: Validator.ResultType.ERROR,
515: components,
516: NbBundle.getMessage(SOAPComponentVisitor.class, "SOAPBodyValidator.No_abstract_message"),
517: ""));
518: }
519: NamedComponentReference<Message> message = abstractInput.getMessage();
520: if (message == null) {
521: results.add(
522: new Validator.ResultItem(this,
523: Validator.ResultType.ERROR,
524: components,
525: NbBundle.getMessage(SOAPComponentVisitor.class, "SOAPBodyValidator.No_abstract_message"),
526: ""));
527: }
528:
529: } else {
530:
531: }
532: */
533: }
534:
535: public void visit(SOAPFault fault) {
536: String name = fault.getName();
537: if (name == null) {
538: results
539: .add(new Validator.ResultItem(mValidator,
540: Validator.ResultType.ERROR, fault,
541: NbBundle.getMessage(
542: SOAPComponentVisitor.class,
543: "SOAPFaultValidator.Missing_name")));
544: }
545:
546: Collection<String> encodingStyles = fault.getEncodingStyles();
547: if (encodingStyles != null) {
548: // This is optional. Don't verify contents at this point.
549: }
550:
551: String namespace = fault.getNamespace();
552: if (namespace != null) {
553: // This is optional. We should verify that it is a valid URI, but
554: // I don't want to be too restrictive at this point.
555: }
556:
557: try {
558: SOAPMessageBase.Use use = fault.getUse();
559: } catch (Throwable th) {
560: results
561: .add(new Validator.ResultItem(
562: mValidator,
563: Validator.ResultType.ERROR,
564: fault,
565: NbBundle
566: .getMessage(
567: SOAPComponentVisitor.class,
568: "SOAPFaultValidator.Unsupported_use_attribute")));
569: }
570: }
571:
572: public void visit(SOAPHeaderFault headerFault) {
573: NamedComponentReference<Message> message = headerFault
574: .getMessage();
575: if (message == null) {
576: results
577: .add(new Validator.ResultItem(
578: mValidator,
579: Validator.ResultType.ERROR,
580: headerFault,
581: NbBundle
582: .getMessage(
583: SOAPComponentVisitor.class,
584: "SOAPHeaderFaultValidator.Missing_header_fault_message")));
585: }
586:
587: String part = headerFault.getPart();
588: if (part == null) {
589: results
590: .add(new Validator.ResultItem(
591: mValidator,
592: Validator.ResultType.ERROR,
593: headerFault,
594: NbBundle
595: .getMessage(
596: SOAPComponentVisitor.class,
597: "SOAPHeaderFaultValidator.Missing_header_fault_part")));
598: }
599:
600: try {
601: SOAPMessageBase.Use use = headerFault.getUse();
602: if (use == null) {
603: results
604: .add(new Validator.ResultItem(
605: mValidator,
606: Validator.ResultType.ERROR,
607: headerFault,
608: NbBundle
609: .getMessage(
610: SOAPComponentVisitor.class,
611: "SOAPHeaderFaultValidator.Missing_header_fault_use")));
612: }
613: } catch (Throwable th) {
614: results
615: .add(new Validator.ResultItem(
616: mValidator,
617: Validator.ResultType.ERROR,
618: headerFault,
619: NbBundle
620: .getMessage(
621: SOAPComponentVisitor.class,
622: "SOAPHeaderFaultValidator.Unsupported_header_fault_use_attribute")));
623: }
624:
625: Collection<String> encodingStyles = headerFault
626: .getEncodingStyles();
627: if (encodingStyles != null) {
628: // This is optional. Don't verify contents at this point.
629: }
630:
631: String namespace = headerFault.getNamespace();
632: if (namespace != null) {
633: // This is optional. We should verify that it is a valid URI, but
634: // I don't want to be too restrictive at this point.
635: }
636:
637: }
638:
639: public void visit(SOAPOperation operation) {
640: String soapActionURI = operation.getSoapAction();
641: if (soapActionURI != null) {
642: // This is fine. The URI can be anything. In reality,
643: // we should verify that this is a valid URI, but I don't want
644: // to be too restrictive.
645: }
646:
647: try {
648: SOAPBinding.Style style = operation.getStyle();
649: } catch (Throwable th) {
650: results
651: .add(new Validator.ResultItem(
652: mValidator,
653: Validator.ResultType.ERROR,
654: operation,
655: NbBundle
656: .getMessage(
657: SOAPComponentVisitor.class,
658: "SOAPOperationValidator.Unsupported_style_attribute")));
659: }
660: }
661:
662: private void visit(BindingInput bindingInput) {
663: Map<MessagePart, SOAPMessageBase> partMap = new HashMap<MessagePart, SOAPMessageBase>();
664:
665: List<SOAPHeader> soapHeaders = bindingInput
666: .getExtensibilityElements(SOAPHeader.class);
667: for (SOAPHeader header : soapHeaders) {
668: header.accept(this );
669: ensureUniqueParts(partMap, header);
670: Collection<SOAPHeaderFault> soapHeaderFaults = header
671: .getSOAPHeaderFaults();
672: for (SOAPHeaderFault fault : soapHeaderFaults) {
673: fault.accept(this );
674: ensureUniqueParts(partMap, fault);
675: }
676: }
677:
678: int numSoapBodies = bindingInput.getExtensibilityElements(
679: SOAPBody.class).size();
680: if (numSoapBodies == 0) {
681: results
682: .add(new Validator.ResultItem(
683: mValidator,
684: Validator.ResultType.ERROR,
685: bindingInput,
686: NbBundle
687: .getMessage(
688: SOAPComponentVisitor.class,
689: "SOAPBodyValidator.Atleast_one_body_Required")));
690:
691: } else if (numSoapBodies > 0 && numSoapBodies != 1) {
692: results
693: .add(new Validator.ResultItem(
694: mValidator,
695: Validator.ResultType.ERROR,
696: bindingInput,
697: NbBundle
698: .getMessage(
699: SOAPComponentVisitor.class,
700: "SOAPBodyValidator.Only_one_body_allowed")));
701: }
702: List<SOAPBody> soapBodies = bindingInput
703: .getExtensibilityElements(SOAPBody.class);
704: for (SOAPBody body : soapBodies) {
705: body.accept(this );
706: ensureUniqueParts(partMap, body, bindingInput);
707: }
708: }
709:
710: private void visit(BindingOutput bindingOutput) {
711: Map<MessagePart, SOAPMessageBase> partMap = new HashMap<MessagePart, SOAPMessageBase>();
712:
713: List<SOAPHeader> soapHeaders = bindingOutput
714: .getExtensibilityElements(SOAPHeader.class);
715: for (SOAPHeader soapHeader : soapHeaders) {
716: soapHeader.accept(this );
717: ensureUniqueParts(partMap, soapHeader);
718: Collection<SOAPHeaderFault> soapHeaderFaults = soapHeader
719: .getSOAPHeaderFaults();
720: for (SOAPHeaderFault fault : soapHeaderFaults) {
721: fault.accept(this );
722: ensureUniqueParts(partMap, fault);
723: }
724: }
725:
726: int numSoapBodies = bindingOutput.getExtensibilityElements(
727: SOAPBody.class).size();
728: if (numSoapBodies == 0) {
729: results
730: .add(new Validator.ResultItem(
731: mValidator,
732: Validator.ResultType.ERROR,
733: bindingOutput,
734: NbBundle
735: .getMessage(
736: SOAPComponentVisitor.class,
737: "SOAPBodyValidator.Atleast_one_body_Required")));
738:
739: } else if (numSoapBodies > 0 && numSoapBodies != 1) {
740:
741: results
742: .add(new Validator.ResultItem(
743: mValidator,
744: Validator.ResultType.ERROR,
745: bindingOutput,
746: NbBundle
747: .getMessage(
748: SOAPComponentVisitor.class,
749: "SOAPBodyValidator.Only_one_body_allowed")));
750: }
751: List<SOAPBody> soapBodies = bindingOutput
752: .getExtensibilityElements(SOAPBody.class);
753: for (SOAPBody body : soapBodies) {
754: body.accept(this );
755: ensureUniqueParts(partMap, body, bindingOutput);
756: }
757: }
758:
759: private void ensureUniqueParts(
760: Map<MessagePart, SOAPMessageBase> partsMap, SOAPBody elem,
761: WSDLComponent parent) {
762:
763: // Obtain the Message definition whose part this SOAPBody element extends
764: OperationParameter param;
765: if (parent instanceof BindingInput) {
766: param = ((BindingInput) parent).getInput().get();
767: } else if (parent instanceof BindingOutput) {
768: param = ((BindingOutput) parent).getOutput().get();
769: } else {
770: throw new IllegalArgumentException(
771: "(Internal error) Unexpected WSDLComponent sub-type "
772: + parent.getClass().getName());
773: }
774:
775: // Let wsdl validator catch undefined message for operation input or output
776: if (param == null || param.getMessage() == null
777: || param.getMessage().get() == null) {
778: return;
779: }
780:
781: Message msg = param.getMessage().get();
782:
783: List<String> partNames = elem.getParts();
784: // If the SOAPBOdy does not explicitly specify a part, assume
785: // it refers to the all the parts.
786: if (partNames == null || partNames.isEmpty()) {
787: Collection<Part> parts = msg.getParts();
788: partNames = new ArrayList<String>(parts.size());
789: for (Part part : parts) {
790: partNames.add(part.getName());
791: }
792: }
793: for (String name : partNames) {
794: if (name != null && !"".equals(name)) {
795: MessagePart msgpart = new MessagePart(msg, name);
796: if (!partsMap.containsKey(msgpart)) {
797: partsMap.put(msgpart, elem);
798: } else {
799: SOAPMessageBase conflictElem = partsMap
800: .get(msgpart);
801: results
802: .add(new Validator.ResultItem(
803: mValidator,
804: Validator.ResultType.ERROR,
805: elem,
806: NbBundle
807: .getMessage(
808: SOAPComponentVisitor.class,
809: "SOAPBodyValidator.Part_already_in_use_by_elem",
810: name,
811: msg.getName(),
812: conflictElem
813: .getQName()
814: .toString())));
815: }
816: }
817: }
818: }
819:
820: private void ensureUniqueParts(
821: Map<MessagePart, SOAPMessageBase> partsMap,
822: SOAPHeaderBase elem) {
823: NamedComponentReference<Message> comp = elem.getMessage();
824:
825: // Let wsdl validator catch undefined message for operation input or output
826: if (elem == null || elem.getMessage() == null
827: || elem.getMessage().get() == null) {
828: return;
829: }
830:
831: Message msg = comp.get();
832: String part = elem.getPart();
833: if (part != null && !"".equals(part)) {
834: MessagePart msgpart = new MessagePart(msg, part);
835: if (!partsMap.containsKey(msgpart)) {
836: partsMap.put(msgpart, elem);
837: } else {
838: SOAPMessageBase conflictElem = partsMap.get(msgpart);
839: results
840: .add(new Validator.ResultItem(
841: mValidator,
842: Validator.ResultType.ERROR,
843: elem,
844: NbBundle
845: .getMessage(
846: SOAPComponentVisitor.class,
847: "SOAPHeaderValidator.Part_already_in_use_by_elem",
848: part, msg.getName(),
849: conflictElem.getQName()
850: .toString())));
851: }
852: }
853: }
854:
855: private List<String> allMessageParts(Message msg) {
856: Collection<Part> parts = msg.getParts();
857: List<String> partNames = new LinkedList<String>();
858: for (Part part : parts) {
859: partNames.add(part.getName());
860: }
861: return partNames;
862: }
863:
864: private boolean containsToken(String val) {
865: if (val.contains("${")) {
866: return true;
867: }
868: return false;
869: }
870:
871: /**
872: * A token string can be of the following format:
873: * 1. http(s)://${host}:${port}/${context}
874: * 2. ${URL}
875: */
876: private boolean isValidSoapAddressToken(String tokenString) {
877: boolean containsProtocolInfo = false;
878: boolean isValidToken = true;
879: if (tokenString.startsWith("http://")) {
880: //strip off the protocol stuff
881: tokenString = tokenString
882: .substring(7, tokenString.length());
883: containsProtocolInfo = true;
884: }
885: if (tokenString.startsWith("https://")) {
886: //strip off the protocol stuff
887: tokenString = tokenString
888: .substring(8, tokenString.length());
889: containsProtocolInfo = true;
890: }
891: //No protocol info, it better be of the format ${URL}
892: if (!containsProtocolInfo) {
893: int indexOfTokenStart = tokenString.indexOf("${");
894: int indexOfTokenEnd = tokenString.indexOf("}");
895: if ((indexOfTokenEnd == tokenString.length() - 1)
896: && (indexOfTokenStart == 0)) {
897: isValidToken = true;
898: } else {
899: return false;
900: }
901: }
902: if (tokenString.contains("${")) {
903: int indexOfPortSeparator = tokenString.indexOf(":");
904: int indexOfContextSeparator = tokenString.lastIndexOf("/");
905:
906: //Context separator / exists.
907: if (indexOfContextSeparator != -1) {
908: //The token is in the context.
909: String context = tokenString.substring(
910: indexOfContextSeparator + 1, tokenString
911: .length());
912: int indexOfContextTokenStart = context.indexOf("${");
913: if (indexOfContextTokenStart == 0) {
914: int indexOfTokenEnd = context.indexOf("}");
915: if (indexOfTokenEnd < indexOfContextTokenStart) {
916: return false;
917: }
918: } else if (context.indexOf("}") > 0) {
919: return false;
920: }
921:
922: int indexOfTokenStart = tokenString.indexOf("${");
923: if (indexOfTokenStart == 0) { //The token is in the host
924: String host = tokenString.substring(1,
925: indexOfPortSeparator);
926: int indexOfTokenEnd = host.indexOf("}");
927: if (indexOfTokenEnd < 1) {
928: return false;
929: }
930: } else if (tokenString.substring(1,
931: indexOfPortSeparator).indexOf("}") > 0) {
932: return false;
933: }
934: String port = tokenString.substring(
935: indexOfPortSeparator + 1,
936: indexOfContextSeparator);
937: if ((port.indexOf("${") != -1)
938: && (port.indexOf("}") > 0)) {
939: isValidToken = true;
940: } else {
941: return false;
942: }
943: }
944: }
945: return isValidToken;
946: }
947: }
|