felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r1750478 - in /felix/sandbox/cziegeler/configadmin-r7: ./ src/main/java/org/apache/felix/cm/impl/ src/main/java/org/osgi/service/cm/ src/test/java/org/apache/felix/cm/impl/
Date Tue, 28 Jun 2016 11:34:40 GMT
Author: cziegeler
Date: Tue Jun 28 11:34:40 2016
New Revision: 1750478

URL: http://svn.apache.org/viewvc?rev=1750478&view=rev
Log:
Update implementation to latest RFC 227

Modified:
    felix/sandbox/cziegeler/configadmin-r7/pom.xml
    felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationAdapter.java
    felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationAdminImpl.java
    felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java
    felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/Configuration.java
    felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/ConfigurationPermission.java
    felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/LockedConfigurationException.java
    felix/sandbox/cziegeler/configadmin-r7/src/test/java/org/apache/felix/cm/impl/ConfigurationManagerTest.java

Modified: felix/sandbox/cziegeler/configadmin-r7/pom.xml
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configadmin-r7/pom.xml?rev=1750478&r1=1750477&r2=1750478&view=diff
==============================================================================
--- felix/sandbox/cziegeler/configadmin-r7/pom.xml (original)
+++ felix/sandbox/cziegeler/configadmin-r7/pom.xml Tue Jun 28 11:34:40 2016
@@ -68,6 +68,7 @@
         in the IDE launcher. 
     -->
     <properties>
+        <felix.java.version>6</felix.java.version>
         <bundle.build.name>
             ${basedir}/target
         </bundle.build.name>
@@ -108,7 +109,6 @@
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
-            <version>4.6</version>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -197,9 +197,14 @@
                             <!-- overwrite version from compendium bundle -->
                             org.osgi.service.log;version="1.3"
                         </DynamicImport-Package>
-                        <Provide-Capability>osgi.service;objectClass:List&lt;String>="org.osgi.service.cm.ConfigurationAdmin",
-                        osgi.service;objectClass:List&lt;String>="org.apache.felix.cm.PersistenceManager"</Provide-Capability>
-                        <Require-Capability>osgi.service;filter:="(objectClass=org.osgi.service.log.LogService)";effective:=active;resolution:=optional</Require-Capability>
+                        <Provide-Capability><![CDATA[
+                            osgi.service;objectClass:List<String>="org.osgi.service.cm.ConfigurationAdmin";uses:="org.osgi.service.cm,org.apache.felix.cm",
+                            osgi.service;objectClass:List<String>="org.apache.felix.cm.PersistenceManager";uses:="org.osgi.service.cm,org.apache.felix.cm",
+                            osgi.implementation;osgi.implementation="osgi.cm";uses:="org.osgi.service.cm,org.apache.felix.cm";version:Version="1.6"
+                        ]]></Provide-Capability>
+                        <Require-Capability><![CDATA[
+                            osgi.service;filter:="(objectClass=org.osgi.service.log.LogService)";effective:=active;resolution:=optional
+                        ]]></Require-Capability>
                         <Embed-Dependency>
                             org.osgi.core;inline=org/osgi/util/tracker/ServiceTracker*|org/osgi/util/tracker/AbstractTracked.class
                         </Embed-Dependency>

Modified: felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationAdapter.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationAdapter.java?rev=1750478&r1=1750477&r2=1750478&view=diff
==============================================================================
--- felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationAdapter.java
(original)
+++ felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationAdapter.java
Tue Jun 28 11:34:40 2016
@@ -22,7 +22,13 @@ package org.apache.felix.cm.impl;
 import java.io.IOException;
 import java.util.Dictionary;
 
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
 import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationPermission;
+import org.osgi.service.cm.LockedConfigurationException;
+import org.osgi.service.cm.ManagedService;
 import org.osgi.service.log.LogService;
 
 
@@ -49,6 +55,7 @@ public class ConfigurationAdapter implem
     /**
      * @see org.apache.felix.cm.impl.ConfigurationImpl#getPid()
      */
+    @Override
     public String getPid()
     {
         checkDeleted();
@@ -59,6 +66,7 @@ public class ConfigurationAdapter implem
     /**
      * @see org.apache.felix.cm.impl.ConfigurationImpl#getFactoryPid()
      */
+    @Override
     public String getFactoryPid()
     {
         checkDeleted();
@@ -69,6 +77,7 @@ public class ConfigurationAdapter implem
     /**
      * @see org.apache.felix.cm.impl.ConfigurationImpl#getBundleLocation()
      */
+    @Override
     public String getBundleLocation()
     {
         // CM 1.4 / 104.13.2.4
@@ -86,6 +95,7 @@ public class ConfigurationAdapter implem
      * @param bundleLocation
      * @see org.apache.felix.cm.impl.ConfigurationImpl#setStaticBundleLocation(String)
      */
+    @Override
     public void setBundleLocation( String bundleLocation )
     {
         delegatee.getConfigurationManager().log( LogService.LOG_DEBUG, "setBundleLocation(bundleLocation={0})",
@@ -106,6 +116,7 @@ public class ConfigurationAdapter implem
      * @throws IOException
      * @see org.apache.felix.cm.impl.ConfigurationImpl#update()
      */
+    @Override
     public void update() throws IOException
     {
         delegatee.getConfigurationManager().log( LogService.LOG_DEBUG, "update()", ( Throwable
) null );
@@ -121,18 +132,21 @@ public class ConfigurationAdapter implem
      * @throws IOException
      * @see org.apache.felix.cm.impl.ConfigurationImpl#update(java.util.Dictionary)
      */
-    public void update( Dictionary properties ) throws IOException
+    @Override
+    public void update( Dictionary<String, ?> properties ) throws IOException
     {
         delegatee.getConfigurationManager().log( LogService.LOG_DEBUG, "update(properties={0})",
new Object[]
             { properties } );
 
         checkActive();
         checkDeleted();
+        checkLocked();
         delegatee.update( properties );
     }
 
 
-    public Dictionary getProperties()
+    @Override
+    public Dictionary<String, Object> getProperties()
     {
         delegatee.getConfigurationManager().log( LogService.LOG_DEBUG, "getProperties()",
( Throwable ) null );
 
@@ -144,6 +158,7 @@ public class ConfigurationAdapter implem
     }
 
 
+    @Override
     public long getChangeCount()
     {
         delegatee.getConfigurationManager().log( LogService.LOG_DEBUG, "getChangeCount()",
( Throwable ) null );
@@ -158,6 +173,7 @@ public class ConfigurationAdapter implem
      * @throws IOException
      * @see org.apache.felix.cm.impl.ConfigurationImpl#delete()
      */
+    @Override
     public void delete() throws IOException
     {
         delegatee.getConfigurationManager().log( LogService.LOG_DEBUG, "delete()", ( Throwable
) null );
@@ -168,21 +184,72 @@ public class ConfigurationAdapter implem
     }
 
 
-    public void setProperties(final Dictionary<String, ?> properties) throws IOException
{
-        // TODO
-        update(properties);
+    /**
+     * @see org.osgi.service.cm.Configuration#setProperties(java.util.Dictionary)
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public boolean setProperties(final Dictionary<String, ?> properties) throws IOException
+    {
+        delegatee.getConfigurationManager().log( LogService.LOG_DEBUG, "setProperties(properties={0})",
new Object[]
+                { properties } );
+
+        checkActive();
+        checkDeleted();
+        checkLocked();
+
+        if ( ConfigurationImpl.equals((Dictionary<String, Object>)properties, delegatee.getProperties(false))
)
+        {
+            // nothing to do
+            return false;
+        }
+        delegatee.update( properties );
+        return true;
     }
 
 
-    public void setLocked(boolean flag) throws IOException {
-        // TODO Auto-generated method stub
+    /**
+     * @see org.osgi.service.cm.Configuration#setLocked(boolean)
+     */
+    @Override
+    public void setLocked(boolean flag) throws IOException
+    {
+        delegatee.getConfigurationManager().log( LogService.LOG_DEBUG, "setLocked({0})",
+                new Object[] { flag } );
 
+        checkDeleted();
+        final String bundleLocation = delegatee.getBundleLocation();
+        this.configurationAdmin.checkPermission(this.delegatee.getConfigurationManager(),
+                ( bundleLocation == null ) ? "*" : bundleLocation,
+                        ConfigurationPermission.LOCK,
+                        true);
+        delegatee.setLocked( flag );
     }
 
 
-    public boolean isLocked() {
-        // TODO Auto-generated method stub
-        return false;
+    /**
+     * @see org.osgi.service.cm.Configuration#getModifiedProperties(org.osgi.framework.ServiceReference)
+     */
+    @Override
+    public Dictionary<String, Object> getModifiedProperties(ServiceReference<ManagedService>
sr) {
+        final Dictionary<String, Object> props = this.getProperties();
+
+        this.delegatee.getConfigurationManager().callPlugins(props, sr,
+                (String)props.get(Constants.SERVICE_PID),
+                (String)props.get(ConfigurationAdmin.SERVICE_FACTORYPID));
+
+        return props;
+    }
+
+
+    /**
+     * @see org.osgi.service.cm.Configuration#isLocked()
+     */
+    @Override
+    public boolean isLocked()
+    {
+        checkDeleted();
+        return delegatee.isLocked();
     }
 
 
@@ -246,4 +313,17 @@ public class ConfigurationAdapter implem
             throw new IllegalStateException( "Configuration " + delegatee.getPid() + " deleted"
);
         }
     }
+
+    /**
+     * Checks whether this configuration object is locked.
+     *
+     * @throws LockedConfigurationException If this configuration object is locked.
+     */
+    private void checkLocked() throws IOException
+    {
+        if ( delegatee.isLocked() )
+        {
+            throw new LockedConfigurationException( "Configuration " + delegatee.getPid()
+ " is locked" );
+        }
+    }
 }

Modified: felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationAdminImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationAdminImpl.java?rev=1750478&r1=1750477&r2=1750478&view=diff
==============================================================================
--- felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationAdminImpl.java
(original)
+++ felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationAdminImpl.java
Tue Jun 28 11:34:40 2016
@@ -70,6 +70,7 @@ public class ConfigurationAdminImpl impl
     /* (non-Javadoc)
      * @see org.osgi.service.cm.ConfigurationAdmin#createFactoryConfiguration(java.lang.String)
      */
+    @Override
     public Configuration createFactoryConfiguration( String factoryPid ) throws IOException
     {
         final ConfigurationManager configurationManager = getConfigurationManager();
@@ -87,6 +88,7 @@ public class ConfigurationAdminImpl impl
     /* (non-Javadoc)
      * @see org.osgi.service.cm.ConfigurationAdmin#createFactoryConfiguration(java.lang.String,
java.lang.String)
      */
+    @Override
     public Configuration createFactoryConfiguration( String factoryPid, String location )
throws IOException
     {
         final ConfigurationManager configurationManager = getConfigurationManager();
@@ -106,6 +108,7 @@ public class ConfigurationAdminImpl impl
     /* (non-Javadoc)
      * @see org.osgi.service.cm.ConfigurationAdmin#getConfiguration(java.lang.String)
      */
+    @Override
     public Configuration getConfiguration( String pid ) throws IOException
     {
         final ConfigurationManager configurationManager = getConfigurationManager();
@@ -147,6 +150,7 @@ public class ConfigurationAdminImpl impl
     /* (non-Javadoc)
      * @see org.osgi.service.cm.ConfigurationAdmin#getConfiguration(java.lang.String, java.lang.String)
      */
+    @Override
     public Configuration getConfiguration( String pid, String location ) throws IOException
     {
         final ConfigurationManager configurationManager = getConfigurationManager();
@@ -175,6 +179,7 @@ public class ConfigurationAdminImpl impl
     /* (non-Javadoc)
      * @see org.osgi.service.cm.ConfigurationAdmin#listConfigurations(java.lang.String)
      */
+    @Override
     public Configuration[] listConfigurations( String filter ) throws IOException, InvalidSyntaxException
     {
         final ConfigurationManager configurationManager = getConfigurationManager();
@@ -239,6 +244,25 @@ public class ConfigurationAdminImpl impl
      */
     void checkPermission( final ConfigurationManager configurationManager, String name, boolean
checkOwn )
     {
+        checkPermission(configurationManager, name, ConfigurationPermission.CONFIGURE, checkOwn);
+    }
+
+    /**
+     * Checks whether the current access control context (call stack) has
+     * the given permission for the given bundle location and throws a
+     * <code>SecurityException</code> if this is not the case.
+     *
+     * @param name The bundle location to check for permission. If this
+     *      is <code>null</code> permission is always granted.
+     * @param action The action to check.
+     * @param checkOwn If {@code false} permission is alwas granted if
+     *      {@code name} is the same the using bundle's location.
+     *
+     * @throws SecurityException if the access control context does not
+     *      have the appropriate permission
+     */
+    void checkPermission( final ConfigurationManager configurationManager, String name, String
action, boolean checkOwn )
+    {
         // the caller's permission must be checked
         final SecurityManager sm = System.getSecurityManager();
         if ( sm != null )
@@ -248,45 +272,45 @@ public class ConfigurationAdminImpl impl
             {
                 try
                 {
-                    sm.checkPermission( new ConfigurationPermission( name, ConfigurationPermission.CONFIGURE
) );
+                    sm.checkPermission( new ConfigurationPermission( name, action ) );
 
                     configurationManager.log( LogService.LOG_DEBUG,
-                        "Explicit Permission; grant CONFIGURE permission on configuration
bound to {0} to bundle {1}",
+                        "Explicit Permission; grant {0} permission on configuration bound
to {1} to bundle {2}",
                         new Object[]
-                            { name, getBundle().getLocation() } );
+                            { action, name, getBundle().getLocation() } );
                 }
                 catch ( SecurityException se )
                 {
                     configurationManager
                         .log(
                             LogService.LOG_DEBUG,
-                            "No Permission; denied CONFIGURE permission on configuration
bound to {0} to bundle {1}; reason: {2}",
+                            "No Permission; denied {0} permission on configuration bound
to {1} to bundle {2}; reason: {3}",
                             new Object[]
-                                { name, getBundle().getLocation(), se.getMessage() } );
+                                { action, name, getBundle().getLocation(), se.getMessage()
} );
                     throw se;
                 }
             }
             else if ( configurationManager.isLogEnabled( LogService.LOG_DEBUG ) )
             {
                 configurationManager.log( LogService.LOG_DEBUG,
-                    "Implicit Permission; grant CONFIGURE permission on configuration bound
to {0} to bundle {1}",
+                    "Implicit Permission; grant {0} permission on configuration bound to
{1} to bundle {2}",
                     new Object[]
-                        { name, getBundle().getLocation() } );
+                        { action, name, getBundle().getLocation() } );
 
             }
         }
         else if ( configurationManager.isLogEnabled( LogService.LOG_DEBUG ) )
         {
             configurationManager.log( LogService.LOG_DEBUG,
-                "No SecurityManager installed; grant CONFIGURE permission on configuration
bound to {0} to bundle {1}",
+                "No SecurityManager installed; grant {0} permission on configuration bound
to {1} to bundle {2}",
                 new Object[]
-                    { name, getBundle().getLocation() } );
+                    { action, name, getBundle().getLocation() } );
         }
     }
 
 
     /**
-     * Returns the {@link ConfigurationManager} backing this configuraiton
+     * Returns the {@link ConfigurationManager} backing this configuration
      * admin instance or throws {@code IllegalStateException} if already
      * disposed off.
      *
@@ -305,15 +329,77 @@ public class ConfigurationAdminImpl impl
     }
 
 
-    public Configuration getFactoryConfiguration(String factoryPid, String alias, String
location) throws IOException {
-        // TODO Auto-generated method stub
-        return null;
-    }
+    /**
+     * @see org.osgi.service.cm.ConfigurationAdmin#getFactoryConfiguration(java.lang.String,
java.lang.String, java.lang.String)
+     */
+    @Override
+    public Configuration getFactoryConfiguration(String factoryPid, String alias, String
location) throws IOException
+    {
+        final ConfigurationManager configurationManager = getConfigurationManager();
+
+        configurationManager.log( LogService.LOG_DEBUG, "getFactoryConfiguration(factoryPid={0},
alias={1}, location={2})", new Object[]
+            { factoryPid, alias, location } );
+
+        final String pid = factoryPid + '#' + alias;
 
+        // CM 1.4 / 104.13.2.3
+        this.checkPermission( configurationManager, ( location == null ) ? "*" : location,
false );
+
+        ConfigurationImpl config = configurationManager.getConfiguration( pid );
+        if ( config == null )
+        {
+            config = configurationManager.createConfiguration( pid, factoryPid, location
);
+        }
+        else
+        {
+            final String configLocation = config.getBundleLocation();
+            this.checkPermission( configurationManager, ( configLocation == null ) ? "*"
: configLocation, false );
+        }
 
+        return this.wrap( config );
+      }
+
+
+    /**
+     * @see org.osgi.service.cm.ConfigurationAdmin#getFactoryConfiguration(java.lang.String,
java.lang.String)
+     */
+    @Override
     public Configuration getFactoryConfiguration(String factoryPid, String alias) throws
IOException {
-        // TODO Auto-generated method stub
-        return null;
+        final ConfigurationManager configurationManager = getConfigurationManager();
+
+        configurationManager.log( LogService.LOG_DEBUG, "getFactoryConfiguration(factoryPid={0},
alias={1})", new Object[]
+            { factoryPid, alias } );
+
+        final String pid = factoryPid + '#' + alias;
+
+        ConfigurationImpl config = configurationManager.getConfiguration( pid );
+        if ( config == null )
+        {
+            config = configurationManager.createConfiguration( pid, factoryPid, null );
+
+            // FELIX-3360: configuration creation with implicit binding is dynamic
+            config.setDynamicBundleLocation( getBundle().getLocation(), false );
+        }
+        else
+        {
+            if ( config.getBundleLocation() == null )
+            {
+                configurationManager.log( LogService.LOG_DEBUG, "Binding configuration {0}
(isNew: {1}) to bundle {2}",
+                    new Object[]
+                        { config.getPid(), config.isNew() ? Boolean.TRUE : Boolean.FALSE,
+                            this.getBundle().getLocation() } );
+
+                // FELIX-3360: first implicit binding is dynamic
+                config.setDynamicBundleLocation( getBundle().getLocation(), true );
+            }
+            else
+            {
+                // CM 1.4 / 104.13.2.3
+                this.checkPermission( configurationManager, config.getBundleLocation(), false
);
+            }
+        }
+
+        return this.wrap( config );
     }
 
 }

Modified: felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java?rev=1750478&r1=1750477&r2=1750478&view=diff
==============================================================================
--- felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java
(original)
+++ felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java
Tue Jun 28 11:34:40 2016
@@ -21,6 +21,7 @@ package org.apache.felix.cm.impl;
 
 import java.io.IOException;
 import java.util.Dictionary;
+import java.util.Enumeration;
 import java.util.Hashtable;
 
 import org.apache.felix.cm.PersistenceManager;
@@ -96,6 +97,8 @@ public class ConfigurationImpl extends C
      */
     private static final String CONFIGURATION_NEW = "_felix_.cm.newConfiguration";
 
+    private static final String PROPERTY_LOCKED = ":org.apache.felix.configadmin.locked:";
+
     /**
      * The factory PID of this configuration or <code>null</code> if this
      * is not a factory configuration.
@@ -140,9 +143,11 @@ public class ConfigurationImpl extends C
      */
     private volatile long revision;
 
+    private volatile boolean locked;
+
 
     ConfigurationImpl( ConfigurationManager configurationManager, PersistenceManager persistenceManager,
-        Dictionary properties )
+        Dictionary<String, Object> properties )
     {
         super( configurationManager, persistenceManager, ( String ) properties.remove( Constants.SERVICE_PID
) );
 
@@ -315,7 +320,7 @@ public class ConfigurationImpl extends C
      *            <code>true</code> if a deep copy is to be returned.
      * @return the configuration properties
      */
-    public Dictionary getProperties( boolean deepCopy )
+    public Dictionary<String, Object> getProperties( boolean deepCopy )
     {
         // no properties yet
         if ( properties == null )
@@ -343,7 +348,7 @@ public class ConfigurationImpl extends C
             // read configuration from persistence (again)
             if ( localPersistenceManager.exists( getPidString() ) )
             {
-                Dictionary properties = localPersistenceManager.load( getPidString() );
+                Dictionary<String, Object> properties = localPersistenceManager.load(
getPidString() );
 
                 // ensure serviceReference pid
                 String servicePid = ( String ) properties.get( Constants.SERVICE_PID );
@@ -362,10 +367,10 @@ public class ConfigurationImpl extends C
     }
 
 
-    /* (non-Javadoc)
+    /**
      * @see org.osgi.service.cm.Configuration#update(java.util.Dictionary)
      */
-    public void update( Dictionary properties ) throws IOException
+    public void update( Dictionary<String, ?> properties ) throws IOException
     {
         PersistenceManager localPersistenceManager = getPersistenceManager();
         if ( localPersistenceManager != null )
@@ -397,6 +402,7 @@ public class ConfigurationImpl extends C
 
     //---------- Object overwrites --------------------------------------------
 
+    @Override
     public boolean equals( Object obj )
     {
         if ( obj == this )
@@ -413,12 +419,14 @@ public class ConfigurationImpl extends C
     }
 
 
+    @Override
     public int hashCode()
     {
         return getPidString().hashCode();
     }
 
 
+    @Override
     public String toString()
     {
         return "Configuration PID=" + getPidString() + ", factoryPID=" + factoryPID + ",
bundleLocation=" + getBundleLocation();
@@ -456,7 +464,7 @@ public class ConfigurationImpl extends C
      */
     private void storeNewConfiguration() throws IOException
     {
-        Dictionary props = new Hashtable();
+        Dictionary<String, Object> props = new Hashtable<String, Object>();
         setAutoProperties( props, true );
         props.put( CONFIGURATION_NEW, Boolean.TRUE );
         getPersistenceManager().store( getPidString(), props );
@@ -494,17 +502,18 @@ public class ConfigurationImpl extends C
     }
 
 
+    @Override
     void store() throws IOException
     {
         // we don't need a deep copy, since we are not modifying
         // any value in the dictionary itself. we are just adding
         // properties to it, which are required for storing
-        Dictionary props = getProperties( false );
+        Dictionary<String, Object> props = getProperties( false );
 
         // if this is a new configuration, we just use an empty Dictionary
         if ( props == null )
         {
-            props = new Hashtable();
+            props = new Hashtable<String, Object>();
 
             // add automatic properties including the bundle location (if
             // statically bound)
@@ -515,6 +524,11 @@ public class ConfigurationImpl extends C
             replaceProperty( props, ConfigurationAdmin.SERVICE_BUNDLELOCATION, getStaticBundleLocation()
);
         }
 
+        if ( this.locked )
+        {
+            props.put(PROPERTY_LOCKED, this.locked);
+        }
+
         // only store now, if this is not a new configuration
         getPersistenceManager().store( getPidString(), props );
     }
@@ -555,7 +569,7 @@ public class ConfigurationImpl extends C
     }
 
 
-    private void configureFromPersistence( Dictionary properties )
+    private void configureFromPersistence( Dictionary<String, Object> properties )
     {
         // if the this is not an empty/new configuration, accept the properties
         // otherwise just set the properties field to null
@@ -569,8 +583,13 @@ public class ConfigurationImpl extends C
         }
     }
 
-    private void configure( final Dictionary properties )
+    private void configure( final Dictionary<String, Object> properties )
     {
+        final Object lockedValue = properties == null ? null : properties.get(PROPERTY_LOCKED);
+        if ( lockedValue != null )
+        {
+            this.locked = true;
+        }
         final CaseInsensitiveDictionary newProperties;
         if ( properties == null )
         {
@@ -600,7 +619,7 @@ public class ConfigurationImpl extends C
     }
 
 
-    void setAutoProperties( Dictionary properties, boolean withBundleLocation )
+    void setAutoProperties( Dictionary<String, Object> properties, boolean withBundleLocation
)
     {
         // set pid and factory pid in the properties
         replaceProperty( properties, Constants.SERVICE_PID, getPidString() );
@@ -618,7 +637,7 @@ public class ConfigurationImpl extends C
     }
 
 
-    static void setAutoProperties( Dictionary properties, String pid, String factoryPid )
+    static void setAutoProperties( Dictionary<String, Object> properties, String pid,
String factoryPid )
     {
         replaceProperty( properties, Constants.SERVICE_PID, pid );
         replaceProperty( properties, ConfigurationAdmin.SERVICE_FACTORYPID, factoryPid );
@@ -626,10 +645,105 @@ public class ConfigurationImpl extends C
     }
 
 
-    static void clearAutoProperties( Dictionary properties )
+    private static final String[] AUTO_PROPS = new String[] {
+            Constants.SERVICE_PID,
+            ConfigurationAdmin.SERVICE_FACTORYPID,
+            ConfigurationAdmin.SERVICE_BUNDLELOCATION,
+            PROPERTY_LOCKED
+    };
+
+    static void clearAutoProperties( Dictionary<String, Object> properties )
     {
-        properties.remove( Constants.SERVICE_PID );
-        properties.remove( ConfigurationAdmin.SERVICE_FACTORYPID );
-        properties.remove( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
+        for(final String p : AUTO_PROPS)
+        {
+            properties.remove( p );
+        }
+    }
+
+
+    public void setLocked(final boolean flag) throws IOException
+    {
+        this.locked = flag;
+        store();
+    }
+
+    /**
+     * Compare the two properties, ignoring auto properties
+     * @param props1 Set of properties
+     * @param props2 Set of properties
+     * @return {@code true} if the set of properties is equal
+     */
+    static boolean equals( Dictionary<String, Object> props1, Dictionary<String,
Object> props2)
+    {
+        final int count1 = getCount(props1);
+        final int count2 = getCount(props2);
+        if ( count1 != count2 )
+        {
+            return false;
+        }
+
+        final Enumeration<String> keys = props1.keys();
+        while ( keys.hasMoreElements() )
+        {
+            final String key = keys.nextElement();
+            if ( !isAutoProp(key) )
+            {
+                final Object val1 = props1.get(key);
+                final Object val2 = props2.get(key);
+                if ( val1 == null )
+                {
+                    if ( val2 != null )
+                    {
+                        return false;
+                    }
+                }
+                else
+                {
+                    if ( val2 == null )
+                    {
+                        return false;
+                    }
+                    if ( !val1.equals(val2) )
+                    {
+                        return false;
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+
+    static boolean isAutoProp(final String name)
+    {
+        for(final String p : AUTO_PROPS)
+        {
+            if ( p.equals(name) )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static int getCount( Dictionary<String, Object> props )
+    {
+        int count = (props == null ? 0 : props.size());
+        if ( props != null )
+        {
+            for(final String p : AUTO_PROPS)
+            {
+                if ( props.get(p) != null )
+                {
+                    count--;
+                }
+            }
+        }
+        return count;
+    }
+
+    public boolean isLocked()
+    {
+        return this.locked;
     }
 }

Modified: felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/Configuration.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/Configuration.java?rev=1750478&r1=1750477&r2=1750478&view=diff
==============================================================================
--- felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/Configuration.java
(original)
+++ felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/Configuration.java
Tue Jun 28 11:34:40 2016
@@ -21,6 +21,7 @@ import java.util.Dictionary;
 
 import org.osgi.annotation.versioning.ProviderType;
 import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
 
 /**
  * The configuration information for a {@code ManagedService} or
@@ -105,7 +106,32 @@ public interface Configuration {
 	 */
 	public Dictionary<String, Object> getProperties();
 
-	/**
+    /**
+     * Return the modified properties of this {@code Configuration} object.
+     *
+     * The {@code Dictionary} 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}.
+     *
+     * <p>
+     * Before the properties are returned they are run through all
+     * registered {@link ConfigurationPlugin}s handling the configuration
+     * for this PID.
+     *
+     * <p>
+     * If called just after the configuration is created and before update has
+     * been called, this method returns {@code null}.
+     *
+     * @return A private copy of the properties for the caller or {@code null}.
+     *         These properties must not contain the "service.bundleLocation"
+     *         property. The value of this property may be obtained from the
+     *         {@link #getBundleLocation()} method.
+     * @throws IllegalStateException If this configuration has been deleted.
+     */
+    public Dictionary<String, Object> getModifiedProperties(ServiceReference<ManagedService>
reference);
+
+    /**
 	 * Update the properties of this {@code Configuration} object.
 	 *
 	 * Stores the properties in persistent storage after adding or overwriting
@@ -127,6 +153,7 @@ public interface Configuration {
 	 * {@link ConfigurationEvent#CM_UPDATED} event.
 	 *
 	 * @param properties the new set of properties for this configuration
+	 * @throws LockedConfigurationException if the configuration is locked
 	 * @throws IOException if update cannot be made persistent
 	 * @throws IllegalArgumentException if the {@code Dictionary} object
 	 *         contains invalid configuration types or contains case variants of
@@ -149,6 +176,7 @@ public interface Configuration {
 	 * Also notifies all Configuration Listeners with a
 	 * {@link ConfigurationEvent#CM_DELETED} event.
 	 *
+     * @throws LockedConfigurationException if the configuration is locked
 	 * @throws IOException If delete fails.
 	 * @throws IllegalStateException If this configuration has been deleted.
 	 */
@@ -206,6 +234,8 @@ public interface Configuration {
      * {@link ConfigurationEvent#CM_UPDATED} event.
      *
      * @param properties the new set of properties for this configuration
+     * @return Returns {@code true} if the configuration was updated.
+     *
      * @throws LockedConfigurationException If the configuration is locked
      * @throws IOException if update cannot be made persistent
      * @throws IllegalArgumentException if the {@code Dictionary} object
@@ -214,7 +244,7 @@ public interface Configuration {
      * @throws IllegalStateException If this configuration has been deleted.
      * @since 1.6
      */
-    public void setProperties(Dictionary<String, ?> properties) throws IOException;
+    public boolean setProperties(Dictionary<String, ?> properties) throws IOException;
 
     /**
 	 * Bind this {@code Configuration} object to the specified location.

Modified: felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/ConfigurationPermission.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/ConfigurationPermission.java?rev=1750478&r1=1750477&r2=1750478&view=diff
==============================================================================
--- felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/ConfigurationPermission.java
(original)
+++ felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/ConfigurationPermission.java
Tue Jun 28 11:34:40 2016
@@ -58,7 +58,15 @@ public final class ConfigurationPermissi
 	 */
 	public final static String		TARGET				= "target";
 
-	private final static int		ACTION_CONFIGURE	= 0x00000001;
+    /**
+     * Provides permission to lock a configurations.
+     * The action string {@value #LOCK}.
+     *
+     * @since 1.6
+     */
+    public final static String      LOCK              = "lock";
+
+    private final static int		ACTION_CONFIGURE	= 0x00000001;
 	private final static int		ACTION_TARGET		= 0x00000002;
 	private final static int		ACTION_ALL			= ACTION_CONFIGURE | ACTION_TARGET;
 	final static int				ACTION_NONE			= 0;

Modified: felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/LockedConfigurationException.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/LockedConfigurationException.java?rev=1750478&r1=1750477&r2=1750478&view=diff
==============================================================================
--- felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/LockedConfigurationException.java
(original)
+++ felix/sandbox/cziegeler/configadmin-r7/src/main/java/org/osgi/service/cm/LockedConfigurationException.java
Tue Jun 28 11:34:40 2016
@@ -16,6 +16,8 @@
 
 package org.osgi.service.cm;
 
+import java.io.IOException;
+
 /**
  * An {@code Exception} class to inform the client of a {@code Configuration}
  * about the locked state of a configuration object.
@@ -23,7 +25,7 @@ package org.osgi.service.cm;
  * @author $Id$
  * @since 1.6
  */
-public class LockedConfigurationException extends Exception {
+public class LockedConfigurationException extends IOException {
     static final long       serialVersionUID    = 1898442024230518832L;
 
     /**

Modified: felix/sandbox/cziegeler/configadmin-r7/src/test/java/org/apache/felix/cm/impl/ConfigurationManagerTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configadmin-r7/src/test/java/org/apache/felix/cm/impl/ConfigurationManagerTest.java?rev=1750478&r1=1750477&r2=1750478&view=diff
==============================================================================
--- felix/sandbox/cziegeler/configadmin-r7/src/test/java/org/apache/felix/cm/impl/ConfigurationManagerTest.java
(original)
+++ felix/sandbox/cziegeler/configadmin-r7/src/test/java/org/apache/felix/cm/impl/ConfigurationManagerTest.java
Tue Jun 28 11:34:40 2016
@@ -214,6 +214,7 @@ public class ConfigurationManagerTest ex
 
         SynchronousConfigurationListener syncListener1 = new SynchronousConfigurationListener()
         {
+            @Override
             public void configurationEvent(ConfigurationEvent event)
             {
                 result.add("L1");
@@ -221,6 +222,7 @@ public class ConfigurationManagerTest ex
         };
         SynchronousConfigurationListener syncListener2 = new SynchronousConfigurationListener()
         {
+            @Override
             public void configurationEvent(ConfigurationEvent event)
             {
                 result.add("L2");
@@ -228,6 +230,7 @@ public class ConfigurationManagerTest ex
         };
         SynchronousConfigurationListener syncListener3 = new SynchronousConfigurationListener()
         {
+            @Override
             public void configurationEvent(ConfigurationEvent event)
             {
                 result.add("L3");
@@ -272,7 +275,7 @@ public class ConfigurationManagerTest ex
         utField.setAccessible( true );
         utField.set( configMgr, new UpdateThread( configMgr, null, "Test updater" ));
 
-        Dictionary<String, String> props = new Hashtable<String, String>();
+        Dictionary<String, Object> props = new Hashtable<String, Object>();
         props.put( Constants.SERVICE_PID, "org.acme.testpid" );
         ConfigurationImpl config = new ConfigurationImpl( configMgr, new MockPersistenceManager(),
props );
         configMgr.updated( config, true );




Mime
View raw message