org.eclipse.smila.webservice.WebservicePublisher.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.smila.webservice.WebservicePublisher.java

Source

/*******************************************************************************
 * 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.");
        }
    }
}