com.github.jeluard.extend.osgi.OSGILoader.java Source code

Java tutorial

Introduction

Here is the source code for com.github.jeluard.extend.osgi.OSGILoader.java

Source

/**
 * 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
            }
        }
    }

}