directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jcon...@apache.org
Subject svn commit: r501176 [3/6] - in /directory/sandbox/jconlon/osgi-services/configuration-service: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/configuration/ src/main/java/org/apache/configuration/...
Date Mon, 29 Jan 2007 20:38:29 GMT
Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceTrackerCustomizer.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceTrackerCustomizer.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceTrackerCustomizer.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceTrackerCustomizer.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,167 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF 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.apache.configuration.event;
+
+import java.util.concurrent.Executor;
+
+import org.apache.configuration.impl.ConfigurationDictionary;
+import org.apache.configuration.impl.ConfigurationStore;
+import org.apache.configuration.impl.ConfigurationTransformer;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ManagedServiceTrackerCustomizer.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ManagedServiceTrackerCustomizer implements ServiceTrackerCustomizer
+{
+    /** the log for this class */
+    private static final Logger log = LoggerFactory.getLogger( ManagedServiceTrackerCustomizer.class );
+    private ConfigurationStore configurationStore;
+    private Executor executor;
+    private ConfigurationTransformer configurationTransformer;
+//    private BundleContext bundleContext;
+    private ManagedServiceTrackingAdapter managedServiceTrackingAdapter;
+    
+    
+
+
+    /* (non-Javadoc)
+     * @see org.osgi.util.tracker.ServiceTrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
+     */
+    public Object addingService( final ServiceReference serviceReference )
+    {
+        Runnable command = 
+            new Runnable() {
+
+                 String servicePid = (String) serviceReference.getProperty(Constants.SERVICE_PID);
+                public void run() 
+                {
+                    
+                    String location = serviceReference.getBundle().getLocation();
+                    try
+                    {
+                        ConfigurationDictionary configurationDictionary = 
+                            configurationStore.retrieveAndBind( servicePid, location );
+                        ManagedService managedService =managedServiceTrackingAdapter.getService( serviceReference );
+//                        ManagedService managedService = (ManagedService) bundleContext.getService( serviceReference );
+                        managedService.updated( configurationTransformer.transform( serviceReference, configurationDictionary) );
+                    }
+                    catch ( Exception e )
+                    {
+                        
+                        log.error( "Failed to update ManagedService for servicePid="+servicePid,e);
+                    }
+                    
+                }
+               
+        };
+        
+        executor.execute( command );
+        return serviceReference ;
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.osgi.util.tracker.ServiceTrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
+     */
+    public void modifiedService( ServiceReference arg0, Object arg1 )
+    {
+        // ignore
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.osgi.util.tracker.ServiceTrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
+     */
+    public void removedService( final ServiceReference serviceReference, Object service )
+    {
+        Runnable command = 
+            new Runnable() {
+
+                public void run() 
+                {
+                    
+                    String servicePid = (String) serviceReference.getProperty(Constants.SERVICE_PID);
+
+                    configurationStore.unbind(servicePid);
+                   
+                }
+               
+        };
+        
+        executor.execute( command );
+    }
+
+
+//    /**
+//     * @param bundleContext the bundleContext to set
+//     */
+//    public void setBundleContext( BundleContext bundleContext )
+//    {
+//        this.bundleContext = bundleContext;
+//    }
+
+
+    /**
+     * @param configurationStore the configurationStore to set
+     */
+    public void setConfigurationStore( ConfigurationStore configurationStore )
+    {
+        this.configurationStore = configurationStore;
+    }
+
+
+    /**
+     * @param configurationTransformer the configurationTransformer to set
+     */
+    public void setConfigurationTransformer( ConfigurationTransformer configurationTransformer )
+    {
+        this.configurationTransformer = configurationTransformer;
+    }
+
+
+    /**
+     * @param executor the executor to set
+     */
+    public void setExecutor( Executor executor )
+    {
+        this.executor = executor;
+    }
+
+
+    /**
+     * @param managedServiceTrackingAdapter the managedServiceTrackingAdapter to set
+     */
+    public void setManagedServiceTrackingAdapter( ManagedServiceTrackingAdapter managedServiceTrackingAdapter )
+    {
+        this.managedServiceTrackingAdapter = managedServiceTrackingAdapter;
+    }
+
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceTrackingAdapter.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceTrackingAdapter.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceTrackingAdapter.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceTrackingAdapter.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,52 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF 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.apache.configuration.event;
+
+import org.apache.configuration.springosgi.ServiceTrackingAdapter;
+import org.osgi.service.cm.ManagedService;
+
+/**
+ * A <tt>ManagedServiceTrackingAdapter</tt> is a {@link ServiceTrackingAdapter} for 
+ * {@link ManagedService} serviceReferences.  
+ * 
+ * @see ServiceTrackingAdapter
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ManagedServiceTrackingAdapter extends ServiceTrackingAdapter<ManagedService>
+{
+    
+    public ManagedServiceTrackingAdapter()
+    {
+       super(ManagedService.class);
+    }
+
+    
+//    /**
+//     * Creates a new instance of ManagedServiceTrackingAdapter.
+//     * @deprecated
+//     */
+//    public ManagedServiceTrackingAdapter(ServiceTrackerCustomizer serviceTrackingCustomizer, ServiceTracking<ManagedService> delegate)
+//    {
+//       super(ManagedService.class,  serviceTrackingCustomizer, delegate);
+//    }
+
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/PluginManager.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/PluginManager.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/PluginManager.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/PluginManager.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,339 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.configuration.event;
+
+
+import java.util.Dictionary;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.configuration.impl.ConfigurationDictionary;
+import org.apache.configuration.impl.ConfigurationTransformer;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ConfigurationPlugin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.osgi.context.BundleContextAware;
+
+
+/**
+ * This class is responsible for managing ConfigurationPlugins.
+ * 
+ */
+public final class PluginManager implements ServiceListener, BundleContextAware, ConfigurationTransformer
+{
+    /** the log for this class */
+    private static final Logger log = LoggerFactory.getLogger( PluginManager.class );
+
+    private final static String CM_RANKING = "service.cmRanking";
+
+    private static final String FILTER = "(objectClass=" + ConfigurationPlugin.class.getName() + ")";
+
+    private BundleContext bundleContext;//injected
+
+    /**
+     * Sorted Map of ranked ServiceReferences.
+     */
+    private Map<RankingKey, ServiceReference> preModificationPlugins = new TreeMap<RankingKey, ServiceReference>();
+
+    /**
+     * Sorted Map of ranked ServiceReferences.
+     */
+    private Map<RankingKey, ServiceReference> modifyingPlugins = new TreeMap<RankingKey, ServiceReference>();
+
+    /**
+     * Sorted Map of ranked ServiceReferences.
+     */
+    private Map<RankingKey, ServiceReference> postModificationPlugins = new TreeMap<RankingKey, ServiceReference>();
+
+
+    public void init()
+    {
+        try
+        {
+            bundleContext.addServiceListener( this, FILTER );
+        }
+        catch ( InvalidSyntaxException ise )
+        {
+            log.error( ise.getMessage(), ise );
+        }
+    }
+
+
+    public void destroy()
+    {
+        bundleContext.removeServiceListener( this );
+    }
+
+
+    /**
+     * Handle ConfigurationPlugin ServiceEvents.
+     * 
+     * @param event The event that caused the change
+     */
+    public synchronized void serviceChanged( ServiceEvent event )
+    {
+        log.debug( "Processing serviceEvent {} .", event );
+
+        ServiceReference sr = event.getServiceReference();
+        int eventType = event.getType();
+        Object rankingProperty = sr.getProperty( CM_RANKING );
+
+        int ranking;
+
+        if ( rankingProperty == null || rankingProperty.getClass() != Integer.class )
+        {
+            ranking = 0;
+        }
+        else
+        {
+            ranking = ( ( Integer ) rankingProperty ).intValue();
+        }
+
+        RankingKey key = new RankingKey( ranking, sr );
+
+        switch ( eventType )
+        {
+            case ServiceEvent.REGISTERED:
+            case ServiceEvent.MODIFIED:
+                insertPluginReference( ranking, key, sr );
+                break;
+            case ServiceEvent.UNREGISTERING:
+                removePluginReference( key );
+                break;
+            default:
+                break;
+        }
+    }
+
+
+    /**
+     * Call all applicable ConfigurationPlugins with for a given serviceReference and a dictionary.
+     * 
+     * @param targetServiceReference The ServiceReference of the target ManagedService[Factory].
+     * @param dictionary The configuration dictionary to be modified.
+     * @return The description of what the method returns.
+     * 
+     */
+    private 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.createCopy();
+        }
+
+        return dictionary;
+    }
+
+
+    /**
+     * 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( int ranking, RankingKey key, ServiceReference serviceReference )
+    {
+        log.debug( "Inserting PluginReference bundle=" + serviceReference.getBundle().getBundleId() + " ranking="
+            + ranking );
+        removePluginReference( key );
+
+        if ( ranking < 0 )
+        {
+            preModificationPlugins.put( key, serviceReference );
+        }
+        else if ( 0 <= ranking && ranking <= 1000 )
+        {
+            modifyingPlugins.put( key, serviceReference );
+        }
+        else if ( ranking > 1000 )
+        {
+            postModificationPlugins.put( key, serviceReference );
+        }
+    }
+
+
+    /**
+     * Remove a plugin service reference given a ranking key.
+     * 
+     * @param key The key to the service reference of the ConfigurationPlugin.
+     */
+    private void removePluginReference( RankingKey key )
+    {
+        log.debug( "Removing PluginReference key {}.", key );
+        preModificationPlugins.remove( key );
+        modifyingPlugins.remove( key );
+        postModificationPlugins.remove( key );
+    }
+
+
+    /**
+     * Call all plugins contained in collection of plugins 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, Map plugins, boolean allowModification )
+    {
+        String pid = ( String ) targetServiceReference.getProperty( Constants.SERVICE_PID );
+        ConfigurationDictionary currentDictionary = dictionary;
+        Iterator it = plugins.values().iterator();
+
+        while ( it.hasNext() )
+        {
+            ServiceReference pluginReference = ( ServiceReference ) it.next();
+
+            // Call the plugin if no cm.target is specified or if target matches
+            String cmTarget = ( String ) pluginReference.getProperty( ConfigurationPlugin.CM_TARGET );
+
+            if ( cmTarget == null || cmTarget.equals( pid ) )
+            {
+                ConfigurationPlugin plugin = ( ConfigurationPlugin ) bundleContext.getService( pluginReference );
+
+                if ( plugin != null )
+                {
+
+                    ConfigurationDictionary dictionaryCopy = currentDictionary.createCopy();
+
+                    try
+                    {
+                        plugin.modifyConfiguration( targetServiceReference, dictionaryCopy );
+
+                        ConfigurationDictionary.validateDictionary( dictionary );
+
+                        if ( allowModification )
+                        {
+                            currentDictionary = dictionaryCopy;
+                        }
+                    }
+                    catch ( Exception exception )
+                    {
+                        log.error( "Exception thrown by plugin: " + exception.getMessage() );
+                    }
+
+                }
+            }
+        }
+
+        return currentDictionary;
+    }
+
+    private class RankingKey implements Comparable
+    {
+        public int hashCode()
+        {
+            return 0;
+        }
+
+        private int ranking;
+        private ServiceReference reference;
+
+
+        private RankingKey( int ranking, ServiceReference reference )
+        {
+            this.ranking = ranking;
+            this.reference = reference;
+        }
+
+
+        public int compareTo( Object o )
+        {
+            final int BEFORE = -1;
+            final int EQUAL = 0;
+            final int AFTER = 1;
+
+            if ( this == o )
+            {
+                return EQUAL;
+            }
+
+            final RankingKey that = ( RankingKey ) o;
+
+            if ( this.reference == that.reference )
+            {
+                return EQUAL;
+            }
+
+            if ( this.ranking < that.ranking )
+            {
+                return BEFORE;
+            }
+
+            if ( this.ranking > that.ranking )
+            {
+                return AFTER;
+            }
+
+            return EQUAL;
+        }
+
+
+        public boolean equals( Object o )
+        {
+            if ( this == o )
+            {
+                return true;
+            }
+
+            final RankingKey that = ( RankingKey ) o;
+
+            return this.reference == that.reference;
+        }
+    }
+
+
+    public void setBundleContext( BundleContext bundleContext )
+    {
+        this.bundleContext = bundleContext;
+
+    }
+
+
+    public Dictionary transform( ServiceReference serviceReference, ConfigurationDictionary dictionary )
+    {
+        return callPluginsAndCreateACopy( serviceReference, dictionary );
+    }
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/package-info.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/package-info.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/package-info.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/package-info.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,11 @@
+/**
+ * org.apache.configuration.event is the set of interfaces and classes that specify a
+ * framework for notifying ConfiguarionAdmin clients and internal implementation 
+ * classes of state changes to the Configuraiton Admin implementation.  This framework 
+ * is utilized for asynchronously invoking methods on ConfigurationListener, 
+ * ManagedServiceFactory, and ManagedService OSGi client users of the ConfigurationAdmin
+ * service.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+package org.apache.configuration.event;
\ No newline at end of file

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/felix/framework/FilterImpl.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/felix/framework/FilterImpl.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/felix/framework/FilterImpl.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/felix/framework/FilterImpl.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,286 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.configuration.felix.framework;
+
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+import org.apache.felix.framework.util.ldap.AttributeNotFoundException;
+import org.apache.felix.framework.util.ldap.EvaluationException;
+import org.apache.felix.framework.util.ldap.Evaluator;
+import org.apache.felix.framework.util.ldap.LdapLexer;
+import org.apache.felix.framework.util.ldap.Mapper;
+import org.apache.felix.framework.util.ldap.ParseException;
+import org.apache.felix.framework.util.ldap.Parser;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class implements an RFC 1960-based filter. The syntax of the
+ * filter string is the string representation of LDAP search filters
+ * as defined in RFC 1960. These filters are used to search for services
+ * and to track services using <tt>ServiceTracker</tt> objects.
+**/
+public class FilterImpl implements Filter
+{
+//    private Logger m_logger = null;
+    private Logger m_logger = LoggerFactory.getLogger( FilterImpl.class );
+    private String m_toString = null;
+    private Evaluator m_evaluator = null;
+    private SimpleMapper m_mapper = null;
+
+    public FilterImpl(String expr) throws InvalidSyntaxException
+    {
+        this(null, expr);
+    }
+
+    /**
+     * Construct a filter for a given filter expression string.
+     * @param expr the filter expression string for the filter.
+    **/
+    public FilterImpl(Logger logger, String expr) throws InvalidSyntaxException
+    {
+        m_logger = logger;
+        if (expr == null)
+        {
+            throw new InvalidSyntaxException("Filter cannot be null", null);
+        }
+
+        if (expr != null)
+        {
+            CharArrayReader car = new CharArrayReader(expr.toCharArray());
+            LdapLexer lexer = new LdapLexer(car);
+            Parser parser = new Parser(lexer);
+            try
+            {
+                if (!parser.start())
+                {
+                    throw new InvalidSyntaxException(
+                        "Failed to parse LDAP query.", expr);
+                }
+            }
+            catch (ParseException ex)
+            {
+                throw new InvalidSyntaxException(
+                    ex.getMessage(), expr);
+            }
+            catch (IOException ex)
+            {
+                throw new InvalidSyntaxException(
+                    ex.getMessage(), expr);
+            }
+            m_evaluator = new Evaluator(parser.getProgram());
+            m_mapper = new SimpleMapper();
+        }
+    }
+
+    /**
+     * Compares the <tt>Filter</tt> object to another.
+     * @param o the object to compare this <tt>Filter</tt> against.
+     * @return If the other object is a <tt>Filter</tt> object, it
+     *         returns <tt>this.toString().equals(obj.toString())</tt>;
+     *         <tt>false</tt> otherwise.
+    **/
+    public boolean equals(Object o)
+    {
+        if (o == null)
+        {
+            return false;
+        }
+        else if (o instanceof Filter)
+        {
+            return toString().equals(o.toString());
+        }
+        return false;
+    }
+
+    /**
+     * Returns the hash code for the <tt>Filter</tt> object.
+     * @return The value <tt>this.toString().hashCode()</tt>.
+    **/
+    public int hashCode()
+    {
+        return toString().hashCode();
+    }
+
+    /**
+     * Filter using a <tt>Dictionary</tt> object. The <tt>Filter</tt>
+     * is executed using the <tt>Dictionary</tt> object's keys and values.
+     * @param dict the <tt>Dictionary</tt> object whose keys and values
+     *             are used to determine a match.
+     * @return <tt>true</tt> if the <tt>Dictionary</tt> object's keys
+     *         and values match this filter; <tt>false</tt> otherwise.
+     * @throws IllegalArgumentException if the dictionary contains case
+     *         variants of the same key name.
+    **/
+    public boolean match(Dictionary dict)
+        throws IllegalArgumentException
+    {
+        try
+        {
+            // Since the mapper instance is reused, we should
+            // null the source after use to avoid potential
+            // garbage collection issues.
+            m_mapper.setSource(dict, false);
+            boolean result = m_evaluator.evaluate(m_mapper);
+            m_mapper.setSource(null, false);
+            return result;
+        }
+        catch (AttributeNotFoundException ex)
+        {
+            m_logger.debug("FilterImpl: Attribute not found.", ex);
+        }
+        catch (EvaluationException ex)
+        {
+            m_logger.error("FilterImpl: " + toString(), ex);
+        }
+        return false;
+    }
+
+    /**
+     * Filter using a service's properties. The <tt>Filter</tt>
+     * is executed using the properties of the referenced service.
+     * @param ref A reference to the service whose properties
+     *             are used to determine a match.
+     * @return <tt>true</tt> if the service's properties match this
+     *         filter; <tt>false</tt> otherwise.
+    **/
+    public boolean match(ServiceReference ref)
+    {
+        try
+        {
+            // Since the mapper instance is reused, we should
+            // null the source after use to avoid potential
+            // garbage collection issues.
+            m_mapper.setSource(ref);
+            boolean result = m_evaluator.evaluate(m_mapper);
+            m_mapper.setSource(null);
+            return result;
+        }
+        catch (AttributeNotFoundException ex)
+        {
+            m_logger.error( "FilterImpl: Attribute not found.", ex);
+        }
+        catch (EvaluationException ex)
+        {
+            m_logger.error("FilterImpl: " + toString(), ex);
+        }
+        return false;
+    }
+
+    public boolean matchCase(Dictionary dict)
+    {
+        try
+        {
+            // Since the mapper instance is reused, we should
+            // null the source after use to avoid potential
+            // garbage collection issues.
+            m_mapper.setSource(dict, true);
+            boolean result = m_evaluator.evaluate(m_mapper);
+            m_mapper.setSource(null, true);
+            return result;
+        }
+        catch (AttributeNotFoundException ex)
+        {
+            m_logger.debug("FilterImpl: Attribute not found.", ex);
+        }
+        catch (EvaluationException ex)
+        {
+            m_logger.error("FilterImpl: " + toString(), ex);
+        }
+        return false;
+    }
+
+    /**
+     * Returns the <tt>Filter</tt> object's filter string.
+     * @return Filter string.
+    **/
+    public String toString()
+    {
+        if (m_toString == null)
+        {
+            m_toString = m_evaluator.toStringInfix();
+        }
+        return m_toString;
+    }
+
+    static class SimpleMapper implements Mapper
+    {
+        private ServiceReference m_ref = null;
+        private StringMap m_map = null;
+
+        public void setSource(ServiceReference ref)
+        {
+            m_ref = ref;
+            m_map = null;
+        }
+
+        public void setSource(Dictionary dict, boolean caseSensitive)
+        {
+            // Create a map if we don't have one.
+            
+            if (m_map == null)
+            {
+                m_map = new StringMap();
+            }
+            else
+            {
+                m_map.clear();
+            }
+
+            // Set case comparison accordingly.
+            m_map.setCaseSensitive(caseSensitive);
+
+            // Put all dictionary entries into the map.
+            if (dict != null)
+            {
+                Enumeration keys = dict.keys();
+                while (keys.hasMoreElements())
+                {
+                    Object key = keys.nextElement();
+                    if (m_map.get(key) == null)
+                    {
+                        m_map.put(key, dict.get(key));
+                    }
+                    else
+                    {
+                        throw new IllegalArgumentException(
+                            "Duplicate attribute: " + key.toString());
+                    }
+                }
+            }
+            m_ref = null;
+        }
+
+        public Object lookup(String name)
+        {
+            if (m_map == null)
+            {
+                return m_ref.getProperty(name);
+            }
+            return m_map.get(name);
+        }
+    }
+
+}
\ No newline at end of file

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/felix/framework/StringMap.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/felix/framework/StringMap.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/felix/framework/StringMap.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/felix/framework/StringMap.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,104 @@
+
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.configuration.felix.framework;
+
+import java.util.*;
+
+/**
+ * Simple utility class that creates a map for string-based keys by
+ * extending <tt>TreeMap</tt>. This map can be set to use case-sensitive
+ * or case-insensitive comparison when searching for the key.
+ * Any keys put into this map will be converted to
+ * a <tt>String</tt> using the <tt>toString()</tt> method,
+ * since it is only intended to compare strings.
+**/
+public class StringMap extends TreeMap
+{
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1L;
+
+    public StringMap()
+    {
+        this(true);
+    }
+    
+    @SuppressWarnings("unchecked")
+    public StringMap(boolean caseSensitive)
+    {
+        super(new StringComparator(caseSensitive));
+    }
+    
+    @SuppressWarnings("unchecked")
+    public StringMap(Map map, boolean caseSensitive)
+    {
+        this(caseSensitive);
+        putAll(map);
+    }
+    
+    @SuppressWarnings("unchecked")
+    public Object put(Object key, Object value)
+    {
+        return super.put(key.toString(), value);
+    }
+    
+    public boolean isCaseSensitive()
+    {
+        return ((StringComparator) comparator()).isCaseSensitive();
+    }
+
+    public void setCaseSensitive(boolean b)
+    {
+        ((StringComparator) comparator()).setCaseSensitive(b);
+    }
+
+    private static class StringComparator implements Comparator
+    {
+        private boolean m_isCaseSensitive = true;
+
+        public StringComparator(boolean b)
+        {
+            m_isCaseSensitive = b;
+        }
+
+        public int compare(Object o1, Object o2)
+        {
+            if (m_isCaseSensitive)
+            {
+                return o1.toString().compareTo(o2.toString());
+            }
+            else
+            {
+                return o1.toString().compareToIgnoreCase(o2.toString());
+            }
+        }
+
+        public boolean isCaseSensitive()
+        {
+            return m_isCaseSensitive;
+        }
+
+        public void setCaseSensitive(boolean b)
+        {
+            m_isCaseSensitive = b;
+        }
+    }
+}
\ No newline at end of file

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/felix/framework/package-info.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/felix/framework/package-info.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/felix/framework/package-info.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/felix/framework/package-info.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,8 @@
+/**
+ * org.apache.configuration.felix.framework is the set of classes from the 
+ * <em>Apache Felix</em> project that implement an OSGi filter that can be used
+ * for searching for Configuration dictionary objects.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+package org.apache.configuration.felix.framework;
\ No newline at end of file

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationAdminImpl.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationAdminImpl.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationAdminImpl.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationAdminImpl.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,304 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.configuration.impl;
+
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Dictionary;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationPermission;
+
+/**
+ * <p>A <tt>ConfigurationAdminImpl</tt> 
+ * is a ConfigurationAdmin service assigned to individual bundles.  
+ * Registered indirectly with the framework via the ServiceFactory ConfigurationAdminServiceFactory.
+ * 
+ * @see ConfigurationAdminServiceFactory
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ * 
+ */
+public class ConfigurationAdminImpl implements ConfigurationAdmin
+{
+    
+    private final Bundle callingBundle;
+    private final ConfigurationStore configurationStore;
+
+    /**
+     * 
+     * Creates a new instance of ConfigurationAdminImpl.
+     *
+     * @param configurationStore
+     * @param callingBundle
+     */
+    public ConfigurationAdminImpl( ConfigurationStore configurationStore, Bundle callingBundle )
+    {
+
+        this.configurationStore = configurationStore;
+        this.callingBundle = callingBundle;
+    }
+
+    
+    /**
+     * Create a new factory <code>Configuration</code> object with a new PID.
+     * 
+     * The properties of the new <code>Configuration</code> object are
+     * <code>null</code> until the first time that its
+     * {@link Configuration#update(Dictionary)} method is called.
+     * 
+     * <p>
+     * It is not required that the <code>factoryPid</code> maps to a
+     * registered Managed Service Factory.
+     * <p>
+     * The <code>Configuration</code> object is bound to the location of the
+     * calling bundle.
+     * 
+     * @param factoryPid PID of factory (not <code>null</code>).
+     * @return A new <code>Configuration</code> object.
+     * @throws IOException if access to persistent storage fails.
+     * @throws SecurityException if caller does not have <code>ConfigurationPermission[*,CONFIGURE]</code> and <code>factoryPid</code> is bound to another bundle.
+     */
+    public Configuration createFactoryConfiguration( String factoryPid ) throws IOException
+    {
+        Object sm = System.getSecurityManager();
+
+        if (sm != null)
+        {
+            ((SecurityManager) sm).checkPermission(new ConfigurationPermission("*",
+                ConfigurationPermission.CONFIGURE));
+        }
+        String bundleLocation = callingBundle.getLocation();
+        return createFactoryConfiguration( factoryPid, bundleLocation );
+    }
+
+    
+    /**
+     * Create a new factory <code>Configuration</code> object with a new PID.
+     * 
+     * The properties of the new <code>Configuration</code> object are
+     * <code>null</code> until the first time that its
+     * {@link Configuration#update(Dictionary)} method is called.
+     * 
+     * <p>
+     * It is not required that the <code>factoryPid</code> maps to a
+     * registered Managed Service Factory.
+     * 
+     * <p>
+     * The <code>Configuration</code> is bound to the location specified. If
+     * this location is <code>null</code> it will be bound to the location of
+     * the first bundle that registers a Managed Service Factory with a
+     * corresponding PID.
+     * 
+     * @param factoryPid PID of factory (not <code>null</code>).
+     * @param location A bundle location string, or <code>null</code>.
+     * @return a new <code>Configuration</code> object.
+     * @throws IOException if access to persistent storage fails.
+     * @throws SecurityException if caller does not have <code>ConfigurationPermission[*,CONFIGURE]</code>.
+     */
+    public Configuration createFactoryConfiguration( String factoryPid, String location ) throws IOException
+    {
+        Object sm = System.getSecurityManager();
+
+        if (sm != null)
+        {
+            ((SecurityManager) sm).checkPermission(new ConfigurationPermission("*",
+                ConfigurationPermission.CONFIGURE));
+        }
+        if(factoryPid ==null){
+            throw new IllegalArgumentException("factoryPid argument cannot be null.");
+        }
+        String pid = generatePid( factoryPid );
+        
+        Configuration config = configurationStore.getNewConfiguration( location, factoryPid, pid );
+
+        return config;
+    }
+
+    /**
+     * Get an existing or new <code>Configuration</code> object from the
+     * persistent store.
+     * 
+     * If the <code>Configuration</code> object for this PID does not exist,
+     * create a new <code>Configuration</code> object for that PID, where
+     * properties are <code>null</code>. Bind its location to the calling
+     * bundle's location.
+     * 
+     * <p>
+     * Otherwise, if the location of the existing <code>Configuration</code> object
+     * is <code>null</code>, set it to the calling bundle's location.
+     * 
+     * @param pid persistent identifier.
+     * @return an existing or new <code>Configuration</code> matching the PID.
+     * @throws IOException if access to persistent storage fails.
+     * @throws SecurityException if the <code>Configuration</code> object is bound 
+     * to a location different from that of the calling bundle and it has 
+     * no <code>ConfigurationPermission[*,CONFIGURE]</code>.
+     */
+    public Configuration getConfiguration( String pid ) throws IOException
+    {
+        Object sm = System.getSecurityManager();
+
+        if (sm != null)
+        {
+            ((SecurityManager) sm).checkPermission(new ConfigurationPermission("*",
+                ConfigurationPermission.CONFIGURE));
+        }
+      
+        return getConfiguration( pid, callingBundle.getLocation());
+    }
+
+    /**
+     * Get an existing <code>Configuration</code> object from the persistent
+     * store, or create a new <code>Configuration</code> object.
+     * 
+     * <p>
+     * If a <code>Configuration</code> with this PID already exists in
+     * Configuration Admin service return it. The location parameter is ignored
+     * in this case.
+     * 
+     * <p>
+     * Else, return a new <code>Configuration</code> object. This new object
+     * is bound to the location and the properties are set to <code>null</code>.
+     * If the location parameter is <code>null</code>, it will be set when a
+     * Managed Service with the corresponding PID is registered for the first
+     * time.
+     * 
+     * @param pid Persistent identifier.
+     * @param location The bundle location string, or <code>null</code>.
+     * @return An existing or new <code>Configuration</code> object.
+     * @throws IOException if access to persistent storage fails.
+     * @throws SecurityException if the caller does not have 
+     * <code>ConfigurationPermission[*,CONFIGURE]</code>.
+     */
+    public Configuration getConfiguration( String pid, String location ) throws IOException
+    {
+        Object sm = System.getSecurityManager();
+
+        if (sm != null)
+        {
+            ((SecurityManager) sm).checkPermission(new ConfigurationPermission("*",
+                ConfigurationPermission.CONFIGURE));
+        }
+        
+        if(pid == null){
+            throw new IllegalArgumentException("pid argument cannot be null.");
+        }
+        if(!configurationStore.listPids().contains( pid )){
+            Configuration c = configurationStore.getNewConfiguration( location, null, pid );
+
+            if ( location != null )
+            {
+                c.setBundleLocation( location );
+            }
+
+            return c;
+        }
+        ConfigurationDictionary dictionary;
+
+        try
+        {
+            dictionary = load( pid );
+        }
+        catch ( IOException e )
+        {
+            dictionary = null;
+        }
+
+        
+
+        String bundleLocation = (String) dictionary.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+        String factoryPid = (String) dictionary.get( ConfigurationAdmin.SERVICE_FACTORYPID );
+
+        return configurationStore.getNewConfiguration( bundleLocation, factoryPid, pid, dictionary );
+    }
+
+    
+
+    public Configuration[] listConfigurations( final String filterString ) throws IOException, InvalidSyntaxException
+    {
+        Configuration[] configurations = null;
+
+        try
+        {
+            configurations =  AccessController.doPrivileged( new PrivilegedExceptionAction<Configuration[]>()
+            {
+                public Configuration[] run() throws IOException, InvalidSyntaxException
+                {
+                    return configurationStore.listConfigurations( filterString );
+                }
+            } );
+        }
+        catch ( PrivilegedActionException e )
+        {
+            configurations = null;
+
+            if ( e.getException().getClass() == InvalidSyntaxException.class )
+            {
+                throw (InvalidSyntaxException) e.getException();
+            }
+
+            throw (IOException) e.getException();
+        }
+
+        return configurations;
+    }
+
+    
+    
+    private ConfigurationDictionary load( final String pid ) throws IOException
+    {
+        try
+        {
+            return  AccessController.doPrivileged( new PrivilegedExceptionAction<ConfigurationDictionary>()
+            {
+                public ConfigurationDictionary run() throws IOException
+                {
+                    return configurationStore.retrieve( pid );
+                }
+            } );
+        }
+        catch ( PrivilegedActionException e )
+        {
+            throw (IOException) e.getException();
+        }
+    }
+    
+    private String generatePid( final String factoryPid ) throws IOException
+    {
+        try
+        {
+            return AccessController.doPrivileged( new PrivilegedExceptionAction<String>()
+            {
+                public String run() throws IOException
+                {
+                    return configurationStore.generatePid( factoryPid );
+                }
+            } );
+        }
+        catch ( PrivilegedActionException e )
+        {
+            throw (IOException) e.getException();
+        }
+    }
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationAdminServiceFactory.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationAdminServiceFactory.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationAdminServiceFactory.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationAdminServiceFactory.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,87 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.configuration.impl;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 
+ * <p>A <tt>ConfigurationAdminServiceFactory</tt> is a {@link ServiceFactory} that provides 
+ * {@link ConfigurationAdmin} Service instances to the framework. 
+ * 
+ * <tt>ConfigurationAdminServiceFactory</tt> dispatches Configuration UpdateEvents to be handled 
+ * by seperate process running in another thread. 
+ * 
+ * <tt>ConfigurationAdminServiceFactory</tt> is the main component specified by the Spring-OSGi metadata.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ConfigurationAdminServiceFactory implements ServiceFactory
+{
+    /** the log for this class */
+    private static final Logger log = LoggerFactory.getLogger( ConfigurationAdminServiceFactory.class );
+   
+    private ConfigurationStore configurationStore;//Injected
+    /**
+     * 
+     * ServiceFactory implemented method that is invoked by the 
+     * framework to get a ConfigurationAdmin for the bundle.
+     *
+     * @param bundle
+     * @param serviceRegistration
+     * @return Configuration admin implementation.
+     */
+     public Object getService(Bundle bundle, ServiceRegistration serviceRegistration)
+    {
+        log.debug("Received a ServiceFactory.getService() call");
+        return new ConfigurationAdminImpl(configurationStore, bundle);
+    }
+
+    /**
+     * ServiceFactory implemented method that is invoked by the framework to remove 
+     * a ConfigurationAdmin for the bundle.
+     * 
+     * Can be used for tracking bundles that have unset a ConfigurationAdmin Service.
+     * 
+     * @param bundle
+     * @param registration
+     * @param service
+     */
+    public void ungetService(Bundle bundle, ServiceRegistration registration,
+            Object service)
+    {
+        log.debug("ungetting Service for {} not supported at this time.",registration.getReference());
+        
+    }
+
+    
+    /**
+     * @param configurationStore 
+     */
+    public void setConfigurationStore( ConfigurationStore configurationStore )
+    {
+        this.configurationStore = configurationStore;
+    }
+
+
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationDictionary.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationDictionary.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationDictionary.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationDictionary.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,540 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.configuration.impl;
+
+import java.lang.reflect.Array;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Vector;
+
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * A <tt>ConfigurationDictionary</tt> implements the datatype restrictions, 
+ * and case insensitive lookup, required of configuration dictionaries in 
+ * the Configuration Admin.
+ */
+public final class ConfigurationDictionary extends Dictionary<String, Object>
+{
+    public static final String DYNAMIC_BUNDLE_LOCATION = "dynamic.service.bundleLocation";
+    /**
+     * Allowed object types.
+     */
+    private final static Map<Class, Class> allowedObjectTypes = new HashMap<Class, Class>();
+
+    static
+    {
+        allowedObjectTypes.put( Integer.class, Integer.class );
+        allowedObjectTypes.put( Short.class, Short.class );
+        allowedObjectTypes.put( Long.class, Long.class );
+        allowedObjectTypes.put( String.class, String.class );
+        allowedObjectTypes.put( Float.class, Float.class );
+        allowedObjectTypes.put( Double.class, Double.class );
+        allowedObjectTypes.put( Byte.class, Byte.class );
+        allowedObjectTypes.put( Character.class, Character.class );
+        allowedObjectTypes.put( Boolean.class, Boolean.class );
+    }
+
+    /**
+     * Allowed primitive types in arrays.
+     */
+    private final static Map<Class, Class> allowedPrimitiveTypes = new HashMap<Class, Class>();
+
+    static
+    {
+        allowedPrimitiveTypes.put( Integer.TYPE, Integer.TYPE );
+        allowedPrimitiveTypes.put( Short.TYPE, Short.TYPE );
+        allowedPrimitiveTypes.put( Long.TYPE, Long.TYPE );
+        allowedPrimitiveTypes.put( Float.TYPE, Float.TYPE );
+        allowedPrimitiveTypes.put( Double.TYPE, Double.TYPE );
+        allowedPrimitiveTypes.put( Byte.TYPE, Byte.TYPE );
+        allowedPrimitiveTypes.put( Character.TYPE, Character.TYPE );
+        allowedPrimitiveTypes.put( Boolean.TYPE, Boolean.TYPE );
+    }
+
+    private final static Map<Class, Class> classToPrimitiveType = new HashMap<Class, Class>();
+
+    static
+    {
+        classToPrimitiveType.put( Integer.class, Integer.TYPE );
+        classToPrimitiveType.put( Short.class, Short.TYPE );
+        classToPrimitiveType.put( Long.class, Long.TYPE );
+        classToPrimitiveType.put( Float.class, Float.TYPE );
+        classToPrimitiveType.put( Double.class, Double.TYPE );
+        classToPrimitiveType.put( Byte.class, Byte.TYPE );
+        classToPrimitiveType.put( Character.class, Character.TYPE );
+        classToPrimitiveType.put( Boolean.class, Boolean.TYPE );
+    }
+
+    private String bundleLocation = null;
+    
+    private boolean isStaticBound = false;
+    /**
+     * Mapping of keys in lowercase to the case they had when added to the
+     * dictionary.
+     */
+    final Hashtable<String, Object> lowercaseToOriginalCase;
+
+    /**
+     * A dictionary holding the key-value pairs of the configuration with
+     * the keys in the original case they were entered in.
+     */
+    final Dictionary<String,Object> originalCase;
+
+    public ConfigurationDictionary()
+    {
+        this( new Hashtable<String,Object>() );
+    }
+
+    /**
+     * Construct a ConfigurationDictionary given an ordinary Dictionary.
+     * 
+     * @param dictionary The original dictionary.
+     */
+    public ConfigurationDictionary( Dictionary<String,Object> dictionary )
+    {
+        this.lowercaseToOriginalCase = new Hashtable<String, Object>();
+        this.originalCase = dictionary;
+        updateLowercaseToOriginalCase();
+    }
+
+    
+    @SuppressWarnings("unchecked")
+    private ConfigurationDictionary( ConfigurationDictionary original )
+    {
+        this.originalCase = copyDictionary( original.originalCase );
+        this.lowercaseToOriginalCase = (Hashtable) original.lowercaseToOriginalCase.clone();
+    }
+
+    public Enumeration<Object> elements()
+    {
+        return originalCase.elements();
+    }
+
+    public Object get( Object key )
+    {
+        Object val = originalCase.get( key );
+
+        if ( val != null )
+        {
+            return val;
+        }
+
+        String lowercaseKey = ( (String) key ).toLowerCase();
+        String originalCaseKey = (String) lowercaseToOriginalCase.get( lowercaseKey );
+
+        if ( originalCaseKey != null )
+        {
+            key = originalCaseKey;
+        }
+
+        val = originalCase.get( key );
+
+        return val;
+    }
+
+    public boolean isEmpty()
+    {
+        return originalCase.isEmpty();
+    }
+
+    public Enumeration<String> keys()
+    {
+        return originalCase.keys();
+    }
+
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer( getClass().getName() + " [ " );
+
+        for ( Enumeration e = keys(); e.hasMoreElements(); )
+        {
+            Object key = e.nextElement();
+            Object val = get( key );
+
+            sb.append( key + "=" + val );
+            if ( e.hasMoreElements() )
+            {
+                sb.append( ", " );
+            }
+        }
+
+        sb.append( " ]" );
+
+        return sb.toString();
+    }
+
+    public Object put( String key, Object value )
+    {
+        String lowercaseKey = ( (String) key ).toLowerCase();
+        String originalCaseKey = (String) lowercaseToOriginalCase.get( lowercaseKey );
+
+        if ( originalCaseKey != null )
+        {
+            key = originalCaseKey;
+        }
+
+        Object o = originalCase.put((String) key, value );
+
+        if ( originalCaseKey == null )
+        {
+            updateLowercaseToOriginalCase( (String) key );
+        }
+
+        return o;
+    }
+
+    public Object remove( Object key )
+    {
+        String lowercaseKey = ( (String) key ).toLowerCase();
+
+        if ( !lowercaseToOriginalCase.containsKey( lowercaseKey ) )
+        {
+            return null;
+        }
+
+        String originalCaseKey = (String) lowercaseToOriginalCase.remove( lowercaseKey );
+
+        return originalCase.remove( originalCaseKey );
+    }
+
+    public int size()
+    {
+        return originalCase.size();
+    }
+
+    Dictionary getOriginal()
+    {
+        return originalCase;
+    }
+    
+    public String getFactoryPid(){
+        Object o = originalCase.get(ConfigurationAdmin.SERVICE_FACTORYPID);
+        return o!=null?(String)o:null;
+    }
+    
+    public String getServicePid(){
+        Object o = originalCase.get(Constants.SERVICE_PID);
+        return o!=null?(String)o:null;
+    }
+
+
+    public ConfigurationDictionary createCopy()
+    {
+        return new ConfigurationDictionary( this );
+    }
+
+//    /**
+//     * 
+//     * @deprecated
+//     *
+//     * @return
+//     */
+//    public ConfigurationDictionary createCopyAndRemoveLocation()
+//    {
+//        ConfigurationDictionary cd = createCopy();
+//        cd.remove( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+//        cd.remove( DYNAMIC_BUNDLE_LOCATION );
+//
+//        return cd;
+//    }
+
+    private void updateLowercaseToOriginalCase()
+    {
+        Enumeration keys = originalCase.keys();
+
+        while ( keys.hasMoreElements() )
+        {
+            String originalKey = (String) keys.nextElement();
+            updateLowercaseToOriginalCase( originalKey );
+        }
+    }
+
+    private void updateLowercaseToOriginalCase( String originalKey )
+    {
+        if ( originalKey == null )
+        {
+            return;
+        }
+
+        String lowercaseKey = originalKey.toLowerCase();
+
+        if ( !lowercaseToOriginalCase.containsKey( lowercaseKey ) )
+        {
+            lowercaseToOriginalCase.put( lowercaseKey, originalKey );
+        }
+    }
+
+    static public ConfigurationDictionary createDeepCopy( Dictionary<String, Object> in )
+    {
+        Hashtable<String, Object> h = copyDictionary( in );
+        return new ConfigurationDictionary( h );
+    }
+
+    static public Hashtable<String, Object> copyDictionary( Dictionary<String, Object> in )
+    {
+        if ( in == null )
+        {
+            return null;
+        }
+
+        Hashtable<String, Object> out = new Hashtable<String, Object>();
+        Enumeration<String> keys = in.keys();
+
+        while ( keys.hasMoreElements() )
+        {
+            String key = keys.nextElement();
+            Object origVal = in.get( key );
+            Object val = copyValue( origVal );
+
+            String s =  key;
+            String lower = s.toLowerCase();
+
+            if ( !s.equals( lower ) )
+            {
+                Object lowerVal = in.get( lower );
+
+                if ( null != lowerVal )
+                {
+                    key = lower;
+                }
+            }
+            out.put( key, val );
+        }
+        return out;
+    }
+
+    @SuppressWarnings("unchecked")
+    static private Object copyValue( Object in )
+    {
+        if ( in == null )
+        {
+            return null;
+        }
+
+        if ( in.getClass().isArray() )
+        {
+            return copyArray( in );
+        }
+        else
+            if ( in instanceof Vector )
+            {
+                return copyVector( (Vector) in );
+            }
+            else
+            {
+                return in;
+            }
+    }
+
+    static private Vector<Object> copyVector( Vector<Object> in )
+    {
+        if ( in == null )
+        {
+            return null;
+        }
+
+        Vector<Object> out = new Vector<Object>();
+        Enumeration elements = in.elements();
+
+        while ( elements.hasMoreElements() )
+        {
+            out.addElement( copyValue( elements.nextElement() ) );
+        }
+
+        return out;
+    }
+
+    static private Object copyArray( Object in )
+    {
+        if ( in == null )
+        {
+            return null;
+        }
+
+        int length = Array.getLength( in );
+
+        Object out = Array.newInstance( in.getClass().getComponentType(), length );
+
+        for ( int ii = 0; ii < length; ++ii )
+        {
+            Array.set( out, ii, copyValue( Array.get( in, ii ) ) );
+        }
+
+        return out;
+    }
+
+    public static void validateDictionary( Dictionary dictionary ) throws IllegalArgumentException
+    {
+        if ( dictionary == null )
+        {
+            return;
+        }
+
+        Enumeration keys = dictionary.keys();
+
+        while ( keys.hasMoreElements() )
+        {
+            Object key = keys.nextElement();
+
+            if ( key.getClass() != String.class )
+            {
+                throw new IllegalArgumentException( "The key " + key + " is not of type java.lang.String." );
+            }
+
+            try
+            {
+                validateValue( dictionary.get( key ) );
+            }
+            catch ( IllegalArgumentException e )
+            {
+                throw new IllegalArgumentException( "The value for key " + key + " is not of correct type: "
+                        + e.getMessage() );
+            }
+        }
+    }
+
+    static private void validateValue( Object value ) throws IllegalArgumentException
+    {
+        if ( value == null )
+        {
+            return;
+        }
+
+        Class valueClass = value.getClass();
+
+        if ( valueClass.isArray() )
+        {
+            validateArray( value );
+        }
+        else
+            if ( valueClass == Vector.class )
+            {
+                validateVector( (Vector) value );
+            }
+            else
+            {
+                if ( !allowedObjectTypes.containsKey( valueClass ) )
+                {
+                    throw new IllegalArgumentException( valueClass.toString() + " is not an allowed type." );
+                }
+            }
+    }
+
+    static private void validateArray( Object array )
+    {
+        Class componentType = array.getClass().getComponentType();
+
+        int length = Array.getLength( array );
+
+        if ( componentType.isArray() || componentType == Vector.class )
+        {
+            for ( int ii = 0; ii < length; ++ii )
+            {
+                Object o = Array.get( array, ii );
+
+                if ( o != null )
+                {
+                    Class objectClass = o.getClass();
+
+                    if ( objectClass != componentType )
+                    {
+                        throw new IllegalArgumentException( "Objects with different type in array. " + "Found "
+                                + objectClass.toString() + " " + "Expected " + componentType.toString() );
+                    }
+                    validateValue( o );
+                }
+            }
+        }
+        else
+        {
+            if ( !allowedPrimitiveTypes.containsKey( componentType ) && !allowedObjectTypes.containsKey( componentType ) )
+            {
+                throw new IllegalArgumentException( "Illegal component type for arrays: " + componentType.toString() );
+            }
+
+            for ( int ii = 0; ii < length; ++ii )
+            {
+                Object o = Array.get( array, ii );
+
+                if ( o != null )
+                {
+                    Class objectClass = o.getClass();
+
+                    if ( componentType.isPrimitive() )
+                    {
+                        objectClass = (Class) classToPrimitiveType.get( objectClass );
+                    }
+
+                    if ( objectClass != componentType )
+                    {
+                        throw new IllegalArgumentException( "Objects with different type in array. " + "Found "
+                                + objectClass.toString() + " " + "Expected " + componentType.toString() );
+                    }
+                }
+            }
+        }
+    }
+
+    static private void validateVector( Vector vector )
+    {
+        for ( int ii = 0; ii < vector.size(); ++ii )
+        {
+            Object element = vector.elementAt( ii );
+            validateValue( element );
+        }
+    }
+
+    /**
+     * @return the bundleLocation
+     */
+    String getBundleLocation()
+    {
+        return bundleLocation;
+    }
+
+    /**
+     * @param bundleLocation the bundleLocation to set
+     */
+    void setBundleLocation( String bundleLocation )
+    {
+        this.bundleLocation = bundleLocation;
+    }
+
+    /**
+     * @return the isStaticBound
+     */
+    boolean isStaticBound()
+    {
+        return isStaticBound;
+    }
+
+    /**
+     * @param isStaticBound the isStaticBound to set
+     */
+    void setStaticBound( boolean isStaticBound )
+    {
+        this.isStaticBound = isStaticBound;
+    }
+
+    
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationImpl.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationImpl.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationImpl.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/impl/ConfigurationImpl.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,575 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   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 org.apache.configuration.impl;
+
+
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Dictionary;
+
+import javax.naming.NameNotFoundException;
+import javax.naming.directory.SchemaViolationException;
+
+import org.apache.configuration.dao.ConfigurationDaoException;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationPermission;
+import org.osgi.service.cm.ConfigurationPlugin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * 
+ * ConfigurationImpl is an implementation of the OSGi Service Platform Release 4; 104.15.2.
+ * 
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ConfigurationImpl implements Configuration
+{
+    private static final Logger log = LoggerFactory.getLogger( ConfigurationImpl.class );
+
+    private final ConfigurationStore configurationStore;
+    private final String factoryPid;
+    private final String servicePid;
+
+   
+    private boolean deleted = false;
+    private boolean updateCalled = false;
+
+    private ConfigurationDictionary configurationDictionary;
+
+    /**
+     * 
+     * Creates a new instance of ConfigurationImpl.
+     *
+     * @param configurationStore
+     * @param configurationDictionary
+     */
+    public ConfigurationImpl( ConfigurationStore configurationStore, ConfigurationDictionary properties )
+    {
+        if(properties == null){
+            throw new IllegalArgumentException("configurationDictionary cannot be null");
+        }
+
+        this.factoryPid = ( String ) properties.get( ConfigurationAdmin.SERVICE_FACTORYPID );
+        this.servicePid = ( String ) properties.get( Constants.SERVICE_PID );
+
+        this.configurationStore = configurationStore;
+        this.configurationDictionary = ConfigurationDictionary.createDeepCopy( properties );
+    }
+
+    /**
+     * 
+     * Creates a new instance of ConfigurationImpl.
+     *
+     * @param configurationStore
+     * @param factoryPid
+     * @param servicePid
+     */
+    public ConfigurationImpl( ConfigurationStore configurationDao, String factoryPid, String servicePid )
+    {
+        this( configurationDao, factoryPid, servicePid, null );
+    }
+
+
+    /**
+     * 
+     * Creates a new instance of ConfigurationImpl.
+     *
+     * @param configurationStore
+     * 
+     * @param factoryPid
+     * @param servicePid
+     * @param configurationDictionary
+     */
+    public ConfigurationImpl( ConfigurationStore configurationDao, String factoryPid, String servicePid,
+        ConfigurationDictionary configurationDictionary )
+    {
+      
+        this.configurationStore = configurationDao;
+        this.factoryPid = factoryPid;
+        this.servicePid = servicePid;
+        
+
+        if ( configurationDictionary == null )
+        {
+            this.configurationDictionary = new ConfigurationDictionary();
+            
+            if(factoryPid!=null){
+                this.configurationDictionary.put( ConfigurationAdmin.SERVICE_FACTORYPID, factoryPid);
+            }
+            if(servicePid!=null){
+                this.configurationDictionary.put( Constants.SERVICE_PID, servicePid);
+            }
+        }
+        else
+        {
+            this.configurationDictionary = ConfigurationDictionary.createDeepCopy( configurationDictionary );
+        }
+    }
+
+
+    
+
+
+    /**
+     * Delete this <code>Configuration</code> object.
+     * 
+     * Removes this configuration object from the persistent configurationStore. Notify
+     * asynchronously the corresponding Managed Service or Managed Service
+     * Factory. A <code>ManagedService</code> object is notified by a call to
+     * its <code>updated</code> method with a <code>null</code> configurationDictionary
+     * argument. A <code>ManagedServiceFactory</code> object is notified by a
+     * call to its <code>deleted</code> method.
+     * 
+     * <p>
+     * Also intiates an asynchronous call to all
+     * <code>ConfigurationListener</code>s with a
+     * <code>ConfigurationEvent.CM_DELETED</code> event.
+     * 
+     * <p>
+     * OSGi Service Platform Release 4; 104.15.2.1
+     * 
+     * @throws IOException If delete fails
+     * @throws IllegalStateException if this configuration has been deleted
+     */
+    public void delete() throws IOException
+    {
+        throwIfDeleted();
+        delete( this );
+        deleted = true;
+    }
+
+
+    /**
+     * Equality is defined to have equal PIDs
+     * 
+     * Two Configuration objects are equal when their PIDs are equal.
+     * 
+     * <p>
+     * OSGi Service Platform Release 4; 104.15.2.2
+     * 
+     * @param other <code>Configuration</code> object to compare against
+     * @return <code>true</code> if equal, <code>false</code> if not a
+     *         <code>Configuration</code> object or one with a different PID.
+     */
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( obj != null && obj instanceof Configuration )
+        {
+            Configuration target = ( Configuration ) obj ;
+            if(this.getPid() !=null && target.getPid() !=null ){
+                return this.getPid().equals( target.getPid()) ;
+            }else if (this.getPid() ==null && target.getPid() ==null){
+                return true;
+            }
+            
+        }
+        return false;
+    }
+
+
+    /**
+     * Get the bundle location.
+     * 
+     * Returns the bundle location to which this configuration is bound, or
+     * <code>null</code> if it is not yet bound to a bundle location.
+     * 
+     * <p>
+     * OSGi Service Platform Release 4; 104.15.2.3
+     * 
+     * @return location to which this configuration is bound, or
+     *         <code>null</code>.
+     * @throws IllegalStateException If this <code>Configuration</code> object
+     *         has been deleted.
+     * @throws SecurityException If the caller does not have
+     *         <code>ConfigurationPermission[*,CONFIGURE]</code>.
+     */
+    public String getBundleLocation()
+    {
+        Object sm = System.getSecurityManager();
+
+        if (sm != null)
+        {
+            ((SecurityManager) sm).checkPermission(new ConfigurationPermission("*",
+                ConfigurationPermission.CONFIGURE));
+        }
+        throwIfDeleted();
+        return configurationDictionary.getBundleLocation();
+    }
+
+
+    /**
+     * For a factory configuration return the PID of the corresponding Managed
+     * Service Factory, else return <code>null</code>.
+     * 
+     * <p>
+     * OSGi Service Platform Release 4; 104.15.2.4
+     * 
+     * @return factory PID or <code>null</code>
+     * @throws IllegalStateException if this configuration has been deleted
+     */
+    public String getFactoryPid()
+    {
+        throwIfDeleted();
+        return factoryPid;
+    }
+
+
+    /**
+     * Get the PID for this <code>Configuration</code> object.
+     * 
+     * <p>
+     * OSGi Service Platform Release 4; 104.15.2.5
+     * 
+     * @return the PID for this <code>Configuration</code> object.
+     * @throws IllegalStateException if this configuration has been deleted
+     */
+    public String getPid()
+    {
+        throwIfDeleted();
+        return servicePid;
+    }
+
+
+    /**
+     * Return the configurationDictionary of this <code>Configuration</code> object.
+     * 
+     * The <code>Dictionary</code> object returned is a private copy for the
+     * caller and may be changed without influencing the stored configuration.
+     * The keys in the returned dictionary are case insensitive and are always
+     * of type <code>String</code>.
+     * 
+     * <p>
+     * If called just after the configuration is created and before update has
+     * been called, this method returns <code>null</code>.
+     * 
+     * <p>
+     * OSGi Service Platform Release 4; 104.15.2.6
+     * 
+     * @return A private copy of the configurationDictionary for the caller or
+     *         <code>null</code>. These configurationDictionary must not contain the
+     *         "service.bundleLocation" property. The value of this property may
+     *         be obtained from the <code>getBundleLocation</code> method.
+     * @throws IllegalStateException if this configuration has been deleted
+     */
+    public Dictionary getProperties()
+    {
+        throwIfDeleted();
+
+        if ( configurationDictionary == null || !updateCalled)
+        {
+            return null;
+        }
+
+        return configurationDictionary.createCopy();
+    }
+
+
+    /**
+     * Hash code is based on PID.
+     * 
+     * The hashcode for two Configuration objects must be the same when the
+     * Configuration PID's are the same.
+     * 
+     * <p>
+     * OSGi Service Platform Release 4; 104.15.2.7
+     * 
+     * @return hash code for this Configuration object
+     */
+    @Override
+    public int hashCode()
+    {
+        return servicePid != null ? servicePid.hashCode() : super.hashCode();
+    }
+
+
+    /**
+     * Bind this <code>Configuration</code> object to the specified bundle
+     * location.
+     * 
+     * If the bundleLocation parameter is <code>null</code> then the
+     * <code>Configuration</code> object will not be bound to a location. It
+     * will be set to the bundle's location before the first time a Managed
+     * Service/Managed Service Factory receives this <code>Configuration</code>
+     * object via the updated method and before any plugins are called. The
+     * bundle location will be set persistently.
+     * 
+     * <p>
+     * OSGi Service Platform Release 4; 104.15.2.8
+     * 
+     * @param bundleLocation a bundle location or <code>null</code>
+     * @throws IllegalStateException If this configuration has been deleted.
+     * @throws SecurityException If the caller does not have
+     *         <code>ConfigurationPermission[*,CONFIGURE]</code>.
+     */
+    public void setBundleLocation( String bundleLocation )
+    {
+        Object sm = System.getSecurityManager();
+
+        if (sm != null)
+        {
+            ((SecurityManager) sm).checkPermission(new ConfigurationPermission("*",
+                ConfigurationPermission.CONFIGURE));
+        }
+        throwIfDeleted();
+
+        configurationDictionary.setBundleLocation( bundleLocation );
+        configurationDictionary.setStaticBound( true );
+    }
+
+
+
+    /**
+     * Update the configurationDictionary of this <code>Configuration</code> object.
+     * 
+     * Stores the configurationDictionary in persistent storage after adding or overwriting
+     * the following configurationDictionary:
+     * <ul>
+     * <li>"service.pid" : is set to be the PID of this configuration.</li>
+     * <li>"service.factoryPid" : if this is a factory configuration it is set
+     * to the factory PID else it is not set.</li>
+     * </ul>
+     * These system configurationDictionary are all of type <code>String</code>.
+     * 
+     * <p>
+     * If the corresponding Managed Service/Managed Service Factory is
+     * registered, its updated method must be called asynchronously. Else, this
+     * callback is delayed until aforementioned registration occurs.
+     * 
+     * <p>
+     * Also intiates an asynchronous call to all
+     * <code>ConfigurationListener</code>s with a
+     * <code>ConfigurationEvent.CM_UPDATED</code> event.
+     * 
+     * <p>
+     * OSGi Service Platform Release 4; 104.15.2.9
+     * 
+     * @param configurationDictionary the new set of configurationDictionary for this configuration
+     * @throws IOException if update cannot be made persistent
+     * @throws IllegalArgumentException if the <code>Dictionary</code> object
+     *         contains invalid configuration types or contains case variants of
+     *         the same key name.
+     * @throws IllegalStateException if this configuration has been deleted
+     */
+    @SuppressWarnings("unchecked")
+    public void update( Dictionary properties ) throws IOException
+    {
+        throwIfDeleted();
+
+        ConfigurationDictionary.validateDictionary( properties );
+
+        ConfigurationDictionary old = this.configurationDictionary;
+
+        if ( properties == null )
+        {
+            this.configurationDictionary = new ConfigurationDictionary();
+        }
+        else
+        {
+            this.configurationDictionary = ConfigurationDictionary.createDeepCopy( properties );
+        }
+
+        try
+        {
+            update();
+        }
+        catch ( IOException e )
+        {
+            this.configurationDictionary = old;
+            throw e;
+        }
+        catch ( ConfigurationDaoException e )
+        {
+            log.error( "Error while updating configurationDictionary.", e );
+            this.configurationDictionary = old;
+            throw new IOException(e.getMessage()+" Because: "+e.getCause());
+        }
+    }
+
+
+    /**
+     * Update the <code>Configuration</code> object with the current
+     * configurationDictionary.
+     * 
+     * Initiate the <code>updated</code> callback to the Managed Service or
+     * Managed Service Factory with the current configurationDictionary asynchronously.
+     * 
+     * <p>
+     * This is the only way for a bundle that uses a Configuration Plugin
+     * service to initate a callback. For example, when that bundle detects a
+     * change that requires an update of the Managed Service or Managed Service
+     * Factory via its <code>ConfigurationPlugin</code> object.
+     * 
+     * <p>
+     * OSGi Service Platform Release 4; 104.15.2.10
+     * 
+     * @see ConfigurationPlugin
+     * @throws IOException if update cannot access the configurationDictionary in persistent
+     *         storage
+     * @throws IllegalStateException if this configuration has been deleted
+     */
+    public void update() throws IOException
+    {
+        throwIfDeleted();
+        ensureAutoPropertiesAreWritten();
+        try
+        {
+            update( this );
+        }
+        catch ( RuntimeException e )
+        {
+           IOException ioe;
+           if(e.getCause()!=null){
+               ioe = new IOException(e.getCause().getMessage());
+               
+           }else{
+               ioe = new IOException(e.getMessage());
+           }
+           throw ioe;
+        }
+        updateCalled=true;
+    }
+
+    
+
+    /**
+     * 
+     * delete the config from the backend.
+     *
+     * @param config
+     * @throws IOException
+     */
+    void delete( final ConfigurationImpl config ) throws IOException
+    {
+        if(configurationDictionary.isEmpty()){
+            throw new IOException("Dictionary is empty.");
+        }
+        
+        try
+        {
+            AccessController.doPrivileged( new PrivilegedExceptionAction<Void>()
+            {
+                public Void run() throws IOException
+                {
+                    configurationStore.delete( config.getPid() );
+
+                    return null;
+                }
+            } );
+        }
+        catch ( PrivilegedActionException e )
+        {
+            throw ( IOException ) e.getException();
+        }
+        catch (ConfigurationDaoException e)
+        {
+            if(e.getCause()!=null){
+                if(e.getCause() instanceof NameNotFoundException)
+                {
+                throw new IOException("Could not delete the configuration because a persisted configuration with pid="+config.servicePid+" was not found.");
+                }
+                else
+                {
+                    throw new IllegalStateException(e.getMessage(), e.getCause());  
+                }
+            }else{
+                throw new IllegalStateException(e.getMessage());
+            }
+            
+        }
+    }
+
+
+    void update( final ConfigurationImpl config ) throws IOException
+    {
+        try
+        {
+            AccessController.doPrivileged( new PrivilegedExceptionAction<Void>()
+            {
+                public Void run() throws IOException
+                {
+                    try{
+                        configurationStore.update( config.getConfigurationDictionary() );
+                    }catch(ConfigurationDaoException e){
+                        log.error( "Failed to update.",e );
+                        
+                        if(e.getCause()!=null && e.getCause() instanceof SchemaViolationException){
+                            IllegalArgumentException e1 = 
+                                new IllegalArgumentException(e.getMessage(),e.getCause());
+                            throw e1;
+                        }else{
+                            throw new IOException(e.getMessage()+" Because: "+e.getCause());
+                        }
+                       
+                    }
+                    return null;
+                }
+            } );
+        }
+        catch ( PrivilegedActionException e )
+        {
+            throw ( IOException ) e.getException();
+        }
+        
+    }
+
+
+    void ensureAutoPropertiesAreWritten()
+    {
+        if ( configurationDictionary == null )
+        {
+            return;
+        }
+
+        configurationDictionary.put( Constants.SERVICE_PID, getPid() );
+
+        if ( getFactoryPid() != null )
+        {
+            configurationDictionary.put( ConfigurationAdmin.SERVICE_FACTORYPID, getFactoryPid() );
+        }
+
+        if ( getBundleLocation() != null )
+        {
+            configurationDictionary.put( ConfigurationAdmin.SERVICE_BUNDLELOCATION, getBundleLocation() );
+        }
+    }
+
+
+    private ConfigurationDictionary getConfigurationDictionary()
+    {
+        return configurationDictionary;
+    }
+
+
+    private void throwIfDeleted()
+    {
+        if ( deleted )
+        {
+            throw new IllegalStateException( "Configuration for " + servicePid + " has been deleted." );
+        }
+    }
+
+}



Mime
View raw message