Package org.jboss.gravia.runtime.osgi.internal

Source Code of org.jboss.gravia.runtime.osgi.internal.OSGiRuntime$OSGiModuleEntriesProvider

/*
* #%L
* Gravia :: Runtime :: OSGi
* %%
* Copyright (C) 2013 - 2014 JBoss by Red Hat
* %%
* 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.
* #L%
*/
package org.jboss.gravia.runtime.osgi.internal;

import static org.jboss.gravia.runtime.spi.RuntimeLogger.LOGGER;

import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

import org.jboss.gravia.Constants;
import org.jboss.gravia.resource.Attachable;
import org.jboss.gravia.resource.DefaultResourceBuilder;
import org.jboss.gravia.resource.DictionaryResourceBuilder;
import org.jboss.gravia.resource.Resource;
import org.jboss.gravia.resource.ResourceBuilder;
import org.jboss.gravia.runtime.Module;
import org.jboss.gravia.runtime.ModuleContext;
import org.jboss.gravia.runtime.ModuleException;
import org.jboss.gravia.runtime.Runtime;
import org.jboss.gravia.runtime.ServiceReference;
import org.jboss.gravia.runtime.ServiceRegistration;
import org.jboss.gravia.runtime.spi.AbstractModule;
import org.jboss.gravia.runtime.spi.AbstractRuntime;
import org.jboss.gravia.runtime.spi.ModuleEntriesProvider;
import org.jboss.gravia.runtime.spi.PropertiesProvider;
import org.jboss.gravia.runtime.spi.ThreadResourceAssociation;
import org.jboss.gravia.runtime.spi.URLStreamHandlerTracker;
import org.jboss.gravia.utils.IllegalArgumentAssertion;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.SynchronousBundleListener;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.url.AbstractURLStreamHandlerService;
import org.osgi.service.url.URLStreamHandlerService;

/**
* The OSGi {@link Runtime}
*
* @author thomas.diesler@jboss.com
* @since 27-Sep-2013
*/
public final class OSGiRuntime extends AbstractRuntime {

    private final BundleContext syscontext;
    private final BundleListener installListener;
    private final URLStreamHandlerTracker streamHandlerTracker;
    private final WeakHashMap<Bundle, Module> uninstalled = new WeakHashMap<Bundle, Module>();

    public OSGiRuntime(BundleContext syscontext, PropertiesProvider propertiesProvider) {
        super(propertiesProvider);

        IllegalArgumentAssertion.assertNotNull(syscontext, "syscontext");
        this.syscontext = syscontext;

        // Assert system bundle
        Bundle sysbundle = syscontext.getBundle();
        if (sysbundle.getBundleId() != 0)
            throw new IllegalArgumentException("Not the system bundle: " + sysbundle);

        // Install system module
        try {
            Resource resource = new DefaultResourceBuilder().addIdentityCapability(getSystemIdentity()).getResource();
            BundleWiring wiring = sysbundle.adapt(BundleWiring.class);
            installModule(wiring.getClassLoader(), resource, sysbundle.getHeaders(), null);
        } catch (ModuleException ex) {
            throw new IllegalStateException("Cannot install system module", ex);
        }

        // Create the {@link URLStreamHandlerTracker}
        streamHandlerTracker = createURLStreamHandlerTracker(getModuleContext());

        // Create the bundle resolve/uninstall listener
        installListener = createBundleInstallListener();
    }

    private URLStreamHandlerTracker createURLStreamHandlerTracker(ModuleContext moduleContext) {
        URLStreamHandlerTracker tracker = new URLStreamHandlerTracker(moduleContext) {

            private Map<ServiceReference<?>, ServiceRegistration<?>> registrations = new HashMap<>();

            @Override
            protected void addingHandler(String protocol, ServiceReference<URLStreamHandler> sref, final URLStreamHandler handler) {
                URLStreamHandlerService service = new AbstractURLStreamHandlerService() {
                    @Override
                    public URLConnection openConnection(URL url) throws IOException {
                        return new URL(null, url.toExternalForm(), handler).openConnection();
                    }
                };
                Dictionary<String, Object> props = new Hashtable<>();
                for (String key : sref.getPropertyKeys()) {
                    if (!key.equals(Constants.SERVICE_ID)) {
                        props.put(key, sref.getProperty(key));
                    }
                }
                ServiceRegistration<URLStreamHandlerService> sreg = getModuleContext().registerService(URLStreamHandlerService.class, service, props);
                registrations.put(sref, sreg);
            }

            @Override
            protected void removingHandler(String protocol, ServiceReference<URLStreamHandler> sref, URLStreamHandler handler) {
                ServiceRegistration<?> sreg = registrations.remove(sref);
                if (sreg != null) {
                    sreg.unregister();
                }
            }
        };
        return tracker;
    }

    private SynchronousBundleListener createBundleInstallListener() {
        return new SynchronousBundleListener() {
            @Override
            public void bundleChanged(BundleEvent event) {
                int eventType = event.getType();
                Bundle bundle = event.getBundle();
                if (eventType == BundleEvent.RESOLVED) {
                    installModule(bundle);
                } else if (eventType == BundleEvent.UNINSTALLED) {
                    Module module = getModule(bundle);
                    if (module != null) {
                        uninstalled.put(bundle, module);
                        uninstallModule(module);
                    }
                }
            }
        };
    }

    Module getModule(Bundle bundle) {
        Module module = super.getModule(bundle.getBundleId());
        if (module == null && bundle.getState() == Bundle.UNINSTALLED) {
            module = uninstalled.get(bundle);
        }
        return module;
    }

    @Override
    public void init() {

        // Start tracking the URLStreamHandler services
        streamHandlerTracker.open();

        // Setup the bundle tracker
        syscontext.addBundleListener(installListener);

        // Install already existing bundles
        for (Bundle bundle : syscontext.getBundles()) {
            installModule(bundle);
        }
    }

    BundleContext getSystemContext() {
        return syscontext;
    }

    @Override
    protected AbstractModule createModule(ClassLoader classLoader, Resource resource, Dictionary<String, String> headers, Attachable context) {
        return new ModuleAdaptor(this, classLoader, resource, headers);
    }

    @Override
    protected ModuleEntriesProvider getDefaultEntriesProvider(Module module, Attachable context) {
        return new OSGiModuleEntriesProvider(module);
    }

    @Override
    protected void uninstallModule(Module module) {
        super.uninstallModule(module);
    }

    private Module installModule(Bundle bundle) {

        Module module = getModule(bundle.getBundleId());
        if (module != null)
            return module;

        BundleWiring wiring = bundle.adapt(BundleWiring.class);
        ClassLoader classLoader = wiring != null ? wiring.getClassLoader() : null;
        if (classLoader == null)
            return null;

        Resource resource = ThreadResourceAssociation.getResource();
        Dictionary<String, String> headers = bundle.getHeaders();
        if (resource == null) {
            ResourceBuilder builder = new DictionaryResourceBuilder().load(headers);
            if (builder.isValid() == false) {
                String symbolicName = bundle.getSymbolicName();
                String version = bundle.getVersion().toString();
                builder.addIdentityCapability(symbolicName, version);
            }
            resource = builder.getResource();
        }

        try {
            module = installModule(classLoader, resource, headers);
        } catch (ModuleException ex) {
            LOGGER.error("Cannot install module from: " + bundle, ex);
        }

        return module;
    }

    @Override
    public Runtime shutdown() {
        throw new UnsupportedOperationException();
    }

    private class OSGiModuleEntriesProvider implements ModuleEntriesProvider {

        private final Module module;

        OSGiModuleEntriesProvider(Module module) {
            this.module = module;
        }

        @Override
        public List<String> getEntryPaths(String path) {
            Bundle bundle = syscontext.getBundle(module.getModuleId());
            Enumeration<String> paths = bundle.getEntryPaths(path);
            List<String> result = new ArrayList<String>();
            if (paths != null) {
                while (paths.hasMoreElements()) {
                    String element = paths.nextElement();
                    result.add(element);
                }
            }
            return Collections.unmodifiableList(result);
        }

        @Override
        public URL getEntry(String path) {
            Bundle bundle = syscontext.getBundle(module.getModuleId());
            return bundle.getEntry(path);
        }

        @Override
        public List<URL> findEntries(String path, String filePattern, boolean recurse) {
            Bundle bundle = syscontext.getBundle(module.getModuleId());
            Enumeration<URL> paths = bundle.findEntries(path, filePattern, recurse);
            List<URL> result = new ArrayList<URL>();
            if (paths != null) {
                while (paths.hasMoreElements()) {
                    URL element = paths.nextElement();
                    result.add(element);
                }
            }
            return Collections.unmodifiableList(result);
        }
    }
}
TOP

Related Classes of org.jboss.gravia.runtime.osgi.internal.OSGiRuntime$OSGiModuleEntriesProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.