You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by jc...@apache.org on 2007/01/29 21:38:29 UTC

svn commit: r501176 [2/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/...

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/JndiConfigurationDaoNotifierImpl.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/JndiConfigurationDaoNotifierImpl.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/JndiConfigurationDaoNotifierImpl.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/JndiConfigurationDaoNotifierImpl.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,265 @@
+/*
+ *   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.dao.jndi.impl;
+
+import javax.naming.Binding;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.event.EventContext;
+import javax.naming.event.EventDirContext;
+import javax.naming.event.NamingEvent;
+import javax.naming.event.NamingExceptionEvent;
+import javax.naming.spi.InitialContextFactory;
+
+import org.apache.configuration.dao.ConfigurationDaoListener;
+import org.apache.configuration.dao.ConfigurationDaoListener.ChangeType;
+import org.apache.configuration.dao.jndi.ContextMapping;
+import org.apache.configuration.dao.jndi.JndiConfigurationDaoNotifier;
+import org.apache.configuration.dao.jndi.NameMapping;
+import org.apache.configuration.impl.ConfigurationDictionary;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 
+ * JndiConfigurationDaoNotifierImpl adapts directory events to configuration events.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class JndiConfigurationDaoNotifierImpl implements JndiConfigurationDaoNotifier
+{
+
+
+    /** the log for this class */
+    private static final Logger log = LoggerFactory.getLogger( JndiConfigurationDaoNotifierImpl.class );
+
+    private final String name;
+    private ConfigurationDaoListener configurationChangeListener;
+    private final ContextMapping contextMapping;
+    private final NameMapping nameMapper;
+    private final InitialContextFactory initialContextFactory;
+    
+    EventDirContext eventDirContext = null;
+
+    /**
+     * Creates a new instance of JndiConfigurationDaoNotifierImpl.
+     * @deprecated pass a ContextMapping value into the other constructor
+     */
+    public JndiConfigurationDaoNotifierImpl()
+    {
+        this(new ContextMapper(), null, null);
+    }
+
+    /**
+     * 
+     * Creates a new instance of JndiConfigurationDaoNotifierImpl.
+     * The name will be used to identify the instance.
+     * 
+     * @param name
+     */
+    public JndiConfigurationDaoNotifierImpl(ContextMapping contextMapping,NameMapping nameMapper, InitialContextFactory initialContextFactory )
+    {
+        this.contextMapping = contextMapping;
+        this.name = "Listener-" + System.currentTimeMillis();
+        this.nameMapper=nameMapper;
+        this.initialContextFactory=initialContextFactory;
+    }
+
+    
+    public void removeConfigurationListener()
+    {
+        this.configurationChangeListener = null;
+        try
+        {
+            eventDirContext.removeNamingListener( this );
+        }
+        catch ( NamingException e )
+        {
+           log.error( "Failed to remove this naming listener.",e );
+        }finally{
+            try
+            {
+                if(eventDirContext!=null){
+                    eventDirContext.close();
+                }
+            }
+            catch ( NamingException e )
+            {
+                log.error( "Failed to close the eventDirContext.",e );
+            }finally{
+                eventDirContext = null;
+            }
+        }
+        
+        
+    }
+
+    public void setConfigurationListener( ConfigurationDaoListener configurationListener )
+    {
+        this.configurationChangeListener = configurationListener;
+        log.debug( "Adding a listener {}",configurationListener );
+        if(eventDirContext==null){
+            try
+            {
+                DirContext dirContext = (DirContext)initialContextFactory.getInitialContext( null) ;
+                eventDirContext = (EventDirContext)dirContext.lookup( "" );
+                eventDirContext.addNamingListener( nameMapper.getSearchBaseName(), EventContext.SUBTREE_SCOPE, this );
+            }
+            catch ( NamingException e )
+            {
+               log.error( "Failed to set a configurationDaoListener.",e );
+               
+            }finally{
+                if(eventDirContext!=null){
+                    try
+                    {
+                        eventDirContext.close();
+                    }
+                    catch ( NamingException e )
+                    {
+                        //ignore
+                    }
+                }
+            }
+        }
+        
+        
+    }
+   
+    
+    public void objectAdded( NamingEvent evt )
+    {
+        log.debug( "Jndi bindings {}. ", evt.getNewBinding() );
+        if ( configurationChangeListener != null )
+        {
+            try
+            {
+                ConfigurationDictionary newConfig = transform( evt.getNewBinding() );
+                log.debug( "Translated configuration {}",newConfig );
+                configurationChangeListener.configurationChanged( ChangeType.CREATED, newConfig );
+            } catch (NamingException ne)
+            {
+                log.error( ne.getMessage(), ne );
+            }
+        }
+    }
+
+    /**
+     * When an object has been added, getOldBinding() will always return null
+     * because it wasn't in the namespace prior to its being added.
+     * @todo Implement method.
+     */
+    public void objectRemoved( NamingEvent evt )
+    {
+        log.debug( "Jndi bindings {}. ", evt.getOldBinding() );
+        if ( configurationChangeListener != null )
+        {
+            try
+            {
+                ConfigurationDictionary oldConfig = transform( evt.getOldBinding() );
+                log.debug( "Translated configuration {}",oldConfig );
+                configurationChangeListener.configurationChanged(ChangeType.DELETED, oldConfig );
+            } catch (NamingException ne)
+            {
+                log.error( ne.getMessage(), ne );
+            }
+        }
+    }
+
+    /**
+     * When an object has been removed, getNewBinding() will always be null
+     * because it won't be in the namespace after it has been removed.
+     */
+    public void objectRenamed( NamingEvent evt )
+    {
+        
+        log.debug( "Renamed {} to {}", evt.getOldBinding(), evt.getNewBinding() );
+        
+        if ( configurationChangeListener != null )
+        {
+            try
+            {
+                ConfigurationDictionary renamedConfig = transform( evt.getNewBinding() );
+                
+                log.debug( "Translated configuration {}",renamedConfig );
+                configurationChangeListener.configurationChanged( ChangeType.UPDATED,  renamedConfig );
+            } catch (NamingException ne)
+            {
+                log.error( ne.getMessage(), ne );
+            }
+        }
+    }
+
+    public void objectChanged( NamingEvent evt )
+    {
+        log.debug( name + " >>> directory object changed: " + evt.getNewBinding() + " from "
+                + evt.getOldBinding() );
+
+        if ( configurationChangeListener != null )
+        {
+            try
+            {
+                ConfigurationDictionary changedConfig = transform( evt.getNewBinding() );
+                log.debug( "Translated configuration {}",changedConfig );
+                configurationChangeListener.configurationChanged( ChangeType.UPDATED,changedConfig );
+            } catch (NamingException ne)
+            {
+                log.error( ne.getMessage(), ne );
+            }
+        }
+    }
+
+    public void namingExceptionThrown( NamingExceptionEvent evt )
+    {
+        log.error( name + " >>> exception: ", evt.getException() );
+    }
+
+    /**
+     * transform the binding to a Dictionary.
+     * 
+     * LDAP attribute types do not contain periods, but some of the OSGi constants do.
+     * Conversion mapping once done in this method has been superceded by a more extensible set of
+     * mappings done by a ConfigurationPlugin Service.
+     * 
+     * 
+     * 
+     * @param binding
+     * @return Hashtable
+     * @throws NamingException
+     * 
+     */
+    private ConfigurationDictionary transform(Binding binding) throws NamingException
+    {
+        Attributes atts = (Attributes) binding.getObject();
+        ConfigurationDictionary transformedResults =contextMapping.transform( atts );
+        contextMapping.translateDirctoryKeysToOsgiKeys( transformedResults );
+        return transformedResults;
+
+
+    }
+
+    @Override
+    public String toString()
+    {
+        return name;
+    }
+
+    
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/KeyMapper.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/KeyMapper.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/KeyMapper.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/KeyMapper.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,108 @@
+package org.apache.configuration.dao.jndi.impl;
+
+import java.util.Dictionary;
+
+import org.apache.configuration.dao.jndi.ContextMapping;
+import org.apache.configuration.dao.jndi.KeyMapping;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.event.EventConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 
+ * KeyMapper maps implementation specific configuration 
+ * keys to OSGi generic dictionary keys.
+ *
+ * @author <a href="mailto:dev@directoryKey.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class KeyMapper implements KeyMapping{
+	private static final Logger log = LoggerFactory.getLogger(KeyMapper.class);
+    
+	
+    public static enum TranslationTable
+    {
+        EVENT_TOPIC   ("osgieventtopics",    EventConstants.EVENT_TOPIC ),
+        EVENT_FILTER  ("osgieventfilter",    EventConstants.EVENT_FILTER),
+        SERVICE_PID   (ContextMapping.APACHEDS_SERVICE_PID,   Constants.SERVICE_PID),
+        FACTORY_SERVICE_PID ("apacheservicefactorypid",ConfigurationAdmin.SERVICE_FACTORYPID );
+        
+        private final String directoryKey;   
+        private final String osgiKey; 
+        
+        
+        TranslationTable(String directory, String osgi) {
+        this.directoryKey = directory;
+        this.osgiKey = osgi;
+        }
+        
+        /**
+         * 
+         * Convert a directoryKey dictionary to one for Osgi.
+         *
+         * @param directoryDictionary
+         */
+        private void directoryKeyToOsgiKey(Dictionary<String,Object> directoryDictionary){
+            if(directoryDictionary.get(directoryKey) != null){
+                log.debug("Renaming configuration attribute identifier {} to {}.",directoryKey,osgiKey);
+                directoryDictionary.put(osgiKey, directoryDictionary.get(directoryKey));
+                directoryDictionary.remove(directoryKey);
+            }
+            
+        }
+        /**
+         * 
+         * Convert an osgiKey dictionary to one for an Apache Directory.
+         *
+         * @param osgiDictionary
+         */
+        private void osgiKeyToDirectoryKey(Dictionary<String,Object> osgiDictionary){
+            if(osgiDictionary.get(osgiKey) != null){
+                log.debug("Renaming configuration attribute identifier {} to {}.",osgiKey,directoryKey);
+                osgiDictionary.put(directoryKey, osgiDictionary.get(osgiKey));
+                osgiDictionary.remove(osgiKey);
+            }
+            
+        }
+    }
+    
+    /**
+     * 
+     * Creates a new instance of KeyNameMapper.
+     *
+     */
+	public KeyMapper() {
+		super();
+	}
+
+ 
+   /**
+    * 
+    *  ChangeType a dictionary from the directoryKey format to an OSGi configuration.
+    *  @param directoryDictionary
+    */
+	@SuppressWarnings("unchecked")
+    public void translateDirctoryKeysToOsgiKeys(Dictionary directoryDictionary) {
+		log.debug("Processing directoryKey configuration to OSGi configuration dictionary{}.",directoryDictionary);
+        for (TranslationTable m : TranslationTable.values())
+               m.directoryKeyToOsgiKey( directoryDictionary );
+		
+	}
+	/**
+     * 
+     * ChangeType a OSGi configuration to a dictionary suitable for the directoryKey.
+     *
+     * @param configurationDictionary
+	 */
+    @SuppressWarnings("unchecked")
+    public void translateOsgiKeysToDirectoryKeys(Dictionary configurationDictionary) {
+        log.debug("Processing OSGi configuration dictionary to a directoryKey configuration {}.",configurationDictionary);
+        for (TranslationTable m : TranslationTable.values())
+               m.osgiKeyToDirectoryKey( configurationDictionary );
+        
+    }
+
+
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/ListCommand.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/ListCommand.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/ListCommand.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/ListCommand.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,168 @@
+/*
+ *   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.dao.jndi.impl;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.naming.Name;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+
+import org.apache.configuration.dao.ConfigurationDaoException;
+import org.apache.configuration.dao.jndi.Command;
+import org.apache.configuration.dao.jndi.ContextMapping;
+import org.apache.configuration.dao.jndi.NameMapping;
+import org.apache.configuration.impl.ConfigurationDictionary;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * ListCommand.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ListCommand implements Command<List<ConfigurationDictionary>>
+{
+    private static final Logger log = LoggerFactory.getLogger( ListCommand.class );
+    private final String filter;
+    private final NameMapping nameMapping;
+    private final ContextMapping contextMapping;
+
+
+    /**
+     * 
+     * Creates a new instance of ListCommand.
+     *
+     * @param filter
+     * @param baseDn
+     * @param contextMapping
+     */
+    public ListCommand( String filter, NameMapping nameMapping, ContextMapping contextMapping )
+    {
+        this.filter = filter;
+        this.nameMapping = nameMapping;
+        this.contextMapping=contextMapping;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.configuration.dao.jndi.Command#execute(javax.naming.directory.DirContext)
+     */
+    public List<ConfigurationDictionary> execute( DirContext dirContext )
+    {
+
+        try
+        {
+            return search(dirContext);
+        }
+        catch ( NamingException e )
+        {
+            log.error( "Could not list ConfigurationDictionaries." ,e );
+            throw new ConfigurationDaoException("Could not list ConfigurationDictionaries.",e);
+        }
+        
+
+    }
+
+
+    private List<ConfigurationDictionary> search( DirContext dirContext ) throws NamingException
+    {
+        Name baseDn = nameMapping.getSearchBaseName();
+        List<ConfigurationDictionary> configurations = new ArrayList<ConfigurationDictionary>();
+        NamingEnumeration namingEnumeration = null;
+        SearchControls searchControls = new SearchControls();
+        searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+        log.debug( "Searching directory from searchBase: {}  using filter: {}", baseDn, filter );
+        NamingException exception = null;
+        try
+        {
+            namingEnumeration = dirContext.search( baseDn, filter, searchControls );
+            SearchResult searchResult = null;
+            ConfigurationDictionary configurationDictionary = null;
+            while ( namingEnumeration.hasMore() )
+            {
+                searchResult = ( SearchResult ) namingEnumeration.next();
+                configurationDictionary = createConfigurationDictionary(searchResult );
+                
+                configurations.add( configurationDictionary );
+            }
+
+            if ( configurations.isEmpty() )
+            {
+                log.debug( 
+                    "Found no entry while searching directory from searchBase: {} using filter: ",baseDn,filter );
+                return null;
+            }
+            else
+            {
+                log.debug( "Found {} entries while searching directory from searchBase: {}  using filter: {}", 
+                    new Object[] {configurations.size(), baseDn,  filter} );
+            }
+            configurationDictionary = createConfigurationDictionary( searchResult );
+
+        }
+        catch ( NamingException e )
+        {
+            log.error( "Search the dirContex for " + filter + " failed.", e );
+            exception = e;
+        }
+        finally
+        {
+            if ( namingEnumeration != null )
+            {
+                try
+                {
+                    namingEnumeration.close();
+                }
+                catch ( Exception e )
+                {
+                    log.error( "Could not close the namingEnumeration", e );
+                }
+            }
+        }
+        if ( exception != null )
+        {
+            throw exception;
+        }
+        return configurations.isEmpty() ? null : configurations;
+    }
+    
+    
+    private ConfigurationDictionary createConfigurationDictionary(SearchResult searchResult  ) throws NamingException
+    {
+        Attributes atts = searchResult.getAttributes();
+        String name = searchResult.getName();
+        ConfigurationDictionary configurationDictionary = contextMapping.transform( atts );
+        nameMapping.addAlternateName(configurationDictionary, name);
+        contextMapping.translateDirctoryKeysToOsgiKeys( configurationDictionary );
+        return configurationDictionary;
+    }
+    
+    
+
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/SimpleDirContextAdapter.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/SimpleDirContextAdapter.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/SimpleDirContextAdapter.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/SimpleDirContextAdapter.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,631 @@
+/*
+ *   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.dao.jndi.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Hashtable;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NameClassPair;
+import javax.naming.NameNotFoundException;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+
+/**
+ * SimpleDirContextAdapter is a simple DirContext used for saving objects in a
+ * directory DirContext.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class SimpleDirContextAdapter implements DirContext
+{
+
+    private static final String EMPTY = ""; //$NON-NLS-1$
+    private final Collection<Attribute> collectionOfAttributes = new ArrayList<Attribute>();
+    
+
+    
+    public void setAttribute(Attribute attribute){
+        collectionOfAttributes.add( attribute );
+    }
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#bind(javax.naming.Name, java.lang.Object, javax.naming.directory.Attributes)
+     */
+    public void bind( Name name, Object obj, Attributes attrs ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#bind(java.lang.String, java.lang.Object, javax.naming.directory.Attributes)
+     */
+    public void bind( String name, Object obj, Attributes attrs ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#createSubcontext(javax.naming.Name, javax.naming.directory.Attributes)
+     */
+    public DirContext createSubcontext( Name name, Attributes attrs ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#createSubcontext(java.lang.String, javax.naming.directory.Attributes)
+     */
+    public DirContext createSubcontext( String name, Attributes attrs ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#getAttributes(javax.naming.Name)
+     */
+    public Attributes getAttributes( Name name ) throws NamingException
+    {
+        if (! EMPTY.equals(name)) {
+            throw new NameNotFoundException();
+        }
+        
+        Attributes  myAttrs = new BasicAttributes(true);
+        for ( Attribute attr : collectionOfAttributes )
+        {
+            myAttrs.put( attr ) ;
+        }
+        return myAttrs;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#getAttributes(java.lang.String)
+     */
+    public Attributes getAttributes(String name) throws NamingException {
+        if (! EMPTY.equals(name)) {
+            throw new NameNotFoundException();
+        }
+        Attributes  myAttrs = new BasicAttributes(true);
+        for ( Attribute attr : collectionOfAttributes )
+        {
+            myAttrs.put( attr ) ;
+        }
+        return myAttrs;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#getAttributes(javax.naming.Name, java.lang.String[])
+     */
+    public Attributes getAttributes( Name name, String[] attrIds ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#getAttributes(java.lang.String, java.lang.String[])
+     */
+    public Attributes getAttributes( String name, String[] attrIds ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#getSchema(javax.naming.Name)
+     */
+    public DirContext getSchema( Name name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#getSchema(java.lang.String)
+     */
+    public DirContext getSchema( String name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#getSchemaClassDefinition(javax.naming.Name)
+     */
+    public DirContext getSchemaClassDefinition( Name name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#getSchemaClassDefinition(java.lang.String)
+     */
+    public DirContext getSchemaClassDefinition( String name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#modifyAttributes(javax.naming.Name, javax.naming.directory.ModificationItem[])
+     */
+    public void modifyAttributes( Name name, ModificationItem[] mods ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String, javax.naming.directory.ModificationItem[])
+     */
+    public void modifyAttributes( String name, ModificationItem[] mods ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#modifyAttributes(javax.naming.Name, int, javax.naming.directory.Attributes)
+     */
+    public void modifyAttributes( Name name, int mod_op, Attributes attrs ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String, int, javax.naming.directory.Attributes)
+     */
+    public void modifyAttributes( String name, int mod_op, Attributes attrs ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#rebind(javax.naming.Name, java.lang.Object, javax.naming.directory.Attributes)
+     */
+    public void rebind( Name name, Object obj, Attributes attrs ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#rebind(java.lang.String, java.lang.Object, javax.naming.directory.Attributes)
+     */
+    public void rebind( String name, Object obj, Attributes attrs ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#search(javax.naming.Name, javax.naming.directory.Attributes)
+     */
+    public NamingEnumeration<SearchResult> search( Name name, Attributes matchingAttributes ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#search(java.lang.String, javax.naming.directory.Attributes)
+     */
+    public NamingEnumeration<SearchResult> search( String name, Attributes matchingAttributes ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#search(javax.naming.Name, javax.naming.directory.Attributes, java.lang.String[])
+     */
+    public NamingEnumeration<SearchResult> search( Name name, Attributes matchingAttributes, String[] attributesToReturn )
+        throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#search(java.lang.String, javax.naming.directory.Attributes, java.lang.String[])
+     */
+    public NamingEnumeration<SearchResult> search( String name, Attributes matchingAttributes,
+        String[] attributesToReturn ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#search(javax.naming.Name, java.lang.String, javax.naming.directory.SearchControls)
+     */
+    public NamingEnumeration<SearchResult> search( Name name, String filter, SearchControls cons )
+        throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#search(java.lang.String, java.lang.String, javax.naming.directory.SearchControls)
+     */
+    public NamingEnumeration<SearchResult> search( String name, String filter, SearchControls cons )
+        throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#search(javax.naming.Name, java.lang.String, java.lang.Object[], javax.naming.directory.SearchControls)
+     */
+    public NamingEnumeration<SearchResult> search( Name name, String filterExpr, Object[] filterArgs,
+        SearchControls cons ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.directory.DirContext#search(java.lang.String, java.lang.String, java.lang.Object[], javax.naming.directory.SearchControls)
+     */
+    public NamingEnumeration<SearchResult> search( String name, String filterExpr, Object[] filterArgs,
+        SearchControls cons ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#addToEnvironment(java.lang.String, java.lang.Object)
+     */
+    public Object addToEnvironment( String propName, Object propVal ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#bind(javax.naming.Name, java.lang.Object)
+     */
+    public void bind( Name name, Object obj ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#bind(java.lang.String, java.lang.Object)
+     */
+    public void bind( String name, Object obj ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#close()
+     */
+    public void close() throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#composeName(javax.naming.Name, javax.naming.Name)
+     */
+    public Name composeName( Name name, Name prefix ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#composeName(java.lang.String, java.lang.String)
+     */
+    public String composeName( String name, String prefix ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#createSubcontext(javax.naming.Name)
+     */
+    public Context createSubcontext( Name name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#createSubcontext(java.lang.String)
+     */
+    public Context createSubcontext( String name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#destroySubcontext(javax.naming.Name)
+     */
+    public void destroySubcontext( Name name ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#destroySubcontext(java.lang.String)
+     */
+    public void destroySubcontext( String name ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#getEnvironment()
+     */
+    public Hashtable<?, ?> getEnvironment() throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#getNameInNamespace()
+     */
+    public String getNameInNamespace() throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#getNameParser(javax.naming.Name)
+     */
+    public NameParser getNameParser( Name name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#getNameParser(java.lang.String)
+     */
+    public NameParser getNameParser( String name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#list(javax.naming.Name)
+     */
+    public NamingEnumeration<NameClassPair> list( Name name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#list(java.lang.String)
+     */
+    public NamingEnumeration<NameClassPair> list( String name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#listBindings(javax.naming.Name)
+     */
+    public NamingEnumeration<Binding> listBindings( Name name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#listBindings(java.lang.String)
+     */
+    public NamingEnumeration<Binding> listBindings( String name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#lookup(javax.naming.Name)
+     */
+    public Object lookup( Name name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#lookup(java.lang.String)
+     */
+    public Object lookup( String name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#lookupLink(javax.naming.Name)
+     */
+    public Object lookupLink( Name name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#lookupLink(java.lang.String)
+     */
+    public Object lookupLink( String name ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#rebind(javax.naming.Name, java.lang.Object)
+     */
+    public void rebind( Name name, Object obj ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#rebind(java.lang.String, java.lang.Object)
+     */
+    public void rebind( String name, Object obj ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#removeFromEnvironment(java.lang.String)
+     */
+    public Object removeFromEnvironment( String propName ) throws NamingException
+    {
+        // ignored
+        return null;
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#rename(javax.naming.Name, javax.naming.Name)
+     */
+    public void rename( Name oldName, Name newName ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#rename(java.lang.String, java.lang.String)
+     */
+    public void rename( String oldName, String newName ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#unbind(javax.naming.Name)
+     */
+    public void unbind( Name name ) throws NamingException
+    {
+        // ignored
+
+    }
+
+
+    /* (non-Javadoc)
+     * @see javax.naming.Context#unbind(java.lang.String)
+     */
+    public void unbind( String name ) throws NamingException
+    {
+        // ignored
+
+    }
+
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/SimpleReadCommand.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/SimpleReadCommand.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/SimpleReadCommand.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/SimpleReadCommand.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,128 @@
+/*
+ *   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.dao.jndi.impl;
+
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.ldap.LdapName;
+
+import org.apache.configuration.dao.ConfigurationDaoException;
+import org.apache.configuration.dao.jndi.Command;
+import org.apache.configuration.dao.jndi.ContextMapping;
+import org.apache.configuration.dao.jndi.NameMapping;
+import org.apache.configuration.impl.ConfigurationDictionary;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * SimpleReadCommand reads a configurationDictionary from the directory.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ * @deprecated use DefaultReadCommand instead.
+ */
+public class SimpleReadCommand implements Command<ConfigurationDictionary>
+{
+
+    private static final Logger log = LoggerFactory.getLogger( SimpleReadCommand.class );
+    private final ContextMapping contextMapping;
+   
+    private final Name name;
+    /**
+     * Creates a new instance of SimpleReadCommand.
+     *
+     */
+    public SimpleReadCommand(ContextMapping contextMapping, Name name)
+    {
+      
+        this.name = name;
+        this.contextMapping=contextMapping;
+    }
+
+    /**
+     * 
+     * Creates a new instance of SimpleReadCommand.
+     *
+     * @param nameMapping
+     * @param contextMapping
+     * @param pid
+     * 
+     */
+    public SimpleReadCommand(NameMapping nameMapping, ContextMapping contextMapping, String pid)
+    {
+    
+        this.name = getDistinguishedName( nameMapping, pid );
+        this.contextMapping=contextMapping;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.configuration.dao.jndi.Command#execute(javax.naming.directory.DirContext)
+     *  an alternate would be to read an object by searching with a 
+     *  "(&(objectclass=apacheserviceconfiguration) (apacheservicefactorypid=" + factoryPid + "))";
+     */
+    public ConfigurationDictionary execute( DirContext dirContext )
+    {
+        ConfigurationDictionary configurationDictionary;
+        try
+        {
+            Attributes atts =dirContext.getAttributes( name );
+            configurationDictionary = createConfigurationDictionary( atts );
+        }
+        catch ( NamingException e )
+        {
+            log.error( name+" could not be read.",e );
+            throw new ConfigurationDaoException(name+" could not be read.",e);
+        }
+       
+       
+       return configurationDictionary;
+    }
+
+
+   
+    private ConfigurationDictionary createConfigurationDictionary( Attributes atts ) throws NamingException
+    {
+        ConfigurationDictionary configurationDictionary = contextMapping.transform( atts );
+        contextMapping.translateDirctoryKeysToOsgiKeys( configurationDictionary );
+        return configurationDictionary;
+    }
+    
+    private Name getDistinguishedName(NameMapping nameMapping, String pid ) 
+    {
+        
+        LdapName dn;
+        try
+        {
+            dn = nameMapping.getDefaultNamingBaseName();
+            dn.add(ContextMapping.APACHEDS_SERVICE_PID +'='+ pid);
+        }
+        catch ( InvalidNameException e )
+        {
+            throw new IllegalArgumentException("Invalid Name "+ pid+ ' '+e.toString());
+        }
+        
+        return dn;
+    }
+
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/UpdateCommand.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/UpdateCommand.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/UpdateCommand.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/UpdateCommand.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,310 @@
+/*
+ *   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.dao.jndi.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Vector;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.configuration.dao.ConfigurationDaoException;
+import org.apache.configuration.dao.jndi.Command;
+import org.apache.configuration.dao.jndi.ContextMapping;
+import org.apache.configuration.dao.jndi.NameMapping;
+import org.apache.configuration.impl.ConfigurationDictionary;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * UpdateCommand command object for updating a ConfigurationDictionary directory entry.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class UpdateCommand implements Command<Boolean>
+{
+    private static final Logger log = LoggerFactory.getLogger( UpdateCommand.class );
+    private final ContextMapping contextMapping;
+    private final NameMapping nameMapping;
+    private final ConfigurationDictionary updatedConfigurationDictionary;
+
+    /**
+     * Creates a new instance of CreateCommand.
+     *
+     */
+    public UpdateCommand(NameMapping nameMapping, ContextMapping contextMapping, ConfigurationDictionary updatedConfigurationDictionary)
+    {
+        this.contextMapping=contextMapping;
+        this.nameMapping=nameMapping;
+        ConfigurationDictionary copy = updatedConfigurationDictionary.createCopy();
+        contextMapping.translateOsgiKeysToDirectoryKeys( copy );
+        this.updatedConfigurationDictionary= copy;
+        log.debug( "Created command to update {}.",updatedConfigurationDictionary );
+    }
+
+
+    /* (non-Javadoc)
+     *
+     * @see org.apache.configuration.dao.jndi.Command#execute(javax.naming.directory.DirContext)
+     */
+    public Boolean execute( DirContext dirContext )
+    {
+       
+        String pid = nameMapping.getPid( updatedConfigurationDictionary );
+        Name name = nameMapping.getDistinguishedName( updatedConfigurationDictionary );
+        String filter = DefaultReadCommand.FILTER_PART_ONE + pid + "))";
+        Command<List<ConfigurationDictionary>> listCommand= new ListCommand(
+            filter,
+            nameMapping, 
+            contextMapping);
+        
+        List<ConfigurationDictionary> list = listCommand.execute( dirContext );
+        
+        if(list==null || list.isEmpty()){
+            return false;
+        }
+        
+        ConfigurationDictionary persistedConfigurationDictionary = list.get( 0 );
+        contextMapping.translateOsgiKeysToDirectoryKeys( persistedConfigurationDictionary );
+        log.debug( "Retrieved persistedConfigurationDictionary {}.",persistedConfigurationDictionary );
+        log.debug( "Changes in  updatedConfigurationDictionary {}.",updatedConfigurationDictionary );
+        ModificationItem[] mods = modifications( persistedConfigurationDictionary);
+        for ( ModificationItem item : mods )
+        {
+            log.debug( "Modifing {} with {}. ",name, item  );
+        }
+        try
+        {
+            dirContext.modifyAttributes( name, mods );
+        }
+        catch ( NamingException e )
+        {
+            log.error( "Could not modify "+name,e );
+            throw new ConfigurationDaoException("Could not modify "+name,e);
+        }
+        
+        log.debug( "Modified entry {} with DN [{}].",updatedConfigurationDictionary, name );
+        return true;
+    }
+
+
+    private ModificationItem[] modifications(ConfigurationDictionary persistedConfigurationDictionary)
+    {
+        Collection<ModificationItem> modificationItems = listRemovalModifications(persistedConfigurationDictionary);
+        modificationItems.addAll( listAdditionModifications(persistedConfigurationDictionary));
+        modificationItems.addAll( listReplacementModifications(persistedConfigurationDictionary));
+        ModificationItem[] mods = (ModificationItem[]) modificationItems.toArray(new ModificationItem[0]);
+        log.debug( "Created {} modificationItems .",mods.length );
+        return mods;
+        
+    }
+    
+    /**
+     * 
+     * @param persistedConfigurationDictionary
+     * @return collection of Replacement modificationItems
+     */
+    private Collection<ModificationItem> listReplacementModifications(ConfigurationDictionary persistedConfigurationDictionary){
+        Collection<ModificationItem> replacementMods = new ArrayList<ModificationItem>();
+        Collection<String> persistedKeys = getCollectionOfKeys( persistedConfigurationDictionary);
+        Collection<String> updatedKeys = getCollectionOfKeys( updatedConfigurationDictionary);
+        Collection<String> commonKeys = findKeysInCommon( persistedKeys,  updatedKeys);
+        Attribute attributeToReplace = null;
+        for ( String key : commonKeys)
+        {
+            if(compareObjectOrVector(persistedConfigurationDictionary.get( key ),updatedConfigurationDictionary.get( key ) )){
+                continue;
+            }
+            
+            log.debug( "Adding "+key+" updated value: {} to replace old value: {}.",updatedConfigurationDictionary.get( key ),persistedConfigurationDictionary.get( key ) );
+            attributeToReplace= new BasicAttribute(key);
+            Object value = updatedConfigurationDictionary.get( key );
+            contextMapping.addValueToAttribute( 
+                value, 
+                attributeToReplace );
+            replacementMods.add( 
+                new ModificationItem(
+                    DirContext.REPLACE_ATTRIBUTE,
+                    attributeToReplace)
+            );
+            
+        }
+        log.debug( "Created {} replaceModifications.",replacementMods.size() );
+        return replacementMods;
+    }
+    
+    /**
+     * 
+     * compare an object that may be a vector.
+     *
+     * @param updated
+     * @param persisted
+     * @return true if they are functionally the same.
+     */
+    private boolean compareObjectOrVector (Object updated, Object persisted){
+        if(updated instanceof Vector && persisted instanceof Vector) {
+            Vector u = (Vector)updated;
+            Vector p = (Vector)persisted;
+            if(u.size()!=p.size()){
+                return false;
+            }
+            if(CollectionUtils.subtract(  u, p).isEmpty()){
+                return true;
+            }
+            return false;
+        }
+        if(persisted.equals( updated)){
+            
+            return true;
+        }
+        log.debug( "updated value {} not the same as persisted value{}",updated,persisted );
+        return false;
+    }
+        
+    
+    /**
+     * 
+     * @param persistedConfigurationDictionary
+     * @return collection of Addition modificationItems
+     */
+    private Collection<ModificationItem> listAdditionModifications(ConfigurationDictionary persistedConfigurationDictionary){
+        Collection<ModificationItem> addMods = new ArrayList<ModificationItem>();
+        Collection<String> persistedKeys = getCollectionOfKeys( persistedConfigurationDictionary );
+        
+        Collection<String> updatedKeys = getCollectionOfKeys( updatedConfigurationDictionary);
+        
+        Collection<String> keysToAddToPersisted = findKeysToAdd(
+            persistedKeys, 
+            updatedKeys);
+        Attribute attributeToAdd = null;
+        for ( String key : keysToAddToPersisted )
+        {
+           attributeToAdd= new BasicAttribute(key);
+           Object value = updatedConfigurationDictionary.get( key );
+           contextMapping.addValueToAttribute( 
+               value, 
+               attributeToAdd );
+           addMods.add( 
+               new ModificationItem(
+                   DirContext.ADD_ATTRIBUTE,
+                   attributeToAdd)
+           );
+           log.debug( "Created addModification for {}.",key );
+        }
+        log.debug( "Created {} addMods.",addMods.size() );
+        return addMods;
+    }
+
+
+    
+    
+    /**
+     * 
+     * @param persistedConfigurationDictionary
+     * @return list of removal modificationItems
+     */
+    private Collection<ModificationItem> listRemovalModifications(ConfigurationDictionary persistedConfigurationDictionary){
+        Collection<ModificationItem> removeMods = new ArrayList<ModificationItem>();
+        Collection<String> persistedKeys = getCollectionOfKeys( persistedConfigurationDictionary);
+        Collection<String> updatedKeys = getCollectionOfKeys( updatedConfigurationDictionary);
+        
+        Collection<String> keysToRemoveFromPersisted = findKeysToRemove(
+            persistedKeys, 
+            updatedKeys);
+        Attribute att = null;
+//        ModificationItem item = null;
+        for ( String key : keysToRemoveFromPersisted )
+        {
+            att = new BasicAttribute(key, persistedConfigurationDictionary.get( key ));
+            
+            removeMods.add( 
+           new ModificationItem(
+               DirContext.REMOVE_ATTRIBUTE,
+               att)
+           );
+            log.debug( "Created removeModification for {}.",key );
+        }
+        log.debug( "Created {} removeMods.",removeMods.size() );
+        return removeMods;
+    }
+    
+    /**
+     * 
+     * Find removed keys
+     *
+     * @param persistedKeys
+     * @param updatedKeys
+     * @return keys in persistedKeys that are not in updatedKeys
+     */
+    @SuppressWarnings("unchecked")
+    private Collection<String> findKeysToRemove(Collection<String> persistedKeys, Collection<String> updatedKeys){
+        Collection<String> keysToRemove = CollectionUtils.subtract( persistedKeys, updatedKeys );
+        log.debug( keysToRemove+" keys in {} that are not in {}.",persistedKeys,updatedKeys );
+        return keysToRemove;
+    }
+    
+    /**
+     * 
+     * Find additional keys
+     *
+     * @param persistedKeys
+     * @param updatedKeys
+     * @return keys in updatedKeys that are not in persistedKeys
+     */
+    @SuppressWarnings("unchecked")
+    private Collection<String> findKeysToAdd(Collection persistedKeys, Collection updatedKeys){
+        Collection<String> keysToAdd = CollectionUtils.subtract(  updatedKeys, persistedKeys);
+        log.debug( keysToAdd+" keys in {} that are not in {}.",updatedKeys,persistedKeys );
+        return keysToAdd;
+    }
+    
+    
+    /**
+     * 
+     * Find common keys
+     *
+     * @param persistedKeys
+     * @param updatedKeys
+     * @return findKeysInCommon
+     */
+    @SuppressWarnings("unchecked")
+    private Collection<String> findKeysInCommon(Collection persistedKeys, Collection updatedKeys){
+        Collection<String> keysInCommon = CollectionUtils.intersection( persistedKeys, updatedKeys );
+        log.debug( keysInCommon+" keys in {} that are also in {}.",updatedKeys,persistedKeys );
+        return keysInCommon;
+    }
+    
+    private Collection<String> getCollectionOfKeys( ConfigurationDictionary persistedConfigurationDictionary )
+    {
+        Collection<String> persistedKeys = new ArrayList<String>();
+        CollectionUtils.addAll( persistedKeys, persistedConfigurationDictionary.keys());
+        return persistedKeys;
+    }
+   
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/package-info.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/package-info.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/package-info.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/impl/package-info.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,9 @@
+/**
+ * org.apache.configuration.dao.jndi.impl is the set of classes that implement the
+ * interfaces in org.apache.configuration.dao.jndi to create a JNDI based 
+ * <em>Data Access Object</em> for persisting Configuration dictionariers in a 
+ * JNDI backend store.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+package org.apache.configuration.dao.jndi.impl;
\ No newline at end of file

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/package-info.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/package-info.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/package-info.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/jndi/package-info.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,8 @@
+/**
+ * org.apache.configuration.dao.jndi is the set of interfaces and classes that specify a
+ * <em>Data Access Object</em> for persisting Configurations dictionaries in a 
+ * JNDI backend store that is found via an InitialContextFactory OSGi Service. 
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+package org.apache.configuration.dao.jndi;
\ No newline at end of file

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/package-info.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/package-info.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/package-info.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/dao/package-info.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,8 @@
+/**
+ * org.apache.configuration.dao is the set of interfaces and classes that specify a
+ * <em>Data Access Object</em> for persisting Configurations dictionaries in a 
+ * backend store.  
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+package org.apache.configuration.dao;
\ No newline at end of file

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/AsyncExecutorService.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/AsyncExecutorService.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/AsyncExecutorService.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/AsyncExecutorService.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,51 @@
+/*
+ *   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 java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+
+/**
+ * <p>A <tt>AsyncExecutorService</tt>  encapsulates an {@link ExecutorService} to present
+ * a instanceFactory method for other <em>Spring</em> wired beans to obtain a {@link Executor} and
+ * to offer a <em>Spring bean destroy-method</em> for shuting down the execution of commands.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class AsyncExecutorService
+{
+
+    private ExecutorService executorService = Executors.newSingleThreadExecutor();
+
+
+    public void destroy()
+    {
+       executorService.shutdown();
+    }
+    
+    public Executor getExecutor(){
+        return executorService;
+    }
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ConfigurationChangeManager.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ConfigurationChangeManager.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ConfigurationChangeManager.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ConfigurationChangeManager.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,378 @@
+/*
+ *   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.dao.ConfigurationDaoListener;
+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.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationEvent;
+import org.osgi.service.cm.ConfigurationListener;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.cm.ManagedServiceFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * ConfigurationChangeManager will asynchronously update ManageService and ManagedServiceFactory registered
+ * serviceReferences and ConfigurationListeners when changes occur on the backend ConfigurationStore.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ * 
+ */
+public class ConfigurationChangeManager implements ConfigurationDaoListener
+{
+
+    /** the log for this class */
+    private static final Logger log = LoggerFactory.getLogger( ConfigurationChangeManager.class );
+
+    private Executor executor;
+
+    private ManagedServiceFactoryTrackingAdapter managedServiceFactoryTrackingAdapter;
+
+    private ManagedServiceTrackingAdapter managedServiceTrackingAdapter;
+
+    private ConfigurationStore configurationStore;
+
+    private ConfigurationTransformer configurationTransformer;
+
+    private ConfigurationListener configurationListener;
+
+
+    /**
+     * ChangeListner implementation that listens to Configuration change events coming 
+     * from the ConfigurationStore and converts them into tasks that are sent 
+     * to the executor queue. 
+     * 
+     * SERVICE_STORE_UPDATING and FACTORY_STORE_UPDATING are the two update types sent.
+     * 
+     * 
+     */
+    public void configurationChanged( ChangeType changeType, ConfigurationDictionary configurationIn )
+    {
+        ConfigurationDictionary configurationDictionary = new ConfigurationDictionary( configurationIn );
+
+        String servicePid = ( String ) configurationDictionary.get( Constants.SERVICE_PID );
+
+        if ( servicePid == null )
+        {
+            log.error( "A configuration change was detected but the servicePid could not be found in dictionary {}.",
+                configurationDictionary );
+            return;
+        }
+
+        Object factoryPidObject = configurationDictionary.get( ConfigurationAdmin.SERVICE_FACTORYPID );
+
+        ServiceReference serviceReference = null;
+        if ( factoryPidObject == null )
+        {
+            serviceReference = updateManagedService( servicePid, configurationDictionary, changeType );
+        }
+        else
+        {
+            String factoryPid = ( String ) factoryPidObject;
+            serviceReference = updateManagedServiceFactory( servicePid, factoryPid, configurationDictionary, changeType );
+        }
+        if ( serviceReference == null )
+        {
+            log.error( "Failed to find a serviceReference for updated configuration =" + configurationDictionary );
+            return;
+        }
+        sendEventToListener( changeType, configurationDictionary, serviceReference );
+
+    }
+
+
+    void sendEventToListener( ChangeType changeType, ConfigurationDictionary configurationDictionary,
+        ServiceReference serviceReference )
+    {
+        int type;
+        if ( ChangeType.DELETED.equals( changeType ) )
+        {
+            type = ConfigurationEvent.CM_DELETED;
+        }
+        else
+        {
+            type = ConfigurationEvent.CM_UPDATED;
+        }
+
+        final ConfigurationEvent event = new ConfigurationEvent( serviceReference, type, configurationDictionary
+            .getFactoryPid(), configurationDictionary.getServicePid() );
+
+        Runnable task = new Runnable()
+        {
+
+            public void run()
+            {
+                configurationListener.configurationEvent( event );
+
+            }
+
+        };
+
+        executor.execute( task );
+    }
+
+
+    /**
+     * @param servicePid
+     */
+    ServiceReference updateManagedService( final String servicePid,
+        final ConfigurationDictionary configurationDictionary, final ChangeType changeType )
+    {
+        final ServiceReference serviceReference = findManagedServiceReference( servicePid );
+        if ( serviceReference == null )
+        {
+            log.error( "Could not find a serviceReference for servicePid=" + servicePid );
+            return serviceReference;
+        }
+        Runnable command = new Runnable()
+        {
+
+            public void run()
+            {
+
+                try
+                {
+                    String location = serviceReference.getBundle().getLocation();
+                    if ( location == null )
+                    {
+                        log.error( "Could not get location from the serviceReferrence." );
+                        return;
+                    }
+                    //Send Bind request to the configurationStore
+                    if ( configurationStore != null )
+                    {
+                        configurationStore.retrieveAndBind( servicePid, location );
+                    }
+                    else
+                    {
+                        log.warn( "Did not bind pid {} and location {} to the persisted store.", servicePid, location );
+                    }
+
+                    ManagedService managedService = ( ManagedService ) managedServiceTrackingAdapter
+                        .getService( serviceReference );
+                    if ( managedService == null )
+                    {
+                        log.error( "Could not find a ManagedService from the associated with ServiceReference="
+                            + serviceReference );
+                        return;
+                    }
+                    if ( ChangeType.DELETED.equals( changeType ) )
+                    {
+                        managedService.updated( null );
+                    }
+                    else
+                    {
+                        managedService.updated( configurationTransformer.transform( serviceReference,
+                            configurationDictionary ) );
+                    }
+
+                }
+                catch ( Exception e )
+                {
+                    log.error( "Failed to process store change for servicePid=" + servicePid, e );
+                }
+
+            }
+
+        };
+
+        executor.execute( command );
+        return serviceReference;
+    }
+
+
+    ServiceReference updateManagedServiceFactory( final String servicePid, final String factoryPid,
+        final ConfigurationDictionary configurationDictionary, final ChangeType changeType )
+    {
+        final ServiceReference serviceReference = findManagedServiceFactoryReference( factoryPid );
+        if ( serviceReference == null )
+        {
+            log.error( "Could not find a serviceReference for factoryPid=" + factoryPid );
+            return serviceReference;
+        }
+
+        Runnable command = new Runnable()
+        {
+
+            public void run()
+            {
+
+                try
+                {
+                    String location = serviceReference.getBundle().getLocation();
+
+                    if ( location == null )
+                    {
+                        log.error( "Could not get location from the serviceReferrence." );
+                        return;
+                    }
+
+                    //Send Bind request to the configurationStore
+                    if ( configurationStore != null )
+                    {
+                        configurationStore.retrieveAndBind( servicePid, location );
+                    }
+                    else
+                    {
+                        log.warn( "Did not bind pid {} and location {} to the persisted store.", servicePid, location );
+                    }
+
+                    ManagedServiceFactory managedServiceFactory = ( ManagedServiceFactory ) managedServiceFactoryTrackingAdapter
+                        .getService( serviceReference );
+
+                    if ( managedServiceFactory == null )
+                    {
+                        log.error( "Could not find a ManagedServiceFactory from the associated with ServiceReference="
+                            + serviceReference );
+                        return;
+                    }
+                    if ( ChangeType.DELETED.equals( changeType ) )
+                    {
+                        managedServiceFactory.deleted( servicePid );
+                    }
+                    else
+                    {
+                        managedServiceFactory.updated( servicePid, configurationTransformer.transform(
+                            serviceReference, configurationDictionary ) );
+                    }
+                }
+                catch ( Exception e )
+                {
+                    log.error( "Failed to process store change for servicePid=" + servicePid + " factoryPid="
+                        + servicePid + "", e );
+                }
+
+            }
+
+        };
+
+        executor.execute( command );
+        return serviceReference;
+    }
+
+
+    /**
+     * 
+     * findManagedServiceFactory for a given factoryPid.
+     *
+     * @param factoryPid
+     * @return
+     */
+    private ServiceReference findManagedServiceFactoryReference( String factoryPid )
+    {
+
+        for ( ServiceReference serviceReference : managedServiceFactoryTrackingAdapter.getServiceReferences() )
+        {
+            if ( factoryPid.equals( serviceReference.getProperty( ConfigurationAdmin.SERVICE_FACTORYPID ) ) )
+            {
+                return serviceReference;
+            }
+        }
+        return null;
+    }
+
+
+    /**
+     * 
+     * findManagedService for a given servicePid.
+     *
+     * @param servicePid
+     * @return
+     */
+    private ServiceReference findManagedServiceReference( String servicePid )
+    {
+
+        for ( ServiceReference serviceReference : managedServiceTrackingAdapter.getServiceReferences() )
+        {
+            if ( servicePid.equals( serviceReference.getProperty( Constants.SERVICE_PID ) ) )
+            {
+                return serviceReference;
+            }
+        }
+        return null;
+    }
+
+
+    /**
+     * @param executor the executor to set
+     */
+    public void setExecutor( Executor executor )
+    {
+        this.executor = executor;
+    }
+
+
+    /**
+     * @param configurationStore the configurationStore to set
+     */
+    public void setConfigurationStore( ConfigurationStore configurationStore )
+    {
+        this.configurationStore = configurationStore;
+    }
+
+
+    /**
+     * @param configurationTransformer 
+     */
+    public void setConfigurationTransformer( ConfigurationTransformer configurationTransformer )
+    {
+        this.configurationTransformer = configurationTransformer;
+    }
+
+
+    /**
+     * @param configurationListener the configurationListener to set
+     */
+    public void setConfigurationListener( ConfigurationListener configurationListener )
+    {
+        this.configurationListener = configurationListener;
+    }
+
+
+    /**
+     * @param managedServiceFactoryTrackingAdapter the managedServiceFactoryTrackingAdapter to set
+     */
+    public void setManagedServiceFactoryTrackingAdapter(
+        ManagedServiceFactoryTrackingAdapter managedServiceFactoryTrackingAdapter )
+    {
+        this.managedServiceFactoryTrackingAdapter = managedServiceFactoryTrackingAdapter;
+    }
+
+
+    /**
+     * @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/ConfigurationEventBroadcaster.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ConfigurationEventBroadcaster.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ConfigurationEventBroadcaster.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ConfigurationEventBroadcaster.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,59 @@
+/*
+ *   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.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.osgi.service.cm.ConfigurationEvent;
+import org.osgi.service.cm.ConfigurationListener;
+
+/**
+ * ConfigurationEventBroadcaster.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ConfigurationEventBroadcaster implements ConfigurationListener
+{
+    List<ConfigurationListener> listeners = new CopyOnWriteArrayList<ConfigurationListener>();
+
+    /* (non-Javadoc)
+     * @see org.osgi.service.cm.ConfigurationListener#configurationEvent(org.osgi.service.cm.ConfigurationEvent)
+     */
+    public void configurationEvent( ConfigurationEvent event )
+    {
+        for ( ConfigurationListener configurationListener : listeners )
+        {
+            configurationListener.configurationEvent( event );
+        }
+
+    }
+
+    /**
+     * @param listeners the listeners to set
+     */
+    public void setListeners( List<ConfigurationListener> listeners )
+    {
+        this.listeners = listeners;
+    }
+
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceFactoryTrackerCustomizer.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceFactoryTrackerCustomizer.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceFactoryTrackerCustomizer.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceFactoryTrackerCustomizer.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,190 @@
+/*
+ *   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.Set;
+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.ServiceReference;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedServiceFactory;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ManagedServiceTracker extends ServiceTracker to handle active ManagedServiceFactory Services.
+ * 
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ * 
+ */
+ 
+public class ManagedServiceFactoryTrackerCustomizer implements ServiceTrackerCustomizer
+{
+
+    /** the log for this class */
+    private final Logger log = LoggerFactory.getLogger( ManagedServiceFactoryTrackerCustomizer.class );
+    private ConfigurationStore configurationStore;
+//    private BundleContext bundleContext;
+    private ConfigurationTransformer configurationTransformer;
+    private ManagedServiceFactoryTrackingAdapter managedServiceFactoryTrackingAdapter;
+    private Executor executor;
+
+
+    
+    /* (non-Javadoc)
+     * @see org.osgi.util.tracker.ServiceTracker#addingService(org.osgi.framework.ServiceReference)
+     */
+    
+    public Object addingService( final ServiceReference serviceReference )
+    {
+        Runnable command = 
+            new Runnable() {
+
+                public void run() 
+                {
+                    String factoryPid = (String) serviceReference.getProperty(ConfigurationAdmin.SERVICE_FACTORYPID);
+                    String location = serviceReference.getBundle().getLocation();
+                    Set<String> pidsForFactory = configurationStore.listPids( factoryPid);
+                    for ( String servicePid : pidsForFactory )
+                    {
+                        try
+                        {
+                            ConfigurationDictionary configurationDictionary;
+                            try
+                            {
+                                configurationDictionary = configurationStore.retrieveAndBind( servicePid, location );
+                            }
+                            catch ( ConfigurationException e )
+                            {
+                                configurationDictionary=null;
+                                log.error( "Failed to retrieve configuration from the backend.",e );
+                            }
+//                          ManagedServiceFactory managedServiceFactory = (ManagedServiceFactory)bundleContext.getService( serviceReference );
+                            ManagedServiceFactory managedServiceFactory = managedServiceFactoryTrackingAdapter.getService(serviceReference);
+                            managedServiceFactory.updated( servicePid,configurationTransformer.transform( serviceReference, configurationDictionary) );
+                        }
+                        catch ( Exception e )
+                        {
+                            log.error( "Failed to update ManagedServiceFactory for factoryPid="+factoryPid,e );
+                        }
+                    }
+
+                }
+               
+        };
+        
+        executor.execute( command );
+        return serviceReference ;
+    }
+
+
+
+    /* (non-Javadoc)
+     * @see org.osgi.util.tracker.ServiceTracker#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
+     */
+
+    public void removedService( final ServiceReference serviceReference, Object service )
+    {
+        Runnable command = 
+            new Runnable() {
+
+                public void run() 
+                {
+                    String factoryPid = (String) serviceReference.getProperty(ConfigurationAdmin.SERVICE_FACTORYPID);
+                    Set<String> pidsForFactory = configurationStore.listPids( factoryPid);
+                    for ( String servicePid : pidsForFactory )
+                    {
+                        configurationStore.unbind(servicePid);
+                    }
+                    
+                }
+               
+        };
+        
+        executor.execute( command );
+        
+    }
+
+    public void modifiedService( ServiceReference arg0, Object arg1 )
+    {
+//      ignore
+        
+    }
+
+
+
+//    /**
+//     * @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 managedServiceFactoryTrackingAdapter the managedServiceFactoryTrackingAdapter to set
+     */
+    public void setManagedServiceFactoryTrackingAdapter(
+        ManagedServiceFactoryTrackingAdapter managedServiceFactoryTrackingAdapter )
+    {
+        this.managedServiceFactoryTrackingAdapter = managedServiceFactoryTrackingAdapter;
+    }
+
+}

Added: directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceFactoryTrackingAdapter.java
URL: http://svn.apache.org/viewvc/directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceFactoryTrackingAdapter.java?view=auto&rev=501176
==============================================================================
--- directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceFactoryTrackingAdapter.java (added)
+++ directory/sandbox/jconlon/osgi-services/configuration-service/src/main/java/org/apache/configuration/event/ManagedServiceFactoryTrackingAdapter.java Mon Jan 29 12:38:25 2007
@@ -0,0 +1,44 @@
+/*
+ *   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;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+/**
+ * A <tt>ManagedServiceFactoryTrackingAdapter</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 ManagedServiceFactoryTrackingAdapter extends ServiceTrackingAdapter<ManagedServiceFactory>
+{
+    
+    public ManagedServiceFactoryTrackingAdapter()
+    {
+       super(ManagedServiceFactory.class);
+    }
+
+
+}