org.wso2.andes.server.plugins.PluginManager.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.andes.server.plugins.PluginManager.java

Source

/*
 * Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you 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 org.wso2.andes.server.plugins;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.felix.framework.Felix;
import org.apache.felix.framework.util.StringMap;
import org.apache.log4j.Logger;
import org.wso2.andes.common.Closeable;
import org.wso2.andes.configuration.qpid.TopicConfiguration;
import org.wso2.andes.configuration.qpid.plugins.ConfigurationPluginFactory;
import org.wso2.andes.configuration.qpid.plugins.SlowConsumerDetectionConfiguration.SlowConsumerDetectionConfigurationFactory;
import org.wso2.andes.configuration.qpid.plugins.SlowConsumerDetectionPolicyConfiguration.SlowConsumerDetectionPolicyConfigurationFactory;
import org.wso2.andes.configuration.qpid.plugins.SlowConsumerDetectionQueueConfiguration.SlowConsumerDetectionQueueConfigurationFactory;
import org.wso2.andes.server.exchange.ExchangeType;
import org.wso2.andes.server.security.SecurityManager;
import org.wso2.andes.server.security.SecurityPluginFactory;
import org.wso2.andes.server.security.access.plugins.AllowAll;
import org.wso2.andes.server.security.access.plugins.DenyAll;
import org.wso2.andes.server.security.access.plugins.LegacyAccess;
import org.wso2.andes.server.security.auth.manager.AuthenticationManagerPluginFactory;
import org.wso2.andes.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
import org.wso2.andes.server.virtualhost.plugins.SlowConsumerDetection;
import org.wso2.andes.server.virtualhost.plugins.VirtualHostPluginFactory;
import org.wso2.andes.server.virtualhost.plugins.policies.TopicDeletePolicy;
import org.wso2.andes.policies.SlowConsumerPolicyPluginFactory;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.launch.Framework;
import org.osgi.util.tracker.ServiceTracker;

import java.io.File;
import java.util.*;

import static org.apache.felix.framework.util.FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP;
import static org.apache.felix.main.AutoProcessor.*;
import static org.osgi.framework.Constants.*;

/**
 * Provides access to pluggable elements, such as exchanges
 */
@SuppressWarnings("unchecked")
public class PluginManager implements Closeable {
    private static final Logger _logger = Logger.getLogger(PluginManager.class);

    private static final int FELIX_STOP_TIMEOUT = 30000;
    private static final String QPID_VER_SUFFIX = "version=0.13,";
    private static BundleContext _bundleContext = null;

    private Framework _felix;

    private ServiceTracker _exchangeTracker = null;
    private ServiceTracker _securityTracker = null;
    private ServiceTracker _configTracker = null;
    private ServiceTracker _virtualHostTracker = null;
    private ServiceTracker _policyTracker = null;
    private ServiceTracker _authenticationManagerTracker = null;

    private Activator _activator;

    private Map<String, SecurityPluginFactory> _securityPlugins = new HashMap<String, SecurityPluginFactory>();
    private Map<List<String>, ConfigurationPluginFactory> _configPlugins = new IdentityHashMap<List<String>, ConfigurationPluginFactory>();
    private Map<String, VirtualHostPluginFactory> _vhostPlugins = new HashMap<String, VirtualHostPluginFactory>();
    private Map<String, SlowConsumerPolicyPluginFactory> _policyPlugins = new HashMap<String, SlowConsumerPolicyPluginFactory>();
    private Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> _authenticationManagerPlugins = new HashMap<String, AuthenticationManagerPluginFactory<? extends Plugin>>();

    public PluginManager(String pluginPath, String cachePath) throws Exception {
        // Store all non-OSGi plugins
        // A little gross that we have to add them here, but not all the plugins are OSGIfied
        for (SecurityPluginFactory<?> pluginFactory : Arrays.asList(AllowAll.FACTORY, DenyAll.FACTORY,
                LegacyAccess.FACTORY)) {
            _securityPlugins.put(pluginFactory.getPluginName(), pluginFactory);
        }
        for (ConfigurationPluginFactory configFactory : Arrays.asList(TopicConfiguration.FACTORY,
                SecurityManager.SecurityConfiguration.FACTORY, AllowAll.AllowAllConfiguration.FACTORY,
                DenyAll.DenyAllConfiguration.FACTORY, LegacyAccess.LegacyAccessConfiguration.FACTORY,
                new SlowConsumerDetectionConfigurationFactory(),
                new SlowConsumerDetectionPolicyConfigurationFactory(),
                new SlowConsumerDetectionQueueConfigurationFactory(),
                PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration.FACTORY)) {
            _configPlugins.put(configFactory.getParentPaths(), configFactory);
        }
        for (SlowConsumerPolicyPluginFactory pluginFactory : Arrays
                .asList(new TopicDeletePolicy.TopicDeletePolicyFactory())) {
            _policyPlugins.put(pluginFactory.getPluginName(), pluginFactory);
        }
        for (VirtualHostPluginFactory pluginFactory : Arrays
                .asList(new SlowConsumerDetection.SlowConsumerFactory())) {
            _vhostPlugins.put(pluginFactory.getClass().getName(), pluginFactory);
        }

        for (AuthenticationManagerPluginFactory<? extends Plugin> pluginFactory : Arrays
                .asList(PrincipalDatabaseAuthenticationManager.FACTORY)) {
            _authenticationManagerPlugins.put(pluginFactory.getPluginName(), pluginFactory);
        }
        if (_bundleContext == null) // Not running inside an OSGi environment.So start Felix.
        {
            // Check the plugin directory path is set and exist
            if (pluginPath == null) {
                return;
            }
            File pluginDir = new File(pluginPath);
            if (!pluginDir.exists()) {
                return;
            }

            // Setup OSGi configuration propery map
            StringMap configMap = new StringMap(false);

            // Add the bundle provided service interface package and the core OSGi
            // packages to be exported from the class path via the system bundle.
            configMap.put(FRAMEWORK_SYSTEMPACKAGES, "org.osgi.framework; version=1.3.0,"
                    + "org.osgi.service.packageadmin; version=1.2.0,"
                    + "org.osgi.service.startlevel; version=1.0.0," + "org.osgi.service.url; version=1.0.0,"
                    + "org.osgi.util.tracker; version=1.0.0," + "org.wso2.andes.junit.extensions.util; "
                    + QPID_VER_SUFFIX + "org.wso2.andes; " + QPID_VER_SUFFIX + "org.wso2.andes.common; "
                    + QPID_VER_SUFFIX + "org.wso2.andes.exchange; " + QPID_VER_SUFFIX + "org.wso2.andes.framing; "
                    + QPID_VER_SUFFIX + "org.wso2.andes.management.common.mbeans.annotations; " + QPID_VER_SUFFIX
                    + "org.wso2.andes.protocol; " + QPID_VER_SUFFIX + "org.wso2.andes.server.binding; "
                    + QPID_VER_SUFFIX + "org.wso2.andes.configuration.qpid; " + QPID_VER_SUFFIX
                    + "org.wso2.andes.configuration.qpid.plugins; " + QPID_VER_SUFFIX
                    + "org.wso2.andes.configuration.qpid.management; " + QPID_VER_SUFFIX
                    + "org.wso2.andes.server.exchange; " + QPID_VER_SUFFIX + "org.wso2.andes.server.logging; "
                    + QPID_VER_SUFFIX + "org.wso2.andes.server.logging.actors; " + QPID_VER_SUFFIX
                    + "org.wso2.andes.server.logging.subjects; " + QPID_VER_SUFFIX
                    + "org.wso2.andes.server.management; " + QPID_VER_SUFFIX + "org.wso2.andes.server.persistent; "
                    + QPID_VER_SUFFIX + "org.wso2.andes.server.plugins; " + QPID_VER_SUFFIX
                    + "org.wso2.andes.server.protocol; " + QPID_VER_SUFFIX + "org.wso2.andes.server.queue; "
                    + QPID_VER_SUFFIX + "org.wso2.andes.server.registry; " + QPID_VER_SUFFIX
                    + "org.wso2.andes.server.security; " + QPID_VER_SUFFIX
                    + "org.wso2.andes.server.security.access; " + QPID_VER_SUFFIX
                    + "org.wso2.andes.server.security.access.plugins; " + QPID_VER_SUFFIX
                    + "org.wso2.andes.server.virtualhost; " + QPID_VER_SUFFIX
                    + "org.wso2.andes.server.virtualhost.plugins; " + QPID_VER_SUFFIX + "org.wso2.andes.util; "
                    + QPID_VER_SUFFIX + "org.apache.commons.configuration; version=1.0.0,"
                    + "org.apache.commons.lang; version=1.0.0," + "org.apache.commons.lang.builder; version=1.0.0,"
                    + "org.apache.commons.logging; version=1.0.0," + "org.apache.log4j; version=1.2.12,"
                    + "javax.management.openmbean; version=1.0.0," + "javax.management; version=1.0.0,"
                    + "javax.security.auth; version=1.0.0");

            // No automatic shutdown hook
            configMap.put("felix.shutdown.hook", "false");

            // Add system activator
            List<BundleActivator> activators = new ArrayList<BundleActivator>();
            _activator = new Activator();
            activators.add(_activator);
            configMap.put(SYSTEMBUNDLE_ACTIVATORS_PROP, activators);

            if (cachePath != null) {
                File cacheDir = new File(cachePath);
                if (!cacheDir.exists() && cacheDir.canWrite()) {
                    _logger.info("Creating plugin cache directory: " + cachePath);
                    cacheDir.mkdir();
                }

                // Set plugin cache directory and empty it
                _logger.info("Cache bundles in directory " + cachePath);
                configMap.put(FRAMEWORK_STORAGE, cachePath);
            }
            configMap.put(FRAMEWORK_STORAGE_CLEAN, FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);

            // Set directory with plugins to auto-deploy
            _logger.info("Auto deploying bundles from directory " + pluginPath);
            configMap.put(AUTO_DEPLOY_DIR_PROPERY, pluginPath);
            configMap.put(AUTO_DEPLOY_ACTION_PROPERY, AUTO_DEPLOY_INSTALL_VALUE + "," + AUTO_DEPLOY_START_VALUE);

            // Start plugin manager and trackers
            _felix = new Felix(configMap);
            try {
                _logger.info("Starting plugin manager...");
                _felix.init();
                process(configMap, _felix.getBundleContext());
                _felix.start();
                _logger.info("Started plugin manager");
            } catch (BundleException e) {
                throw new ConfigurationException("Could not start plugin manager: " + e.getMessage(), e);
            }
            // Initialize bundle context
            _bundleContext = _activator.getContext();
        }
        // TODO save trackers in a map, keyed by class name

        _exchangeTracker = new ServiceTracker(_bundleContext, ExchangeType.class.getName(), null);
        _exchangeTracker.open();

        _securityTracker = new ServiceTracker(_bundleContext, SecurityPluginFactory.class.getName(), null);
        _securityTracker.open();

        _configTracker = new ServiceTracker(_bundleContext, ConfigurationPluginFactory.class.getName(), null);
        _configTracker.open();

        _virtualHostTracker = new ServiceTracker(_bundleContext, VirtualHostPluginFactory.class.getName(), null);
        _virtualHostTracker.open();

        _policyTracker = new ServiceTracker(_bundleContext, SlowConsumerPolicyPluginFactory.class.getName(), null);
        _policyTracker.open();

        _authenticationManagerTracker = new ServiceTracker(_bundleContext,
                AuthenticationManagerPluginFactory.class.getName(), null);
        _authenticationManagerTracker.open();

        _logger.info("Opened service trackers");
    }

    public static void setBundleContext(BundleContext ctx) {
        _bundleContext = ctx;
    }

    private static <T> Map<String, T> getServices(ServiceTracker tracker) {
        Map<String, T> services = new HashMap<String, T>();

        if ((tracker != null) && (tracker.getServices() != null)) {
            for (Object service : tracker.getServices()) {
                if (service instanceof PluginFactory<?>) {
                    services.put(((PluginFactory<?>) service).getPluginName(), (T) service);
                } else {
                    services.put(service.getClass().getName(), (T) service);
                }
            }
        }

        return services;
    }

    public static <T> Map<String, T> getServices(ServiceTracker tracker, Map<String, T> plugins) {
        Map<String, T> services = getServices(tracker);
        services.putAll(plugins);
        return services;
    }

    public Map<List<String>, ConfigurationPluginFactory> getConfigurationPlugins() {
        Map<List<String>, ConfigurationPluginFactory> services = new IdentityHashMap<List<String>, ConfigurationPluginFactory>();

        if (_configTracker != null && _configTracker.getServices() != null) {
            for (Object service : _configTracker.getServices()) {
                ConfigurationPluginFactory factory = (ConfigurationPluginFactory) service;
                services.put(factory.getParentPaths(), factory);
            }
        }

        services.putAll(_configPlugins);

        return services;
    }

    public Map<String, VirtualHostPluginFactory> getVirtualHostPlugins() {
        return getServices(_virtualHostTracker, _vhostPlugins);
    }

    public Map<String, SlowConsumerPolicyPluginFactory> getSlowConsumerPlugins() {
        return getServices(_policyTracker, _policyPlugins);
    }

    public Map<String, ExchangeType<?>> getExchanges() {
        return getServices(_exchangeTracker);
    }

    public Map<String, SecurityPluginFactory> getSecurityPlugins() {
        return getServices(_securityTracker, _securityPlugins);
    }

    public Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> getAuthenticationManagerPlugins() {
        return getServices(_authenticationManagerTracker, _authenticationManagerPlugins);
    }

    public void close() {
        if (_felix != null) {
            try {
                // Close all bundle trackers
                _exchangeTracker.close();
                _securityTracker.close();
                _configTracker.close();
                _virtualHostTracker.close();
                _policyTracker.close();
                _authenticationManagerTracker.close();
            } finally {
                _logger.info("Stopping plugin manager");
                try {
                    // FIXME should be stopAndWait() but hangs VM, need upgrade in felix
                    _felix.stop();
                } catch (BundleException e) {
                    // Ignore
                }

                try {
                    _felix.waitForStop(FELIX_STOP_TIMEOUT);
                } catch (InterruptedException e) {
                    // Ignore
                }
                _logger.info("Stopped plugin manager");
            }
        }
    }
}