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.wsn.component;
018    
019    import java.net.URL;
020    import java.util.ArrayList;
021    import java.util.HashMap;
022    import java.util.List;
023    import java.util.Map;
024    import java.util.Properties;
025    
026    import javax.jbi.servicedesc.ServiceEndpoint;
027    import javax.jms.ConnectionFactory;
028    import javax.naming.Context;
029    import javax.naming.InitialContext;
030    import javax.naming.NamingException;
031    import javax.wsdl.Definition;
032    import javax.wsdl.factory.WSDLFactory;
033    import javax.wsdl.xml.WSDLReader;
034    import javax.wsdl.xml.WSDLLocator;
035    import javax.xml.namespace.QName;
036    
037    import org.w3c.dom.Document;
038    
039    import com.ibm.wsdl.Constants;
040    
041    import org.apache.servicemix.common.BaseServiceUnitManager;
042    import org.apache.servicemix.common.DefaultComponent;
043    import org.apache.servicemix.common.Deployer;
044    import org.apache.servicemix.common.Endpoint;
045    import org.apache.servicemix.common.EndpointSupport;
046    import org.apache.servicemix.common.ServiceUnit;
047    import org.apache.servicemix.common.DefaultServiceUnit;
048    import org.apache.servicemix.common.tools.wsdl.WSDLFlattener;
049    import org.apache.servicemix.wsn.EndpointManager;
050    import org.apache.servicemix.wsn.EndpointRegistrationException;
051    import org.apache.servicemix.wsn.jbi.JbiNotificationBroker;
052    import org.apache.servicemix.wsn.jms.JmsCreatePullPoint;
053    import org.springframework.core.io.Resource;
054    import org.xml.sax.InputSource;
055    
056    public class WSNComponent extends DefaultComponent {
057    
058        private WSDLFlattener flattener;
059    
060        private Map<QName, Document> descriptions;
061    
062        private JbiNotificationBroker notificationBroker;
063    
064        private JmsCreatePullPoint createPullPoint;
065    
066        private WSNConfiguration configuration;
067    
068        private ConnectionFactory connectionFactory;
069    
070        private Resource[] resources;
071    
072        private Object[] requests;
073    
074        private List<Endpoint> endpoints;
075    
076        private WSNDeployer deployer;
077    
078        public WSNComponent() {
079            configuration = new WSNConfiguration();
080            serviceUnit = new DefaultServiceUnit(this);
081        }
082    
083        public JbiNotificationBroker getNotificationBroker() {
084            return notificationBroker;
085        }
086    
087        public JmsCreatePullPoint getCreatePullPoint() {
088            return createPullPoint;
089        }
090    
091        protected Object getExtensionMBean() throws Exception {
092            return configuration;
093        }
094    
095        @Override
096        public BaseServiceUnitManager createServiceUnitManager() {
097            deployer = new WSNDeployer(this);
098            return new BaseServiceUnitManager(this, new Deployer[] {deployer });
099        }
100    
101        public ConnectionFactory getConnectionFactory() {
102            return this.connectionFactory;
103        }
104    
105        public void setConnectionFactory(ConnectionFactory connectionFactory) {
106            this.connectionFactory = connectionFactory;
107        }
108    
109        protected List getConfiguredEndpoints() {
110            return endpoints;
111        }
112    
113        protected Class[] getEndpointClasses() {
114            return new Class[] {
115                WSNEndpoint.class,
116                WSNDeployableEndpoint.class,
117            };
118        }
119    
120        /**
121         * @return Returns the endpoints.
122         */
123        public Resource[] getResources() {
124            return resources;
125        }
126    
127        /**
128         * @param resources The resources to set.
129         */
130        public void setResources(Resource[] resources) {
131            this.resources = resources;
132        }
133    
134        /**
135         * @return Returns the requests.
136         */
137        public Object[] getRequests() {
138            return requests;
139        }
140    
141        /**
142         * @param requests The requests to set.
143         */
144        public void setRequests(Object[] requests) {
145            this.requests = requests;
146        }
147    
148        @Override
149        protected void doInit() throws Exception {
150            configuration.setRootDir(context.getWorkspaceRoot());
151            configuration.load();
152            // Notification Broker
153            notificationBroker = new JbiNotificationBroker(configuration.getBrokerName());
154            notificationBroker.setManager(new WSNEndpointManager());
155            if (connectionFactory == null) {
156                connectionFactory = lookupConnectionFactory();
157            }
158            notificationBroker.setConnectionFactory(connectionFactory);
159            notificationBroker.init();
160            // Create PullPoint
161            createPullPoint = new JmsCreatePullPoint(configuration.getBrokerName());
162            createPullPoint.setManager(new WSNEndpointManager());
163            if (connectionFactory == null) {
164                connectionFactory = lookupConnectionFactory();
165            }
166            createPullPoint.setConnectionFactory(connectionFactory);
167            createPullPoint.init();
168            // Create endpoints
169            endpoints = new ArrayList<Endpoint>();
170            if (resources != null) {
171                for (int i = 0; i < resources.length; i++) {
172                    Endpoint ep = deployer.createEndpoint(resources[i].getURL());
173                    endpoints.add(ep);
174                }
175            }
176            if (requests != null) {
177                for (int i = 0; i < requests.length; i++) {
178                    Endpoint ep = deployer.createEndpoint(requests[i]);
179                    endpoints.add(ep);
180                }
181            }
182            super.doInit();
183        }
184    
185        @Override
186        protected void doShutDown() throws Exception {
187            notificationBroker.destroy();
188            createPullPoint.destroy();
189            super.doShutDown();
190        }
191    
192        /*
193         * (non-Javadoc)
194         * 
195         * @see org.apache.servicemix.common.BaseComponent#getServiceDescription(javax.jbi.servicedesc.ServiceEndpoint)
196         */
197        @Override
198        public Document getServiceDescription(ServiceEndpoint endpoint) {
199            if (logger.isDebugEnabled()) {
200                logger.debug("Querying service description for " + endpoint);
201            }
202            String key = EndpointSupport.getKey(endpoint);
203            Endpoint ep = this.registry.getEndpoint(key);
204            if (ep != null) {
205                QName interfaceName = ep.getInterfaceName();
206                if (interfaceName == null) {
207                    if (logger.isDebugEnabled()) {
208                        logger.debug("Could not retrieve description for endpoint " + key + " (no interface defined)");
209                    }
210                    return null;
211                }
212                return getDescription(interfaceName);
213            } else {
214                if (logger.isDebugEnabled()) {
215                    logger.debug("No endpoint found for " + key);
216                }
217                return null;
218            }
219        }
220    
221        private synchronized Document getDescription(QName interfaceName) {
222            try {
223                if (descriptions == null) {
224                    descriptions = new HashMap<QName, Document>();
225                }
226                Document doc = descriptions.get(interfaceName);
227                if (doc == null) {
228                    if (flattener == null) {
229                        final URL resource = getClass().getClassLoader().getResource("org/apache/servicemix/wsn/wsn.wsdl");
230                        WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
231                        reader.setFeature(Constants.FEATURE_VERBOSE, false);
232                        // Do not let wsdl4j read imports, as it uses the URL getContent() which fails because wsdl
233                        // is not a known extension in OSGi
234                        Definition definition = reader.readWSDL(new WSDLLocator() {
235                            private String last = null;
236                            public InputSource getBaseInputSource() {
237                                return new InputSource(resource.toString());
238                            }
239                            public InputSource getImportInputSource(String parentLocation, String importLocation) {
240                                int idx = parentLocation.lastIndexOf('/');
241                                last = parentLocation.substring(0, idx + 1) + importLocation;
242                                return new InputSource(last);
243                            }
244                            public String getBaseURI() {
245                                return resource.toString();
246                            }
247                            public String getLatestImportURI() {
248                                return last;
249                            }
250                            public void close() {
251                            }
252                        });
253                        flattener = new WSDLFlattener(definition);
254                    }
255                    Definition flatDef = flattener.getDefinition(interfaceName);
256                    doc = WSDLFactory.newInstance().newWSDLWriter().getDocument(flatDef);
257                    descriptions.put(interfaceName, doc);
258                }
259                return doc;
260            } catch (Exception e) {
261                if (logger.isDebugEnabled()) {
262                    logger.debug("Error retrieving endpoint description", e);
263                }
264                return null;
265            }
266        }
267    
268        protected ConnectionFactory lookupConnectionFactory() throws NamingException {
269            Properties props = new Properties();
270            if (configuration.getInitialContextFactory() != null && configuration.getJndiProviderURL() != null) {
271                props.put(Context.INITIAL_CONTEXT_FACTORY, configuration.getInitialContextFactory());
272                props.put(Context.PROVIDER_URL, configuration.getJndiProviderURL());
273            }
274            InitialContext ctx = new InitialContext(props);
275            return (ConnectionFactory) ctx.lookup(configuration.getJndiConnectionFactoryName());
276        }
277    
278        public class WSNEndpointManager implements EndpointManager {
279    
280            public Object register(String address, Object service) throws EndpointRegistrationException {
281                try {
282                    WSNEndpoint endpoint = new WSNEndpoint(address, service);
283                    WSNComponent.this.addEndpoint(endpoint);
284                    return endpoint;
285                } catch (Exception e) {
286                    throw new EndpointRegistrationException("Unable to activate endpoint", e);
287                }
288            }
289    
290            public void unregister(final Object endpoint) throws EndpointRegistrationException {
291                WSNComponent.this.getExecutor().execute(new Runnable() {
292                    public void run() {
293                        try {
294                            Endpoint ep = (Endpoint) endpoint;
295                            WSNComponent.this.removeEndpoint(ep);
296                        } catch (Exception e) {
297                            logger.error("Unable to deactivate endpoint", e);
298                        }
299                    }
300                });
301            }
302    
303        }
304    
305    }