001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.openejb.server.webservices;
017:
018: import org.apache.openejb.config.ValidationContext;
019: import org.apache.openejb.config.ValidationFailure;
020: import org.apache.openejb.config.DeploymentModule;
021:
022: import javax.wsdl.Binding;
023: import javax.wsdl.BindingFault;
024: import javax.wsdl.BindingInput;
025: import javax.wsdl.BindingOutput;
026: import javax.wsdl.Definition;
027: import javax.wsdl.Fault;
028: import javax.wsdl.Operation;
029: import javax.wsdl.Output;
030: import javax.wsdl.Part;
031: import javax.wsdl.Service;
032: import javax.wsdl.extensions.soap.SOAPBinding;
033: import javax.wsdl.extensions.soap.SOAPBody;
034: import javax.xml.namespace.QName;
035: import java.util.ArrayList;
036: import java.util.Map;
037: import java.util.List;
038:
039: public class LightWeightMappingValidator extends WsdlVisitor {
040: private static final QName XSD_STRING = new QName(
041: "http://www.w3.org/2001/XMLSchema", "string");
042:
043: private List<String> operationNames;
044: private ValidationContext context;
045: private Class<? extends DeploymentModule> moduleType;
046:
047: public LightWeightMappingValidator(Definition definition,
048: Class<? extends DeploymentModule> moduleType) {
049: super (definition);
050: this .moduleType = moduleType;
051: }
052:
053: public ValidationContext validate() {
054: if (context == null) {
055: context = new ValidationContext(moduleType, definition
056: .getQName().toString());
057: walkTree();
058: }
059: return context;
060: }
061:
062: public boolean isValid() {
063: ValidationContext context = validate();
064: return !context.hasFailures() && !context.hasErrors();
065: }
066:
067: protected void begin() {
068: operationNames = new ArrayList<String>();
069: }
070:
071: protected void visit(Definition definition) {
072: if (definition.getServices().values().size() != 1) {
073: context
074: .addFailure(new ValidationFailure(
075: "A lightweight RPC/Encoded service must contain only one Service"));
076: }
077: }
078:
079: protected void visit(Output output) {
080: Map outputParts = output.getMessage().getParts();
081: if (outputParts.size() != 0 && outputParts.size() != 1) {
082: context.addFailure(new ValidationFailure(
083: "The output message must contain zero or one parts: "
084: + output.getName()));
085: }
086:
087: }
088:
089: protected void visit(Operation operation) {
090: if (!operationNames.add(operation.getName())) {
091: context.addFailure(new ValidationFailure(
092: "No two operations can have the same name: "
093: + operation.getName()));
094: }
095: }
096:
097: protected void visit(Fault fault) {
098: Part message = fault.getMessage().getPart("message");
099: if (message == null) {
100: context.addFailure(new ValidationFailure(
101: "The fault message must contain one part named 'message' : "
102: + fault.getName()));
103: } else if (!XSD_STRING.equals(message.getTypeName())) {
104: context.addFailure(new ValidationFailure(
105: "The fault message must contain one part of type 'xsd:string' : "
106: + fault.getName()));
107: }
108: }
109:
110: protected void visit(BindingInput bindingInput) {
111: SOAPBody body = getSOAPBody(bindingInput
112: .getExtensibilityElements());
113: String encoding = body.getUse();
114: if (encoding == null || !encoding.equals("encoded")) {
115: context.addFailure(new ValidationFailure(
116: "The use attribute of the binding input operation must be 'encoded': "
117: + bindingInput.getName()));
118: }
119: }
120:
121: protected void visit(BindingOutput bindingOutput) {
122: SOAPBody body = getSOAPBody(bindingOutput
123: .getExtensibilityElements());
124: String encoding = body.getUse();
125: if (encoding == null || !encoding.equals("encoded")) {
126: context.addFailure(new ValidationFailure(
127: "The use attribute of the binding output operation must be 'encoded': "
128: + bindingOutput.getName()));
129: }
130: }
131:
132: protected void visit(BindingFault bindingFault) {
133: SOAPBody body = getSOAPBody(bindingFault
134: .getExtensibilityElements());
135: String encoding = body.getUse();
136: if (encoding == null || !encoding.equals("encoded")) {
137: context.addFailure(new ValidationFailure(
138: "The use attribute of the binding fault operation must be 'encoded': "
139: + bindingFault.getName()));
140: }
141: }
142:
143: protected void visit(Binding binding) {
144: SOAPBinding soapBinding = getSOAPBinding(binding);
145: if (soapBinding == null || soapBinding.getStyle() == null
146: || !soapBinding.getStyle().equals("rpc")) {
147: context.addFailure(new ValidationFailure(
148: "The messaging style of the binding must be rpc: "
149: + binding.getQName()));
150: }
151: }
152:
153: protected void visit(Service service) {
154: if (service.getPorts().values().size() != 1) {
155: context
156: .addFailure(new ValidationFailure(
157: "A lightweight RPC/Encoded service must contain only one Port"));
158: }
159: }
160: }
|