Java tutorial
/** * Copyright 2012 Julien Eluard * This project includes software developed by Julien Eluard: https://github.com/jeluard/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.jeluard.extend.osgi; import com.github.jeluard.extend.spi.Loader; import com.github.jeluard.guayaba.lang.Cancelable; import com.github.jeluard.guayaba.util.ServiceLoaders; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Supplier; import java.io.InputStream; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import java.util.logging.Logger; import org.osgi.framework.*; import org.osgi.framework.launch.Framework; import org.osgi.framework.launch.FrameworkFactory; /** * This implementation is explicitely *not* using org.osgi.util.ServiceTracker as it has been written by penguins. * * http://blog.knowhowlab.org/2012/11/osgi-testing-make-your.html */ public final class OSGILoader implements Loader, Cancelable { //Do not use directly private static final AtomicReference<Optional<Framework>> FRAMEWORK = new AtomicReference<Optional<Framework>>(); private static <T> T setIfAbsentAndReturn(final AtomicReference<Optional<T>> reference, final Supplier<T> callable) { //TODO conc. final Optional<T> optionalValue = reference.get(); if (optionalValue.isPresent()) { return optionalValue.get(); } final T value = callable.get(); reference.set(Optional.fromNullable(value)); return value; } /** * @return initialised {@link Framework} used by this {@link Loader} */ private static Framework getOrCreateFramework() throws BundleException { return setIfAbsentAndReturn(OSGILoader.FRAMEWORK, new Supplier<Framework>() { @Override public Framework get() { final FrameworkFactory frameworkFactory = ServiceLoaders.load(FrameworkFactory.class, Thread.currentThread().getContextClassLoader()); final Map<String, String> config = new HashMap<String, String>(); config.put(Constants.FRAMEWORK_STORAGE, "/Users/julien/osgi-test"); config.put(Constants.FRAMEWORK_STORAGE_CLEAN, "true"); final Framework framework = frameworkFactory.newFramework(config); try { framework.init(); final BundleContext context = framework.getBundleContext(); context.addFrameworkListener(new FrameworkListener() { @Override public void frameworkEvent(final FrameworkEvent event) { System.out.println("event: " + event); } }); framework.start(); } catch (BundleException e) { throw new RuntimeException(e); } return framework; } }); } public void install(final String location, final InputStream inputStream) throws BundleException { Preconditions.checkNotNull(location, "null location"); Preconditions.checkNotNull(inputStream, "null inputStream"); getOrCreateFramework().getBundleContext().installBundle(location, inputStream); } /** * * @param classLoader * @param location * @throws BundleException * @throws NullPointerException if one of arguments is null * @throws IllegalArgumentException if {@link Bundle} specified by `location` cannot be found */ public void uninstall(final String location) throws BundleException { Preconditions.checkNotNull(location, "null location"); final Bundle bundle = getOrCreateFramework().getBundleContext().getBundle(location); if (bundle == null) { throw new IllegalArgumentException("Failed to find bundle identified by <" + location + ">"); } bundle.uninstall(); } @Override public <T> Iterable<T> load(final Class<T> type) { Preconditions.checkNotNull(type, "null type"); try { final BundleContext context = getOrCreateFramework().getBundleContext(); final Collection<T> objects = new LinkedList<T>(); for (final ServiceReference<T> serviceReference : context.getServiceReferences(type, null)) { objects.add(context.getService(serviceReference)); } return objects; } catch (BundleException e) { throw new RuntimeException(e); } catch (InvalidSyntaxException e) { throw new RuntimeException(e); } } @Override public void cancel() { //TODO add lifecycle, should not be valid to use after. Also consider conc. final Optional<Framework> optionalFramework = OSGILoader.FRAMEWORK.get(); if (optionalFramework.isPresent()) { final Framework framework = optionalFramework.get(); try { framework.stop(); } catch (BundleException ex) { Logger.getLogger(OSGILoader.class.getName()).log(Level.SEVERE, null, ex); } try { final FrameworkEvent event = framework.waitForStop(0); //TODO log event } catch (InterruptedException e) { Thread.currentThread().interrupt();//Propagate interruption status } } } }