/** * EasySOA Registry * Copyright 2011 Open Wide * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Contact : easysoa-dev@googlegroups.com */ package org.easysoa.sca.frascati; import java.io.File; import java.io.FilenameFilter; import java.lang.management.ManagementFactory; import java.net.URL; import java.net.URLClassLoader; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.management.InstanceNotFoundException; import javax.management.MBeanRegistrationException; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import org.easysoa.frascati.api.FraSCAtiServiceItf; import org.easysoa.frascati.api.FraSCAtiServiceProviderItf; /** * @author jguillemotte * */ public class RemoteFraSCAtiServiceProvider implements FraSCAtiServiceProviderItf { public static final String REMOTE_FRASCATI_LIBRARIES_BASEDIR = "org.easysoa.remote.frascati.libraries.basedir"; private static Logger log = Logger.getLogger( RemoteFraSCAtiServiceProvider.class.getCanonicalName()); private FraSCAtiServiceItf frascatiService; private Object frascati; private UpdatableURLClassLoader icl; private Class<?> componentClass = null; private Class<?> lifecycleClass = null; private Object factory = null; /** * Constructor * * launch a new FraSCAti instance which is not a Nuxeo application * * @param librariesDirectory * the directory where the FraSCAti's libraries are stored * * @throws Exception */ public RemoteFraSCAtiServiceProvider(File librariesDirectory) throws Exception { // Required for Frascati Web explorer // If this property is not set, the following error is throwed '<sca:component name="WebExplorer"> - <sca:implementation> must be defined' // See discussion at https://groups.google.com/forum/#!msg/easysoa-dev/LE66ptRLL3A/kSSzJrIMzMcJ System.setProperty("org.ow2.frascati.bootstrap", "org.ow2.frascati.bootstrap.FraSCAtiWebExplorer"); if(librariesDirectory == null) { String librariesDirectoryProp = System.getProperty( REMOTE_FRASCATI_LIBRARIES_BASEDIR); if(librariesDirectoryProp == null || !(librariesDirectory = new File( librariesDirectoryProp)).exists()) { throw new InstantiationException("Enable to instantiate a new" + " remote FraSCAti instance : no libraries directory found" ); } } File[] libraries = librariesDirectory.listFiles( new FilenameFilter(){ @Override public boolean accept(File arg0, String arg1) { if(arg1.endsWith(".jar")) { return true; } return false; } }); //Define a new URLClassLoader using a parent which allow to find shared classes icl = new UpdatableURLClassLoader(Thread.currentThread().getContextClassLoader()); if(libraries != null) { for(File library : libraries) { icl.addURL(library.toURI().toURL()); } } Class<?> frascatiClass = icl.loadClass("org.ow2.frascati.FraSCAti"); ClassLoader current = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(icl); try { frascati = frascatiClass.getDeclaredMethod("newFraSCAti").invoke(null); // ,new Class<?>[]{ClassLoader.class}).invoke(null, // new Object[]{icl}); } catch(Exception e) { throw e; } finally { Thread.currentThread().setContextClassLoader(current); } Class<?> managerClass = icl.loadClass( "org.ow2.frascati.assembly.factory.api.CompositeManager"); lifecycleClass = icl.loadClass( "org.objectweb.fractal.api.control.LifeCycleController"); componentClass = icl.loadClass( "org.objectweb.fractal.api.Component"); Object manager = frascatiClass.getDeclaredMethod( "getCompositeManager").invoke(frascati); Object component = managerClass.getDeclaredMethod( "getTopLevelDomainComposite").invoke(manager); factory = getComponent(component, "org.ow2.frascati.FraSCAti/assembly-factory"); frascatiService = (FraSCAtiServiceItf) frascatiClass.getDeclaredMethod("getService",new Class<?>[]{ componentClass, String.class, Class.class}) .invoke(frascati, new Object[]{ factory, "easysoa-frascati-service", FraSCAtiServiceItf.class}); } /** * Find a Fractal Component using a parent of it and its path * * @param currentComponent * a parent of the search component * @param componentPath * the path of the component * @return * the component if it has been found. Null otherwise * @throws Exception */ private Object getComponent(Object currentComponent, String componentPath) throws Exception { String[] componentPathElements = componentPath.split("/"); String lookFor = componentPathElements[0]; String next = null; if(componentPathElements.length>1) { int n = 1; StringBuilder nextSB = new StringBuilder(); for(;n<componentPathElements.length;n++) { nextSB.append(componentPathElements[n]); if(n<componentPathElements.length - 1) { nextSB.append("/"); } } next = nextSB.toString(); } Class<?> componentClass = icl.loadClass( "org.objectweb.fractal.api.Component"); Class<?> contentControllerClass = icl.loadClass( "org.objectweb.fractal.api.control.ContentController"); Class<?> nameControllerClass = icl.loadClass( "org.objectweb.fractal.api.control.NameController"); Object contentController = componentClass.getDeclaredMethod( "getFcInterface",new Class<?>[]{String.class}).invoke( currentComponent,"content-controller"); Object[] subComponents = (Object[]) contentControllerClass.getDeclaredMethod( "getFcSubComponents",(Class<?>[])null).invoke( contentController,(Object[])null); if(subComponents == null) { return null; } for(Object o : subComponents) { Object nameController = componentClass.getDeclaredMethod("getFcInterface", new Class<?>[]{String.class}).invoke(o,"name-controller"); String name = (String) nameControllerClass.getDeclaredMethod("getFcName", (Class<?>[])null).invoke(nameController,(Object[])null); if(lookFor.equals(name)) { if(next == null || next.length() ==0) { return o; } else { return getComponent(o,next); } } } return null; } public FraSCAtiServiceItf getFraSCAtiService() { return frascatiService; } /** * @throws Exception * */ public void stopFraSCAtiService() throws Exception { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); ObjectName name; try { name = new ObjectName("SCA domain:name0=*,*"); Set<ObjectName> names = mbs.queryNames(name, name); for (ObjectName objectName : names) { mbs.unregisterMBean(objectName); } mbs.unregisterMBean(new ObjectName( "org.ow2.frascati.jmx:name=FrascatiJmx")); } catch (MalformedObjectNameException e) { // e.printStackTrace(); } catch (NullPointerException e) { // e.printStackTrace(); } catch (MBeanRegistrationException e) { // e.printStackTrace(); } catch (InstanceNotFoundException e) { // e.printStackTrace(); } Object lifeCycleController = componentClass.getDeclaredMethod( "getFcInterface", new Class<?>[]{String.class}).invoke( factory,new Object[]{"lifecycle-controller"}); lifecycleClass.getDeclaredMethod("stopFc").invoke( lifeCycleController); frascatiService = null; frascati = null; icl = null; Runtime.getRuntime().runFinalization(); System.gc(); } /** * An URLClassLoader which allow to use the addURL method */ private class UpdatableURLClassLoader extends URLClassLoader { /** * @param urls * @param parent * @param factory */ public UpdatableURLClassLoader(ClassLoader parent) { super(new URL[0], parent); } /** * @param url */ @Override public void addURL(URL url) { //log.debug("adding url to load : " + url); super.addURL(url); } /** * {@inheritDoc} * * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean) */ protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { // First, check if the class has already been loaded boolean regular = false; Class<?> clazz = findLoadedClass(name); if (clazz != null) { return clazz; } if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("org.w3c.") || name.startsWith("org.apache.log4j")) { regular = true; if (getParent() != null) { try { clazz = getParent().loadClass(name); } catch (ClassNotFoundException e) { log.log(Level.CONFIG, "'" + name + "' class not found using the parent classloader"); } } } if (clazz == null) { try { clazz = findClass(name); } catch (ClassNotFoundException e) { log.log(Level.CONFIG, "'" + name + "' class not found using the classloader classpath"); } if (clazz == null && !regular && getParent() != null) { clazz = getParent().loadClass(name); } } if (clazz == null) { throw new ClassNotFoundException(name); } if (resolve) { resolveClass(clazz); } return clazz; } /** * {@inheritDoc} * * @see java.lang.ClassLoader#getResource(java.lang.String) */ @Override public URL getResource(String name) { URL url = null; boolean regular = false; if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("org.w3c.") || name.startsWith("org.apache.log4j")) { regular = true; if (getParent() != null) { url = getParent().getResource(name); } } if(url == null) { url = findResource(name); } if (url==null && !regular && getParent() != null) { url = getParent().getResource(name); } return url; } } }