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     */
017    package org.apache.servicemix.soap.wsdl;
018    
019    import java.net.URI;
020    import java.util.Arrays;
021    import java.util.HashSet;
022    
023    import org.apache.servicemix.soap.api.model.Binding;
024    import org.apache.servicemix.soap.api.model.wsdl2.Wsdl2Message.ContentModel;
025    import org.apache.servicemix.soap.bindings.http.impl.Wsdl2HttpBindingImpl;
026    import org.apache.servicemix.soap.bindings.http.impl.Wsdl2HttpHeaderImpl;
027    import org.apache.servicemix.soap.bindings.http.impl.Wsdl2HttpMessageImpl;
028    import org.apache.servicemix.soap.bindings.http.impl.Wsdl2HttpOperationImpl;
029    import org.apache.woden.internal.wsdl20.Constants;
030    import org.apache.woden.internal.wsdl20.extensions.http.HTTPConstants;
031    import org.apache.woden.wsdl20.BindingMessageReference;
032    import org.apache.woden.wsdl20.BindingOperation;
033    import org.apache.woden.wsdl20.Endpoint;
034    import org.apache.woden.wsdl20.Interface;
035    import org.apache.woden.wsdl20.InterfaceFault;
036    import org.apache.woden.wsdl20.InterfaceFaultReference;
037    import org.apache.woden.wsdl20.InterfaceMessageReference;
038    import org.apache.woden.wsdl20.InterfaceOperation;
039    import org.apache.woden.wsdl20.enumeration.Direction;
040    import org.apache.woden.wsdl20.extensions.ComponentExtensions;
041    import org.apache.woden.wsdl20.extensions.http.HTTPBindingMessageReferenceExtensions;
042    import org.apache.woden.wsdl20.extensions.http.HTTPBindingOperationExtensions;
043    import org.apache.woden.wsdl20.extensions.http.HTTPHeader;
044    import org.apache.woden.xml.XMLAttr;
045    import org.apache.ws.commons.schema.XmlSchemaElement;
046    
047    public class Wsdl2BindingFactory {
048    
049        public static URI HTTP_BINDING_TYPE = URI.create("http://www.w3.org/2006/01/wsdl/http");
050        public static URI XSD_2001_SYSTEM = URI.create(Constants.TYPE_XSD_2001);
051        
052        public static Binding<?> createBinding(Endpoint wsdlEndpoint) {
053            if (HTTP_BINDING_TYPE.equals(wsdlEndpoint.getBinding().getType())) {
054                return createWsdl2HttpBinding(wsdlEndpoint);
055            }
056            return null;
057        }
058    
059        private static Binding<?> createWsdl2HttpBinding(Endpoint wsdlEndpoint) {
060            Wsdl2HttpBindingImpl binding = new Wsdl2HttpBindingImpl();
061            binding.setLocation(wsdlEndpoint.getAddress().toString());
062            Interface wsdlInterface = wsdlEndpoint.getBinding().getInterface();
063            InterfaceOperation[] wsdlOperations = wsdlInterface.getInterfaceOperations();
064            for (int i = 0; i < wsdlOperations.length; i++) {
065                // Retrieve binding and extension
066                InterfaceOperation wsdlOperation = wsdlOperations[i];
067                BindingOperation wsdlBindingOperation = findBindingOperation(wsdlEndpoint.getBinding(), wsdlOperation);
068                HTTPBindingOperationExtensions opExt = wsdlBindingOperation != null ? (HTTPBindingOperationExtensions) wsdlBindingOperation.getComponentExtensionsForNamespace(ComponentExtensions.URI_NS_HTTP) : null;
069                // Create operation
070                Wsdl2HttpOperationImpl operation = new Wsdl2HttpOperationImpl();
071                // Standard WSDL2 attributes
072                operation.setName(wsdlOperation.getName());
073                operation.setMep(wsdlOperation.getMessageExchangePattern());
074                operation.setStyle(new HashSet<URI>(Arrays.asList(wsdlOperation.getStyle())));
075                // HTTP extensions
076                if (opExt != null) {
077                    operation.setHttpInputSerialization(opExt.getHttpInputSerialization());
078                    operation.setHttpOutputSerialization(opExt.getHttpOutputSerialization());
079                    operation.setHttpFaultSerialization(opExt.getHttpFaultSerialization());
080                    operation.setHttpLocation(extractLocation(wsdlBindingOperation));
081                    operation.setHttpMethod(opExt.getHttpMethod());
082                    operation.setHttpTransferCodingDefault(opExt.getHttpTransferCodingDefault());
083                    operation.setHttpLocationIgnoreUncited(opExt.isHttpLocationIgnoreUncited());
084                }
085                // Messages
086                InterfaceMessageReference[] iMsgRefs = wsdlOperation.getInterfaceMessageReferences();
087                for (int j = 0; j < iMsgRefs.length; j++) {
088                    // Retrieve binding and extension
089                    InterfaceMessageReference iMsgRef = iMsgRefs[j];
090                    BindingMessageReference bMsgRef = findBindingMessage(wsdlBindingOperation, iMsgRef);
091                    HTTPBindingMessageReferenceExtensions msgExt = bMsgRef != null ? (HTTPBindingMessageReferenceExtensions) bMsgRef.getComponentExtensionsForNamespace(ComponentExtensions.URI_NS_HTTP) : null;
092                    // Create message
093                    Wsdl2HttpMessageImpl message = new Wsdl2HttpMessageImpl();
094                    // Standard WSDL2 attributes
095                    message.setContentModel(ContentModel.parse(iMsgRef.getMessageContentModel()));
096                    message.setElementName(iMsgRef.getElementDeclaration().getName());
097                    if (!XSD_2001_SYSTEM.equals(iMsgRef.getElementDeclaration().getSystem())) {
098                        throw new IllegalStateException("Unsupported type system: " + iMsgRef.getElementDeclaration().getSystem());
099                    }
100                    if (Constants.API_APACHE_WS_XS.equals(iMsgRef.getElementDeclaration().getContentModel())) {
101                        XmlSchemaElement xsEl = (XmlSchemaElement) iMsgRef.getElementDeclaration().getContent();
102                        message.setElementDeclaration(xsEl);
103                    }
104                    // HTTP extensions
105                    if (msgExt != null) {
106                        message.setHttpTransferCoding(msgExt.getHttpTransferCoding());
107                        HTTPHeader[] headers = msgExt.getHttpHeaders();
108                        for (int k = 0; k < headers.length; k++) {
109                            Wsdl2HttpHeaderImpl h = new Wsdl2HttpHeaderImpl();
110                            h.setName(headers[k].getName());
111                            h.setRequired(headers[k].isRequired() ? headers[k].isRequired().booleanValue() : false);
112                            if (!XSD_2001_SYSTEM.equals(headers[k].getTypeDefinition().getSystem())) {
113                                throw new IllegalStateException("Unsupported type system: " + headers[k].getTypeDefinition().getSystem());
114                            }
115                            h.setType(headers[k].getTypeDefinition().getName());
116                            message.addHttpHeader(h);
117                        }
118                    }
119                    // Add the message
120                    if (iMsgRef.getDirection() == Direction.IN) {
121                        operation.setInput(message);
122                    } else if (iMsgRef.getDirection() == Direction.OUT) {
123                        operation.setOutput(message);
124                    } else {
125                        throw new IllegalStateException("Unsupported message direction: " + iMsgRef.getDirection());
126                    }
127                }
128                // Faults
129                InterfaceFaultReference[] faults = wsdlOperation.getInterfaceFaultReferences();
130                for (int j = 0; j < faults.length; j++) {
131                    // TODO: handle interface faults references
132                }
133                // Add the operation
134                binding.addOperation(operation);
135            }
136            // Faults
137            InterfaceFault[] faults = wsdlInterface.getInterfaceFaults();
138            for (int i = 0; i < faults.length; i++) {
139                // TODO: handle interface faults
140            }
141            // Return the complete binding
142            return binding;
143        }
144        
145        private static BindingMessageReference findBindingMessage(BindingOperation wsdlBindingOperation, InterfaceMessageReference iMsgRef) {
146            BindingMessageReference[] bMsgRefs = wsdlBindingOperation.getBindingMessageReferences();
147            for (int i = 0; i < bMsgRefs.length; i++) {
148                if (bMsgRefs[i].getInterfaceMessageReference() == iMsgRef) {
149                    return bMsgRefs[i];
150                }
151            }
152            return null;
153        }
154    
155        private static BindingOperation findBindingOperation(org.apache.woden.wsdl20.Binding binding, InterfaceOperation operation) {
156            BindingOperation[] bindingOps = binding.getBindingOperations();
157            for (int i = 0; i < bindingOps.length; i++) {
158                if (bindingOps[i].getInterfaceOperation() == operation) {
159                    return bindingOps[i];
160                }
161            }
162            return null;
163        }
164    
165        private static String extractLocation(BindingOperation bOperation) {
166            String location = null;
167            if (bOperation != null) {
168                XMLAttr attr = bOperation.toElement().getExtensionAttribute(HTTPConstants.Q_ATTR_LOCATION);
169                if (attr != null) {
170                    location = attr.toExternalForm();
171                }
172            }
173            return location;
174        }
175    }