/* * Copyright (c) 2003-2004, KNOPFLERFISH project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above/* * Copyright (c) 2003-2004, KNOPFLERFISH project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * - Neither the name of the KNOPFLERFISH project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.knopflerfish.bundle.axis; import java.io.InputStream; import java.net.URL; import org.apache.axis.EngineConfiguration; import org.apache.axis.configuration.FileProvider; import org.apache.axis.server.AxisServer; import org.apache.axis.utils.XMLUtils; //import org.apache.axis.WSDDEngineConfiguration; import org.knopflerfish.service.log.LogRef; import org.knopflerfish.axis.ObjectSOAPService; import org.knopflerfish.util.servlet.ServletDescriptor; import org.knopflerfish.util.servlet.WebApp; import org.knopflerfish.util.servlet.WebAppDescriptor; import org.osgi.framework.*; import java.util.Map; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import org.knopflerfish.service.axis.AxisAdmin; /** The Activator is the activator for the Axis OSGi bundle. * Further it handles service registration events for SOAP services. * @author Lasse Helander (lars-erik.helander@home.se) */ public class Activator implements BundleActivator, ServiceListener { public static BundleContext axisBundle = null; public static LogRef log = null; private static AxisServer axisServer = null; private WebApp webApp = null; private AxisAdminImpl axisAdmin; public static AxisServer getAxisServer() { return axisServer; } public void start(BundleContext bc) throws BundleException { try { log = new LogRef(bc, true); axisBundle = bc; setupAxis(); } catch (Exception e) { log.error("Exception when starting bundle", e); throw new BundleException("Failed to start server"); } } void setupAxis() throws Exception { ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(Activator.class.getClassLoader()); URL url = this.getClass().getResource("/axis/server-config.wsdd"); InputStream is = url.openStream(); EngineConfiguration fromBundleResource = new FileProvider(is); log.info("Configuration file read."); axisServer = new AxisServer(fromBundleResource); log.info("Axis server started."); webApp = new WebApp(getWebAppDescriptor()); webApp.start(axisBundle); log.info("Web application started."); axisBundle.addServiceListener(this); // Make sure we get services already registered ServiceReference[] srl = axisBundle.getServiceReferences(null, null); for(int i = 0; srl != null && i < srl.length; i++) { serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, srl[i])); } axisAdmin = new AxisAdminImpl(this); Hashtable props = new Hashtable(); props.put(AxisAdmin.SOAP_SERVICE_NAME, "axisadmin"); axisBundle.registerService(AxisAdmin.class.getName(), axisAdmin, props); } finally { Thread.currentThread().setContextClassLoader(oldLoader); } } public void stop(BundleContext bc) throws BundleException { try { axisBundle.removeServiceListener(this); webApp.stop(bc); webApp = null; axisBundle = null; axisServer = null; log.close(); log = null; } catch (Exception e) { log.error("Exception when stopping bundle", e); throw new BundleException("Failed to stop server", e); } } private WebAppDescriptor getWebAppDescriptor() { WebAppDescriptor wad = new WebAppDescriptor(); wad.servlet = new ServletDescriptor[1]; wad.context = "/axis"; wad.servlet[0] = new ServletDescriptor("/services", new ServicesServlet()); return wad; } Map exportedServices = new HashMap(); public void serviceChanged(ServiceEvent event) { try { switch(event.getType()) { case ServiceEvent.REGISTERED: { ServiceReference sr = event.getServiceReference(); String serviceName = (String) sr.getProperty(AxisAdmin.SOAP_SERVICE_NAME); String[] classes = (String[]) sr.getProperty(Constants.OBJECTCLASS); String allowedMethods = (String) sr.getProperty(AxisAdmin.SOAP_SERVICE_METHODS); if (serviceName != null) { log.info("added service "+serviceName); // throws excpetion if name is invalid assertServiceName(serviceName); Object serviceObj = axisBundle.getService(sr); getAxisServer().getClassCache() .registerClass(serviceObj.getClass().getName(), serviceObj.getClass()); ObjectSOAPService soapService = new ObjectSOAPService(axisServer,serviceName,serviceObj, classes, allowedMethods); soapService.deploy(); exportedServices.put(sr, soapService); } } break; case ServiceEvent.UNREGISTERING: { ServiceReference sr = event.getServiceReference(); String serviceName = (String) sr.getProperty(AxisAdmin.SOAP_SERVICE_NAME); if (serviceName != null) { ObjectSOAPService soapService = (ObjectSOAPService)exportedServices.get(sr); if(soapService != null) { Object serviceObj = soapService.getServiceObject(); getAxisServer().getClassCache() .deregisterClass(soapService.getClass().getName()); soapService.undeploy(); log.info("removed service "+serviceName); exportedServices.remove(sr); } // (new ObjectSOAPService(axisServer,serviceName,null)).undeploy(); } } break; } } catch (Exception e) { log.error("serviceChanged() failed", e); } } /** * Check if service name is OK for publishing as SOAP service. * * This incluced checking for previous registrations at the same name. * * @throws IllegalArgumentException if name is not valid */ void assertServiceName(String serviceName) { if(serviceName == null) { throw new IllegalArgumentException("Service name cannot be null"); } if("".equals(serviceName)) { throw new IllegalArgumentException("Service name cannot be empty string"); } for(int i = 0; i < serviceName.length(); i++) { if(Character.isWhitespace(serviceName.charAt(i))) { throw new IllegalArgumentException("Service name '" + serviceName + "' cannot contain whitespace"); } } synchronized(exportedServices) { for(Iterator it = exportedServices.keySet().iterator(); it.hasNext();) { ServiceReference sr = (ServiceReference)it.next(); String name = (String)sr.getProperty(AxisAdmin.SOAP_SERVICE_NAME); // Object serviceObj = (String)exportedServices.get(sr); if(name.equals(serviceName)) { throw new IllegalArgumentException("Service '" + name + "' is already exported"); } } } } }