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