Package org.knopflerfish.bundle.cm

Source Code of org.knopflerfish.bundle.cm.PluginManager

/*
* Copyright (c) 2003-2005, KNOPFLERFISH project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
*   notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
*   copyright notice, this list of conditions and the following
*   disclaimer in the documentation and/or other materials
*   provided with the distribution.
*
* - Neither the name of the KNOPFLERFISH project nor the names of its
*   contributors may be used to endorse or promote products derived
*   from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.knopflerfish.bundle.cm;

import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import org.osgi.framework.Constants;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.ConfigurationPlugin;

/**
* * This class is responsible for managing ConfigurationPlugins. * *
*
* @author Per Gustafson *
* @version 1.0
*/

final class PluginManager {
    private final static String CM_RANKING = "service.cmRanking";

    private final static String CM_TARGET = ConfigurationPlugin.CM_TARGET;

    private final static String SERVICE_PID = Constants.SERVICE_PID;

    private final static String SERVICE_ID = Constants.SERVICE_ID;

    /**
     * * Sorted Vector of ServiceReferences to ConfigurationPlugins.
     */

    Vector preModificationPlugins = new Vector();

    /**
     * * Sorted Vector of ServiceReferences to ConfigurationPlugins.
     */

    Vector modifyingPlugins = new Vector();

    /**
     * * Sorted Vector of ServiceReferences to ConfigurationPlugins.
     */

    Vector postModificationPlugins = new Vector();

    /**
     * * Hashtable mapping a ServiceReference to its ranking (Integer).
     */

    Hashtable rankings = new Hashtable();

    /**
     * * Construct a PluginManager
     */

    PluginManager() {
    }

    /**
     * * Handle ConfigurationPlugin ServiceEvents. * *
     *
     * @param serviceReference
     *            ServiceReference of the plugin the event concerns *
     * @param eventType
     *            Type of the event that caused the change
     */

    public synchronized void configurationPluginChanged(
            ServiceReference serviceReference, int eventType) {
        Object rankingProperty = serviceReference.getProperty(CM_RANKING);
        if (rankingProperty == null) {
            rankingProperty = new Integer(0);
        } else if (rankingProperty.getClass() != Integer.class) {
            rankingProperty = new Integer(0);
        }

        Long serviceId = (Long) serviceReference.getProperty(SERVICE_ID);
        if (serviceId == null) {
            Activator.log.error("Missing service id for a ConfigurationPlugin");
            return;
        }

        int ranking = ((Integer) rankingProperty).intValue();

        switch (eventType) {
        case ServiceEvent.REGISTERED:
            rankings.put(serviceId, rankingProperty);
            insertPluginReference(serviceReference, ranking);
            break;
        case ServiceEvent.MODIFIED:
            int oldRanking = ((Integer) rankings.get(serviceId)).intValue();
            if (ranking == oldRanking) {
                return;
            }
            removePluginReference(serviceId, oldRanking);
            rankings.put(serviceId, rankingProperty);
            insertPluginReference(serviceReference, ranking);
            break;
        case ServiceEvent.UNREGISTERING:
            rankings.remove(serviceId);
            removePluginReference(serviceId, ranking);
            break;
        default:
            break;
        }
    }

    /**
     * * Insert a ServiceReference to a ConfigurationPlugin in the correct *
     * Vector based on its ranking. * *
     *
     * @param serviceReference
     *            The ServiceReference. *
     * @param ranking
     *            The ranking the ServiceReference.
     */

    private void insertPluginReference(ServiceReference serviceReference,
            int ranking) {
        if (ranking < 0) {
            insertPluginReference(serviceReference, ranking,
                    preModificationPlugins);
        } else if (0 <= ranking && ranking <= 1000) {
            insertPluginReference(serviceReference, ranking, modifyingPlugins);
        } else if (ranking > 1000) {
            insertPluginReference(serviceReference, ranking,
                    postModificationPlugins);
        } else {
            // Shouldn't happen
        }
    }

    /**
     * * Insert a ServiceReference in a Vector sorted on cm.ranking property. * *
     *
     * @param serviceReference
     *            The ServiceReference. *
     * @param pluginsVector
     *            The vector.
     */

    private void insertPluginReference(ServiceReference serviceReference,
            int ranking, Vector pluginsVector) {
        int i;
        for (i = 0; i < pluginsVector.size(); ++i) {
            ServiceReference nextReference = (ServiceReference) pluginsVector
                    .elementAt(i);
            Long serviceId = (Long) nextReference.getProperty(SERVICE_ID);
            Integer rankingOfNextReference = (Integer) rankings.get(serviceId);
            if (ranking < rankingOfNextReference.intValue()) {
                break;
            }
        }
        pluginsVector.insertElementAt(serviceReference, i);
    }

    /**
     * * Remove a ServiceReference to a ConfigurationPlugin given * a service.id
     * and a ranking. * *
     *
     * @param serviceId
     *            The service.id of the ConfigurationPlugin. *
     * @param ranking
     *            The ranking of the ConfigurationPlugin.
     */

    private void removePluginReference(Object serviceId, int ranking) {
        if (ranking < 0) {
            removePluginReference(serviceId, preModificationPlugins);
        } else if (0 <= ranking && ranking <= 1000) {
            removePluginReference(serviceId, modifyingPlugins);
        } else if (ranking > 1000) {
            removePluginReference(serviceId, postModificationPlugins);
        } else {
            // Shouldn't happen
        }
    }

    private void removePluginReference(Object serviceId, Vector pluginsVector) {
        for (int i = 0; i < pluginsVector.size(); ++i) {
            ServiceReference serviceReference = (ServiceReference) pluginsVector
                    .elementAt(i);
            Long currentId = (Long) serviceReference.getProperty(SERVICE_ID);
            if (currentId.equals(serviceId)) {
                pluginsVector.removeElementAt(i);
                return;
            }
        }
    }

    /**
     * * Call all applicable ConfigurationPlugins given a pid and a dictionary. * *
     *
     * @param pid
     *            The pid of the target ManagedService(Factory). *
     * @param dictionary
     *            The configuration dictionary to be modified. * *
     * @return The description of what the method returns.
     */

    public synchronized ConfigurationDictionary callPluginsAndCreateACopy(
            ServiceReference targetServiceReference,
            ConfigurationDictionary dictionary) {
        if (targetServiceReference == null) {
            return dictionary;
        }
        if (dictionary == null) {
            return null;
        }
        callPlugins(targetServiceReference, dictionary, preModificationPlugins,
                false);

        dictionary = callPlugins(targetServiceReference, dictionary,
                modifyingPlugins, true);

        callPlugins(targetServiceReference, dictionary,
                postModificationPlugins, false);

        if (dictionary != null) {
            dictionary = dictionary.createCopyIfRealAndRemoveLocation();
        }
        return dictionary;
    }

    /**
     * * Call all plugins contained in a Vector and * optionally allow
     * modifications. * *
     *
     * @param targetServiceReference
     *            Reference to the target ManagedService(Factory). *
     * @param dictionary
     *            The configuration dictionary to process. *
     * @param plugins
     *            Vector of references to ConfigurationPlugins. *
     * @param allowModification
     *            Should modifications to the configuration dictionary be
     *            allowed. * *
     * @return The modified configuration dictionary.
     */

    private ConfigurationDictionary callPlugins(
            ServiceReference targetServiceReference,
            ConfigurationDictionary dictionary, Vector plugins,
            boolean allowModification) {
        String pid = (String)dictionary.get(SERVICE_PID);
        ConfigurationDictionary currentDictionary = dictionary;
        Enumeration e = plugins.elements();
        while (e.hasMoreElements()) {
            ServiceReference pluginReference = (ServiceReference) e
                    .nextElement();

            // Only call the plugin if no cm.target is specified or if it
            // matches the pid of the target service
            String cmTarget = (String) pluginReference.getProperty(CM_TARGET);
            if (cmTarget == null || cmTarget.equals(pid)) {
                ConfigurationPlugin plugin = (ConfigurationPlugin) Activator.bc
                        .getService(pluginReference);
                if (plugin == null) {
                    continue;
                }
                ConfigurationDictionary dictionaryCopy = currentDictionary
                        .createCopyAndRemoveLocation();
                try {
                    plugin.modifyConfiguration(targetServiceReference,
                            dictionaryCopy);
                    if (allowModification && validateDictionary(dictionaryCopy)) {
                        currentDictionary = dictionaryCopy;
                    }
                } catch (Exception exception) {
                    Activator.log.error("[CM] Exception thrown by plugin: "
                            + exception.getMessage());
                }
            }
        }
        return currentDictionary;
    }

    /**
     * * Verify that a dictionary that has been modified by * a plugin still is
     * valid. * * Might restore some keys. * *
     *
     * @param dictionary
     *            The dictionary to validate. * *
     * @return true if valid, false otherwise.
     */

    private boolean validateDictionary(Dictionary dictionary) {
        ConfigurationDictionary.validateDictionary(dictionary);
        return true;
    }
}
TOP

Related Classes of org.knopflerfish.bundle.cm.PluginManager

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.