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.common.wsdl1;
018    
019    import org.apache.servicemix.common.AbstractDeployer;
020    import org.apache.servicemix.common.ServiceMixComponent;
021    import org.apache.servicemix.common.ServiceUnit;
022    import org.apache.servicemix.common.DefaultServiceUnit;
023    import org.apache.servicemix.common.endpoints.AbstractEndpoint;
024    
025    import org.w3c.dom.Document;
026    
027    import javax.jbi.management.DeploymentException;
028    import javax.wsdl.Binding;
029    import javax.wsdl.Definition;
030    import javax.wsdl.Port;
031    import javax.wsdl.Service;
032    import javax.wsdl.WSDLException;
033    import javax.wsdl.extensions.ExtensibilityElement;
034    import javax.wsdl.extensions.ExtensionRegistry;
035    import javax.wsdl.factory.WSDLFactory;
036    import javax.wsdl.xml.WSDLReader;
037    import javax.xml.parsers.DocumentBuilderFactory;
038    
039    import java.io.File;
040    import java.io.FilenameFilter;
041    import java.util.Iterator;
042    import java.util.Map;
043    
044    public abstract class AbstractWsdl1Deployer extends AbstractDeployer {
045    
046        protected FilenameFilter filter;
047        
048        public AbstractWsdl1Deployer(ServiceMixComponent component) {
049            super(component);
050            filter = new WsdlFilter();
051        }
052    
053        /* (non-Javadoc)
054         * @see org.apache.servicemix.common.Deployer#canDeploy(java.lang.String, java.lang.String)
055         */
056        public boolean canDeploy(String serviceUnitName, 
057                                 String serviceUnitRootPath) {
058            File[] wsdls = new File(serviceUnitRootPath).listFiles(filter);
059            return wsdls != null && wsdls.length > 0;
060        }
061        
062        /* (non-Javadoc)
063         * @see org.apache.servicemix.common.Deployer#deploy(java.lang.String, java.lang.String)
064         */
065        public ServiceUnit deploy(String serviceUnitName, 
066                                  String serviceUnitRootPath) throws DeploymentException {
067            File[] wsdls = new File(serviceUnitRootPath).listFiles(filter);
068            if (wsdls == null || wsdls.length == 0) {
069                throw failure("deploy", "No wsdl found", null);
070            }
071            ServiceUnit su = createServiceUnit(serviceUnitName, serviceUnitRootPath);
072            for (int i = 0; i < wsdls.length; i++) {
073                initFromWsdl(su, wsdls[i]);
074            }
075            if (su.getEndpoints().size() == 0) {
076                throw failure("deploy", "Invalid wsdl: no endpoints found", null);
077            }
078            return su;
079        }
080        
081        protected void initFromWsdl(ServiceUnit su, File wsdl) throws DeploymentException {
082            Document description;
083            Definition definition;
084            try {
085                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
086                factory.setNamespaceAware(true);
087                description = factory.newDocumentBuilder().parse(wsdl);
088                definition = createWsdlReader().readWSDL(null, description);
089            } catch (Exception e) {
090                throw failure("deploy", "Could not parse " + wsdl, e);
091            }
092            Map services = definition.getServices();
093            if (services.size() == 0) {
094                failure("deploy", "Invalid wsdl " + wsdl + ": no defined services", null);
095            }
096            for (Iterator itSvc = services.values().iterator(); itSvc.hasNext();) {
097                Service svc = (Service) itSvc.next();
098                for (Iterator itPorts = svc.getPorts().values().iterator(); itPorts.hasNext();) {
099                    JbiEndpoint jbiEndpoint = null;
100                    Port port = (Port) itPorts.next();
101                    ExtensibilityElement portElement = null;
102                    for (Iterator itElems = port.getExtensibilityElements().iterator(); itElems.hasNext();) {
103                        ExtensibilityElement elem = (ExtensibilityElement) itElems.next();
104                        if (elem instanceof JbiEndpoint) {
105                            jbiEndpoint = (JbiEndpoint) elem;
106                        } else if (filterPortElement(elem)) {
107                            if (portElement == null) {
108                                portElement = elem;
109                            } else {
110                                throw failure("deploy", "Invalid wsdl " + wsdl + ": more than one port element match", null);
111                            }
112                        }
113                    }
114                    if (portElement != null) {
115                        Binding binding = port.getBinding();
116                        ExtensibilityElement bindingElement = null;
117                        for (Iterator itElems = binding.getExtensibilityElements().iterator(); itElems.hasNext();) {
118                            ExtensibilityElement elem = (ExtensibilityElement) itElems.next();
119                            if (filterBindingElement(elem)) {
120                                if (bindingElement == null) {
121                                    bindingElement = elem;
122                                } else {
123                                    throw failure("deploy", "Invalid wsdl " + wsdl + ": more than one binding element match", null);
124                                }
125                            }
126                        }
127                        if (bindingElement == null) {
128                            throw failure("deploy", "Invalid wsdl " + wsdl + ": no matching binding element found", null);
129                        }
130                        AbstractEndpoint ep = createEndpoint(portElement, bindingElement, jbiEndpoint);
131                        if (ep != null) {
132                            ep.setServiceUnit(su);
133                            ep.setDescription(description);
134                            ep.setDefinition(definition);
135                            ep.setService(svc.getQName());
136                            ep.setEndpoint(port.getName());
137                            ep.setInterfaceName(binding.getPortType().getQName());
138                            validate(ep);
139                            su.addEndpoint(ep);
140                        }
141                    }
142                }
143            }
144        }    
145        
146        protected WSDLReader createWsdlReader() throws WSDLException {
147            WSDLFactory factory = WSDLFactory.newInstance();
148            ExtensionRegistry registry = factory.newPopulatedExtensionRegistry();
149            registerExtensions(registry);
150            WSDLReader reader = factory.newWSDLReader();
151            reader.setFeature("javax.wsdl.verbose", false);
152            reader.setExtensionRegistry(registry);
153            return reader;
154        }
155        
156        protected void registerExtensions(ExtensionRegistry registry) {
157            JbiExtension.register(registry);
158        }
159    
160        protected ServiceUnit createServiceUnit(String name, String rootPath) {
161            DefaultServiceUnit su = new DefaultServiceUnit();
162            su.setComponent(component);
163            su.setName(name);
164            su.setRootPath(rootPath);
165            return su;
166        }
167        
168        protected abstract AbstractEndpoint createEndpoint(ExtensibilityElement portElement,
169                                                   ExtensibilityElement bindingElement,
170                                                   JbiEndpoint jbiEndpoint);
171        
172        protected abstract boolean filterPortElement(ExtensibilityElement element);
173        
174        protected abstract boolean filterBindingElement(ExtensibilityElement element);
175        
176        public static class WsdlFilter implements FilenameFilter {
177    
178            public boolean accept(File dir, String name) {
179                return name.endsWith(".wsdl");
180            }
181            
182        }
183        
184    }