blob: d2336522b29f508f0c1f112842b5c60039fabc90 [file] [log] [blame]
/*******************************************************************************
* 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.");
}
}
}