| /******************************************************************************* |
| * Copyright (c) 2008, 2009 empolis GmbH and brox IT Solutions GmbH. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Juergen Schumacher (empolis GmbH) - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.smila.webservice; |
| |
| import java.io.InputStream; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import javax.xml.ws.Endpoint; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.eclipse.smila.utils.config.ConfigUtils; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.Filter; |
| import org.osgi.framework.InvalidSyntaxException; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.util.tracker.ServiceTracker; |
| |
| /** |
| * Tracks services with property <code>org.eclipse.smila.ws</code> and tries to publish them as a JAX-WS webservice. The |
| * value of the property gives the webservice name. The publisher does not check if the service implementor is really a |
| * JAX-WS service implementor (i.e. has the correct annotations and such), but leaves this to JAX-WS, so you will get |
| * JAX-WS exceptions when trying to publish services that are not suitable as a webservice. |
| * |
| * Some properties are configured in the configuration file <tt>webservice.properties</tt>. See the bundle for a example |
| * file. |
| * |
| * @author jschumacher |
| * |
| */ |
| public class WebservicePublisher extends ServiceTracker { |
| /** |
| * name of property of tracked services. |
| */ |
| public static final String PROP_WEBSERVICENAME = "org.eclipse.smila.ws"; |
| |
| /** |
| * filename of my config file. |
| */ |
| public static final String PROPERTY_FILENAME = "webservice.properties"; |
| |
| /** |
| * map of webservice names to the service references. |
| */ |
| private final Map<String, ServiceReference> _references = new HashMap<String, ServiceReference>(); |
| |
| /** |
| * map of webservice names to published endpoints. |
| */ |
| private final Map<String, Endpoint> _endpoints = new HashMap<String, Endpoint>(); |
| |
| /** |
| * configuration properties read from config file <code>webservice.properties</code>, or defaults. |
| */ |
| private WebserviceProperties _properties; |
| |
| /** |
| * local logger. |
| */ |
| private final Log _log = LogFactory.getLog(getClass()); |
| |
| /** |
| * create instance. |
| * |
| * @param bundleContext |
| * bundle context. |
| */ |
| public WebservicePublisher(final BundleContext bundleContext) { |
| super(bundleContext, createFilter(bundleContext), null); |
| } |
| |
| /** |
| * create the filter for a service tracker that tracks all services with the property |
| * <code>org.eclipse.smila.ws</code> set. |
| * |
| * @param bundleContext |
| * bundle context. |
| * @return a filter for <code>org.eclipse.smila.ws=*</code> |
| */ |
| private static Filter createFilter(final BundleContext bundleContext) { |
| try { |
| return bundleContext.createFilter("(" + PROP_WEBSERVICENAME + "=*)"); |
| } catch (final InvalidSyntaxException e) { |
| throw new RuntimeException("should not happen"); |
| } |
| } |
| |
| /** |
| * start the service tracker, read the configuration. |
| */ |
| @Override |
| public void open() { |
| try { |
| final InputStream stream = ConfigUtils.getConfigStream(Activator.BUNDLE_ID, PROPERTY_FILENAME); |
| _properties = new WebserviceProperties(stream); |
| stream.close(); |
| } catch (final Exception ex) { |
| _log.error("Error reading webservice.properties, using defaults."); |
| _properties = new WebserviceProperties(); |
| } |
| super.open(); |
| } |
| |
| /** |
| * stop the service tracker, stop all published webservices, clean up. |
| */ |
| @Override |
| public void close() { |
| super.close(); |
| for (final Endpoint endpoint : _endpoints.values()) { |
| try { |
| endpoint.stop(); |
| } catch (final RuntimeException ex) { |
| _log.warn("error while shutting down", ex); |
| } |
| } |
| _endpoints.clear(); |
| _references.clear(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Object addingService(final ServiceReference reference) { |
| final Object implementor = super.addingService(reference); |
| publishWebservice(reference, implementor); |
| return implementor; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void removedService(final ServiceReference reference, final Object service) { |
| super.removedService(reference, service); |
| stopWebservice(reference); |
| } |
| |
| /** |
| * publish a webservice for a tracked service. |
| * |
| * @param reference |
| * service reference for added service. |
| * @param implementor |
| * service implementor. |
| */ |
| public void publishWebservice(final ServiceReference reference, final Object implementor) { |
| final String name = reference.getProperty(PROP_WEBSERVICENAME).toString(); |
| if (_endpoints.containsKey(name)) { |
| _log.warn("Already have registered a Webservice endpoint with name " + name + ", ignoring new service."); |
| } else { |
| final ClassLoader tccl = Thread.currentThread().getContextClassLoader(); |
| Thread.currentThread().setContextClassLoader(implementor.getClass().getClassLoader()); |
| try { |
| _log.debug("Creating endpoint for webservice " + name); |
| final Endpoint ep = Endpoint.create(implementor); |
| if (ep != null) { |
| final String url = _properties.getBaseURL() + name; |
| _log.debug("Publishing webservice " + name + " at " + url); |
| ep.publish(url); |
| _endpoints.put(name, ep); |
| _references.put(name, reference); |
| _log.info("Webservice successfully published: " + url); |
| } |
| } catch (final Throwable ex) { |
| _log.error("Error publishing webservice " + name, ex); |
| } finally { |
| Thread.currentThread().setContextClassLoader(tccl); |
| } |
| } |
| } |
| |
| /** |
| * stop a published webservice. |
| * |
| * @param reference |
| * service reference for deactivated service. |
| */ |
| public void stopWebservice(final ServiceReference reference) { |
| final String name = reference.getProperty(PROP_WEBSERVICENAME).toString(); |
| final ServiceReference publishedRef = _references.get(name); |
| if (reference.equals(publishedRef)) { |
| try { |
| final Endpoint ep = _endpoints.get(name); |
| if (ep != null) { |
| _log.debug("Stopping webservice " + name); |
| ep.stop(); |
| _endpoints.remove(name); |
| _references.remove(name); |
| _log.info("Webservice " + name + " successfully stopped."); |
| } |
| } catch (final Throwable ex) { |
| _log.error("Error stopping webservice " + name, ex); |
| } |
| } else { |
| _log.warn("Service reference for webservice " + name + " differs from removed reference, ignoring event."); |
| } |
| } |
| } |