All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.diirt.util.config.ServiceLoaderOSGiWrapper Maven / Gradle / Ivy

/**
 * Copyright (C) 2010-14 diirt developers. See COPYRIGHT.TXT
 * All rights reserved. Use is subject to license terms. See LICENSE.TXT
 */
package org.diirt.util.config;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * A wrapper for ServiceLoader that works in OSGi as well.
 * 

* OSGi is known to break the ServiceLoader mechanism. Unfortunately, we have * not been able to make the standard based solution based on Ares SPI-Fly work. * Therefore we have created this wrapper that detects whether the class has * been loaded with OSGi. If not, uses the standard ServiceLoader. If so, uses * introspection to access the OSGi framework and replicate the functionality. *

* Note that the implementation on OSGi will not give all the nice debugging * information that the standard ServiceLoader implementation does. It also is * not optimized: makes heavy use of introspection and does not use lazy * initialization. It's essentially a hack to make things to work. * * @author carcassi */ public class ServiceLoaderOSGiWrapper { public static void load(Class serviceClazz, Logger log, Consumer consumer) { log.log(Level.CONFIG, "Fetching {0}s", serviceClazz.getSimpleName()); int count = 0; for (T service : ServiceLoaderOSGiWrapper.load(serviceClazz)) { log.log(Level.CONFIG, "Found {0} ({1})", new Object[] {serviceClazz.getSimpleName(), service.getClass().getSimpleName()}); consumer.accept(service); count++; } log.log(Level.CONFIG, "Found {0} {1}s", new Object[] {count, serviceClazz.getSimpleName()}); } public static Iterable load(Class serviceClazz) { if (isOSGi(serviceClazz)) { return loadOSGi(serviceClazz); } else { return ServiceLoader.load(serviceClazz); } } private static boolean isOSGi(Class serviceClazz) { try { if (osgi.frameworkUtilClass != null && osgi.getBundle(serviceClazz) != null) { return true; } } catch (Exception e) { } return false; } private static List loadOSGi(Class serviceClazz) { // TODO: improve logging Object bundle = osgi.getBundle(serviceClazz); System.out.println("Found bundle " + bundle); osgi.start(bundle); Object bundleContext = osgi.getBundleContext(bundle); Object[] bundles = osgi.getBundles(bundleContext); System.out.println("Found bundle " + bundleContext); System.out.println("Found bundles " + bundles); Map> bundleToServiceClassnamesMap = new HashMap<>(); List providers = new ArrayList<>(); for (Object providerBundle : bundles) { URL url = osgi.getEntry(providerBundle, "META-INF/services/" + serviceClazz.getName()); if (url != null) { System.out.println("Found " + url + " in " + providerBundle); List classnames = readAllLines(url); if (classnames != null) { bundleToServiceClassnamesMap.put(providerBundle, classnames); System.out.println("Providers " + classnames); for (String classname : classnames) { Class providerClass = osgi.loadClass(providerBundle, classname); if (providerClass != null) { try { T provider = serviceClazz.cast(providerClass.newInstance()); System.out.println("Provider instance " + provider); providers.add(provider); } catch (InstantiationException | IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } } return providers; } private static OSGiReflection osgi = new OSGiReflection(); private static class OSGiReflection { private final Class frameworkUtilClass = loadClass("org.osgi.framework.FrameworkUtil"); private final Class bundleClass = loadClass("org.osgi.framework.Bundle"); private final Class bundleContextClass = loadClass("org.osgi.framework.BundleContext"); private final Method getBundleMethod = loadMethod(frameworkUtilClass, "getBundle", Class.class); private final Method startMethod = loadMethod(bundleClass, "start"); private final Method getBundleContextMethod = loadMethod(bundleClass, "getBundleContext"); private final Method getBundlesMethod = loadMethod(bundleContextClass, "getBundles"); private final Method loadClassMethod = loadMethod(bundleClass, "loadClass", String.class); private final Method getEntryMethod = loadMethod(bundleClass, "getEntry", String.class); private final boolean osgiEnabled; public OSGiReflection() { this.osgiEnabled = false; } private Class loadClass(String name) { try { return Class.forName(name); } catch (ClassNotFoundException ex) { return null; } } private Method loadMethod(Class clazz, String name, Class... parameterTypes) { if (clazz == null) { return null; } try { return clazz.getMethod(name, parameterTypes); } catch (NoSuchMethodException | SecurityException ex) { Logger.getLogger(ServiceLoaderOSGiWrapper.class.getName()).log(Level.SEVERE, null, ex); return null; } } private Object getBundle(Object classFromBundle) { try { return getBundleMethod.invoke(null, classFromBundle); } catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { Logger.getLogger(ServiceLoaderOSGiWrapper.class.getName()).log(Level.SEVERE, null, ex); } return null; } private void start(Object bundle) { try { startMethod.invoke(bundle); } catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { Logger.getLogger(ServiceLoaderOSGiWrapper.class.getName()).log(Level.SEVERE, null, ex); } } private Object getBundleContext(Object bundle) { try { return getBundleContextMethod.invoke(bundle); } catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { Logger.getLogger(ServiceLoaderOSGiWrapper.class.getName()).log(Level.SEVERE, null, ex); } return null; } private Object[] getBundles(Object bundleContext) { try { return (Object[]) getBundlesMethod.invoke(bundleContext); } catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { Logger.getLogger(ServiceLoaderOSGiWrapper.class.getName()).log(Level.SEVERE, null, ex); } return null; } private URL getEntry(Object bundle, String name) { try { return (URL) getEntryMethod.invoke(bundle, name); } catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { Logger.getLogger(ServiceLoaderOSGiWrapper.class.getName()).log(Level.SEVERE, null, ex); } return null; } private Class loadClass(Object bundle, String name) { try { return (Class) loadClassMethod.invoke(bundle, name); } catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { Logger.getLogger(ServiceLoaderOSGiWrapper.class.getName()).log(Level.SEVERE, null, ex); } return null; } } private static List readAllLines(URL url) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"))) { List result = new ArrayList<>(); for (;;) { String line = reader.readLine(); if (line == null) { break; } result.add(line); } return result; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy