You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2016/09/16 06:11:25 UTC
svn commit: r1760997 [1/2] - in /felix/trunk/configadmin: ./
src/main/java/org/apache/felix/cm/impl/ src/main/java/org/osgi/
src/main/java/org/osgi/service/ src/main/java/org/osgi/service/cm/
src/test/java/org/apache/felix/cm/ src/test/java/org/apache/...
Author: cziegeler
Date: Fri Sep 16 06:11:25 2016
New Revision: 1760997
URL: http://svn.apache.org/viewvc?rev=1760997&view=rev
Log:
FELIX-5288 - Implement RFC 227 (R7 Update)
Added:
felix/trunk/configadmin/src/main/java/org/osgi/
felix/trunk/configadmin/src/main/java/org/osgi/service/
felix/trunk/configadmin/src/main/java/org/osgi/service/cm/
felix/trunk/configadmin/src/main/java/org/osgi/service/cm/Configuration.java (with props)
felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationAdmin.java (with props)
felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationEvent.java (with props)
felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationException.java (with props)
felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationListener.java (with props)
felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationPermission.java (with props)
felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationPlugin.java (with props)
felix/trunk/configadmin/src/main/java/org/osgi/service/cm/LockedConfigurationException.java (with props)
felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ManagedService.java (with props)
felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ManagedServiceFactory.java (with props)
felix/trunk/configadmin/src/main/java/org/osgi/service/cm/SynchronousConfigurationListener.java (with props)
felix/trunk/configadmin/src/main/java/org/osgi/service/cm/package-info.java (with props)
Modified:
felix/trunk/configadmin/changelog.txt
felix/trunk/configadmin/pom.xml
felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdapter.java
felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdminImpl.java
felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java
felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/RankingComparator.java
felix/trunk/configadmin/src/test/java/org/apache/felix/cm/MockBundleContext.java
felix/trunk/configadmin/src/test/java/org/apache/felix/cm/impl/ConfigurationManagerTest.java
felix/trunk/configadmin/src/test/java/org/apache/felix/cm/impl/RankingComparatorTest.java
Modified: felix/trunk/configadmin/changelog.txt
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/changelog.txt?rev=1760997&r1=1760996&r2=1760997&view=diff
==============================================================================
--- felix/trunk/configadmin/changelog.txt (original)
+++ felix/trunk/configadmin/changelog.txt Fri Sep 16 06:11:25 2016
@@ -1,3 +1,14 @@
+Changes in 1.9.0
+----------------
+** Improvement
+ * [FELIX-5288] - Implement RFC 227 (R7 Update)
+ * [FELIX-5289] - PID Handling of Factory Configurations
+ * [FELIX-5290] - Locking Configuration Records
+ * [FELIX-5291] - Improving Configuration Updates
+ * [FELIX-5292] - Capabilities
+ * [FELIX-5293] - Improved ConfigurationPlugin Support
+
+
Changes from 1.8.8 to 1.8.10
----------------------------
Modified: felix/trunk/configadmin/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/pom.xml?rev=1760997&r1=1760996&r2=1760997&view=diff
==============================================================================
--- felix/trunk/configadmin/pom.xml (original)
+++ felix/trunk/configadmin/pom.xml Fri Sep 16 06:11:25 2016
@@ -22,8 +22,8 @@
<parent>
<groupId>org.apache.felix</groupId>
<artifactId>felix-parent</artifactId>
- <version>3</version>
- <relativePath>../pom/pom.xml</relativePath>
+ <version>4</version>
+ <relativePath/>
</parent>
<artifactId>org.apache.felix.configadmin</artifactId>
@@ -68,6 +68,7 @@
in the IDE launcher.
-->
<properties>
+ <felix.java.version>6</felix.java.version>
<bundle.build.name>
${basedir}/target
</bundle.build.name>
@@ -77,29 +78,25 @@
</properties>
<dependencies>
-
- <!--
- Depend on latest version to make use of generics. Still we
- make sure to only require Framework API 1.5 (OSGi Core R4.2)
- -->
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>osgi.annotation</artifactId>
+ <version>6.0.1</version>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
- <version>5.0.0</version>
+ <version>6.0.0</version>
<scope>provided</scope>
</dependency>
-
- <!--
- Configuration Admin and other API from latest enterprise
- which provides Config Admin 1.5 API
- -->
<dependency>
<groupId>org.osgi</groupId>
- <artifactId>org.osgi.enterprise</artifactId>
- <version>5.0.0</version>
+ <artifactId>org.osgi.service.log</artifactId>
+ <version>1.3.0</version>
<scope>provided</scope>
</dependency>
-
+
<!-- BND export annotations -->
<dependency>
<groupId>biz.aQute</groupId>
@@ -112,7 +109,6 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
- <version>4.6</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -160,7 +156,7 @@
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
- <version>4.0.3</version>
+ <version>5.4.0</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -170,7 +166,7 @@
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>2.3.7</version>
+ <version>3.0.1</version>
<extensions>true</extensions>
<configuration>
<instructions>
@@ -190,11 +186,10 @@
<!-- when the spec version changes, update the service property that includes the spec version in ConfigurationManager -->
org.apache.felix.cm;
org.apache.felix.cm.file,
- org.osgi.service.cm;provide:=true;version=1.5
+ org.osgi.service.cm;provide:=true;version=1.6
</Export-Package>
<Import-Package>
- org.osgi.service.cm;version="[1.5,1.6)",
- org.osgi.framework;version="[1.4,2)",
+ org.osgi.service.cm;version="[1.6,1.7)",
org.osgi.service.log;resolution:=optional;version="1.3",
*
</Import-Package>
@@ -202,9 +197,14 @@
<!-- overwrite version from compendium bundle -->
org.osgi.service.log;version="1.3"
</DynamicImport-Package>
- <Provide-Capability>osgi.service;objectClass:List<String>="org.osgi.service.cm.ConfigurationAdmin",
- osgi.service;objectClass:List<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/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdapter.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdapter.java?rev=1760997&r1=1760996&r2=1760997&view=diff
==============================================================================
--- felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdapter.java (original)
+++ felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdapter.java Fri Sep 16 06:11:25 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 );
@@ -169,8 +185,78 @@ public class ConfigurationAdapter implem
/**
+ * @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;
+ }
+
+
+ /**
+ * @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 );
+ }
+
+
+ /**
+ * @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();
+ }
+
+
+ /**
* @see org.apache.felix.cm.impl.ConfigurationImpl#hashCode()
*/
+ @Override
public int hashCode()
{
return delegatee.hashCode();
@@ -181,6 +267,7 @@ public class ConfigurationAdapter implem
* @param obj
* @see org.apache.felix.cm.impl.ConfigurationImpl#equals(java.lang.Object)
*/
+ @Override
public boolean equals( Object obj )
{
return delegatee.equals( obj );
@@ -190,6 +277,7 @@ public class ConfigurationAdapter implem
/**
* @see org.apache.felix.cm.impl.ConfigurationImpl#toString()
*/
+ @Override
public String toString()
{
return delegatee.toString();
@@ -225,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/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdminImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdminImpl.java?rev=1760997&r1=1760996&r2=1760997&view=diff
==============================================================================
--- felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdminImpl.java (original)
+++ felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationAdminImpl.java Fri Sep 16 06:11:25 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.
*
@@ -303,4 +327,79 @@ public class ConfigurationAdminImpl impl
return this.configurationManager;
}
+
+
+ /**
+ * @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 {
+ 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/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java?rev=1760997&r1=1760996&r2=1760997&view=diff
==============================================================================
--- felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java (original)
+++ felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java Fri Sep 16 06:11:25 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/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/RankingComparator.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/RankingComparator.java?rev=1760997&r1=1760996&r2=1760997&view=diff
==============================================================================
--- felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/RankingComparator.java (original)
+++ felix/trunk/configadmin/src/main/java/org/apache/felix/cm/impl/RankingComparator.java Fri Sep 16 06:11:25 2016
@@ -95,16 +95,16 @@ public abstract class RankingComparator
final long id1 = this.getLong( obj1, Constants.SERVICE_ID );
final long id2 = this.getLong( obj2, Constants.SERVICE_ID );
+ if ( id1 == id2 )
+ {
+ return 0;
+ }
+
final int rank1 = this.getInteger( obj1, ConfigurationPlugin.CM_RANKING );
final int rank2 = this.getInteger( obj2, ConfigurationPlugin.CM_RANKING );
if ( rank1 == rank2 )
{
- if ( id1 == id2 )
- {
- return 0;
- }
-
return ( id1 > id2 ) ? -1 : 1;
}
Added: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/Configuration.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/main/java/org/osgi/service/cm/Configuration.java?rev=1760997&view=auto
==============================================================================
--- felix/trunk/configadmin/src/main/java/org/osgi/service/cm/Configuration.java (added)
+++ felix/trunk/configadmin/src/main/java/org/osgi/service/cm/Configuration.java Fri Sep 16 06:11:25 2016
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2016). All Rights Reserved.
+ *
+ * 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.osgi.service.cm;
+
+import java.io.IOException;
+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
+ * {@code ManagedServiceFactory} object.
+ *
+ * The Configuration Admin service uses this interface to represent the
+ * configuration information for a {@code ManagedService} or for a service
+ * instance of a {@code ManagedServiceFactory}.
+ *
+ * <p>
+ * A {@code Configuration} object contains a configuration dictionary and allows
+ * the properties to be updated via this object. Bundles wishing to receive
+ * configuration dictionaries do not need to use this class - they register a
+ * {@code ManagedService} or {@code ManagedServiceFactory}. Only administrative
+ * bundles, and bundles wishing to update their own configurations need to use
+ * this class.
+ *
+ * <p>
+ * The properties handled in this configuration have case insensitive
+ * {@code String} objects as keys. However, case must be preserved from the last
+ * set key/value.
+ * <p>
+ * A configuration can be <i>bound</i> to a specific bundle or to a region of
+ * bundles using the <em>location</em>. In its simplest form the location is the
+ * location of the target bundle that registered a Managed Service or a Managed
+ * Service Factory. However, if the location starts with {@code ?} then the
+ * location indicates multiple delivery. In such a case the configuration must
+ * be delivered to all targets.
+ *
+ * If security is on, the Configuration Permission can be used to restrict the
+ * targets that receive updates. The Configuration Admin must only update a
+ * target when the configuration location matches the location of the target's
+ * bundle or the target bundle has a Configuration Permission with the action
+ * {@link ConfigurationPermission#TARGET} and a name that matches the
+ * configuration location. The name in the permission may contain wildcards (
+ * {@code '*'}) to match the location using the same substring matching rules as
+ * {@link Filter}.
+ *
+ * Bundles can always create, manipulate, and be updated from configurations
+ * that have a location that matches their bundle location.
+ *
+ * <p>
+ * If a configuration's location is {@code null}, it is not yet bound to a
+ * location. It will become bound to the location of the first bundle that
+ * registers a {@code ManagedService} or {@code ManagedServiceFactory} object
+ * with the corresponding PID.
+ * <p>
+ * The same {@code Configuration} object is used for configuring both a Managed
+ * Service Factory and a Managed Service. When it is important to differentiate
+ * between these two the term "factory configuration" is used.
+ *
+ * @author $Id$
+ * @ThreadSafe
+ */
+@ProviderType
+public interface Configuration {
+ /**
+ * Get the PID for this {@code Configuration} object.
+ *
+ * @return the PID for this {@code Configuration} object.
+ * @throws IllegalStateException if this configuration has been deleted
+ */
+ public String getPid();
+
+ /**
+ * Return the 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>
+ * 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> 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
+ * the following properties:
+ * <ul>
+ * <li>"service.pid" : is set to be the PID of this configuration.</li>
+ * <li>"service.factoryPid" : if this is a factory configuration it is set
+ * to the factory PID else it is not set.</li>
+ * </ul>
+ * These system properties are all of type {@code String}.
+ *
+ * <p>
+ * If the corresponding Managed Service/Managed Service Factory is
+ * registered, its updated method must be called asynchronously. Else, this
+ * callback is delayed until aforementioned registration occurs.
+ *
+ * <p>
+ * Also notifies all Configuration Listeners with a
+ * {@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
+ * the same key name.
+ * @throws IllegalStateException If this configuration has been deleted.
+ */
+ public void update(Dictionary<String, ?> properties) throws IOException;
+
+ /**
+ * Delete this {@code Configuration} object.
+ *
+ * Removes this configuration object from the persistent store. Notify
+ * asynchronously the corresponding Managed Service or Managed Service
+ * Factory. A {@link ManagedService} object is notified by a call to its
+ * {@code updated} method with a {@code null} properties argument. A
+ * {@link ManagedServiceFactory} object is notified by a call to its
+ * {@code deleted} method.
+ *
+ * <p>
+ * 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.
+ */
+ public void delete() throws IOException;
+
+ /**
+ * For a factory configuration return the PID of the corresponding Managed
+ * Service Factory, else return {@code null}.
+ *
+ * @return factory PID or {@code null}
+ * @throws IllegalStateException If this configuration has been deleted.
+ */
+ public String getFactoryPid();
+
+ /**
+ * Update the {@code Configuration} object with the current properties.
+ *
+ * Initiate the {@code updated} callback to the Managed Service or Managed
+ * Service Factory with the current properties asynchronously.
+ *
+ * <p>
+ * This is the only way for a bundle that uses a Configuration Plugin
+ * service to initiate a callback. For example, when that bundle detects a
+ * change that requires an update of the Managed Service or Managed Service
+ * Factory via its {@code ConfigurationPlugin} object.
+ *
+ * @see ConfigurationPlugin
+ * @throws IOException if update cannot access the properties in persistent
+ * storage
+ * @throws IllegalStateException If this configuration has been deleted.
+ */
+ public void update() throws IOException;
+
+ /**
+ * Update the properties of this {@code Configuration} object if the
+ * provided properties are different than the currently stored set
+ *
+ * If the properties are the same, no operation is performed, otherwise it
+ * stores the properties in persistent storage after adding or overwriting
+ * the following properties:
+ * <ul>
+ * <li>"service.pid" : is set to be the PID of this configuration.</li>
+ * <li>"service.factoryPid" : if this is a factory configuration it is set
+ * to the factory PID else it is not set.</li>
+ * </ul>
+ * These system properties are all of type {@code String}.
+ *
+ * <p>
+ * If the corresponding Managed Service/Managed Service Factory is
+ * registered, its updated method must be called asynchronously. Else, this
+ * callback is delayed until aforementioned registration occurs.
+ *
+ * <p>
+ * Also notifies all Configuration Listeners with a
+ * {@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
+ * contains invalid configuration types or contains case variants of
+ * the same key name.
+ * @throws IllegalStateException If this configuration has been deleted.
+ * @since 1.6
+ */
+ public boolean setProperties(Dictionary<String, ?> properties) throws IOException;
+
+ /**
+ * Bind this {@code Configuration} object to the specified location.
+ *
+ * If the location parameter is {@code null} then the {@code Configuration}
+ * object will not be bound to a location/region. It will be set to the
+ * bundle's location before the first time a Managed Service/Managed Service
+ * Factory receives this {@code Configuration} object via the updated method
+ * and before any plugins are called. The bundle location or region will be
+ * set persistently.
+ *
+ * <p>
+ * If the location starts with {@code ?} then all targets registered with
+ * the given PID must be updated.
+ *
+ * <p>
+ * If the location is changed then existing targets must be informed. If
+ * they can no longer see this configuration, the configuration must be
+ * deleted or updated with {@code null}. If this configuration becomes
+ * visible then they must be updated with this configuration.
+ *
+ * <p>
+ * Also notifies all Configuration Listeners with a
+ * {@link ConfigurationEvent#CM_LOCATION_CHANGED} event.
+ *
+ * @param location a location, region, or {@code null}
+ * @throws IllegalStateException If this configuration has been deleted.
+ * @throws SecurityException when the required permissions are not available
+ * @throws SecurityException when the required permissions are not available
+ * @security ConfigurationPermission[this.location,CONFIGURE] if
+ * this.location is not {@code null}
+ * @security ConfigurationPermission[location,CONFIGURE] if location is not
+ * {@code null}
+ * @security ConfigurationPermission["*",CONFIGURE] if this.location is
+ * {@code null} or if location is {@code null}
+ */
+ public void setBundleLocation(String location);
+
+ /**
+ * Get the bundle location.
+ *
+ * Returns the bundle location or region to which this configuration is
+ * bound, or {@code null} if it is not yet bound to a bundle location or
+ * region. If the location starts with {@code ?} then the configuration is
+ * delivered to all targets and not restricted to a single bundle.
+ *
+ * @return location to which this configuration is bound, or {@code null}.
+ * @throws IllegalStateException If this configuration has been deleted.
+ * @throws SecurityException when the required permissions are not available
+ * @security ConfigurationPermission[this.location,CONFIGURE] if
+ * this.location is not {@code null}
+ * @security ConfigurationPermission["*",CONFIGURE] if this.location is
+ * {@code null}
+ *
+ */
+ public String getBundleLocation();
+
+ /**
+ * Get the change count.
+ *
+ * Each Configuration must maintain a change counter that is incremented
+ * with a positive value every time the configuration is updated and its
+ * properties are stored. The counter must be incremented before the targets
+ * are updated and events are sent out.
+ *
+ * @return A monotonically increasing value reflecting changes in this
+ * Configuration.
+ * @throws IllegalStateException If this configuration has been deleted.
+ * @since 1.5
+ */
+ public long getChangeCount();
+
+ /**
+ * Locks or unlocks the configuration.
+ * @param flag If {@code true} the configuration is locked,
+ * if {@code false} the configuration is unlocked.
+ * @throws IOException If the new lock state cannot be persisted.
+ * @throws IllegalStateException If this configuration has been deleted.
+ * @since 1.6
+ */
+ public void setLocked(boolean flag) throws IOException;
+
+ /**
+ * Check if the configuration is currently locked.
+ * @return {@code true} if the configuration is locked, {
+ * {@code false} otherwise.
+ * @throws IllegalStateException If this configuration has been deleted.
+ * @since 1.6
+ */
+ public boolean isLocked();
+
+ /**
+ * Equality is defined to have equal PIDs
+ *
+ * Two Configuration objects are equal when their PIDs are equal.
+ *
+ * @param other {@code Configuration} object to compare against
+ * @return {@code true} if equal, {@code false} if not a
+ * {@code Configuration} object or one with a different PID.
+ */
+ @Override
+ public boolean equals(Object other);
+
+ /**
+ * Hash code is based on PID.
+ *
+ * The hash code for two Configuration objects must be the same when the
+ * Configuration PID's are the same.
+ *
+ * @return hash code for this Configuration object
+ */
+ @Override
+ public int hashCode();
+}
Propchange: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/Configuration.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/Configuration.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Added: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationAdmin.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationAdmin.java?rev=1760997&view=auto
==============================================================================
--- felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationAdmin.java (added)
+++ felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationAdmin.java Fri Sep 16 06:11:25 2016
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2016). All Rights Reserved.
+ *
+ * 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.osgi.service.cm;
+
+import java.io.IOException;
+import java.util.Dictionary;
+
+import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+
+/**
+ * Service for administering configuration data.
+ *
+ * <p>
+ * The main purpose of this interface is to store bundle configuration data
+ * persistently. This information is represented in {@code Configuration}
+ * objects. The actual configuration data is a {@code Dictionary} of properties
+ * inside a {@code Configuration} object.
+ *
+ * <p>
+ * There are two principally different ways to manage configurations. First
+ * there is the concept of a Managed Service, where configuration data is
+ * uniquely associated with an object registered with the service registry.
+ *
+ * <p>
+ * Next, there is the concept of a factory where the Configuration Admin service
+ * will maintain 0 or more {@code Configuration} objects for a Managed Service
+ * Factory that is registered with the Framework.
+ *
+ * <p>
+ * The first concept is intended for configuration data about "things/services"
+ * whose existence is defined externally, e.g. a specific printer. Factories are
+ * intended for "things/services" that can be created any number of times, e.g.
+ * a configuration for a DHCP server for different networks.
+ *
+ * <p>
+ * Bundles that require configuration should register a Managed Service or a
+ * Managed Service Factory in the service registry. A registration property
+ * named {@code service.pid} (persistent identifier or PID) must be used to
+ * identify this Managed Service or Managed Service Factory to the Configuration
+ * Admin service.
+ *
+ * <p>
+ * When the ConfigurationAdmin detects the registration of a Managed Service, it
+ * checks its persistent storage for a configuration object whose
+ * {@code service.pid} property matches the PID service property (
+ * {@code service.pid}) of the Managed Service. If found, it calls
+ * {@link ManagedService#updated(Dictionary)} method with the new properties.
+ * The implementation of a Configuration Admin service must run these call-backs
+ * asynchronously to allow proper synchronization.
+ *
+ * <p>
+ * When the Configuration Admin service detects a Managed Service Factory
+ * registration, it checks its storage for configuration objects whose
+ * {@code service.factoryPid} property matches the PID service property of the
+ * Managed Service Factory. For each such {@code Configuration} objects, it
+ * calls the {@code ManagedServiceFactory.updated} method asynchronously with
+ * the new properties. The calls to the {@code updated} method of a
+ * {@code ManagedServiceFactory} must be executed sequentially and not overlap
+ * in time.
+ *
+ * <p>
+ * In general, bundles having permission to use the Configuration Admin service
+ * can only access and modify their own configuration information. Accessing or
+ * modifying the configuration of other bundles requires
+ * {@code ConfigurationPermission[location,CONFIGURE]}, where location is the
+ * configuration location.
+ *
+ * <p>
+ * {@code Configuration} objects can be <i>bound</i> to a specified bundle
+ * location or to a region (configuration location starts with {@code ?}). If a
+ * location is not set, it will be learned the first time a target is
+ * registered. If the location is learned this way, the Configuration Admin
+ * service must detect if the bundle corresponding to the location is
+ * uninstalled. If this occurs, the {@code Configuration} object must be
+ * unbound, that is its location field is set back to {@code null}.
+ *
+ * <p>
+ * If target's bundle location matches the configuration location it is always
+ * updated.
+ *
+ * <p>
+ * If the configuration location starts with {@code ?}, that is, the location is
+ * a region, then the configuration must be delivered to all targets registered
+ * with the given PID. If security is on, the target bundle must have
+ * Configuration Permission[location,TARGET], where location matches given the
+ * configuration location with wildcards as in the Filter substring match. The
+ * security must be verified using the
+ * {@link org.osgi.framework.Bundle#hasPermission(Object)} method on the target
+ * bundle.
+ *
+ * <p>
+ * If a target cannot be updated because the location does not match or it has
+ * no permission and security is active then the Configuration Admin service
+ * must not do the normal callback.
+ *
+ * <p>
+ * The method descriptions of this class refer to a concept of "the calling
+ * bundle". This is a loose way of referring to the bundle which obtained the
+ * Configuration Admin service from the service registry. Implementations of
+ * {@code ConfigurationAdmin} must use a
+ * {@link org.osgi.framework.ServiceFactory} to support this concept.
+ *
+ * @author $Id$
+ * @ThreadSafe
+ */
+@ProviderType
+public interface ConfigurationAdmin {
+ /**
+ * Configuration property naming the Factory PID in the configuration
+ * dictionary. The property's value is of type {@code String}.
+ *
+ * @since 1.1
+ */
+ public final static String SERVICE_FACTORYPID = "service.factoryPid";
+ /**
+ * Configuration property naming the location of the bundle that is
+ * associated with a {@code Configuration} object. This property can be
+ * searched for but must not appear in the configuration dictionary for
+ * security reason. The property's value is of type {@code String}.
+ *
+ * @since 1.1
+ */
+ public final static String SERVICE_BUNDLELOCATION = "service.bundleLocation";
+
+ /**
+ * Create a new factory {@code Configuration} object with a new PID.
+ *
+ * The properties of the new {@code Configuration} object are {@code null}
+ * until the first time that its {@link Configuration#update(Dictionary)}
+ * method is called.
+ *
+ * <p>
+ * It is not required that the {@code factoryPid} maps to a registered
+ * Managed Service Factory.
+ *
+ * <p>
+ * The {@code Configuration} object is bound to the location of the calling
+ * bundle. It is possible that the same factoryPid has associated
+ * configurations that are bound to different bundles. Bundles should only
+ * see the factory configurations that they are bound to or have the proper
+ * permission.
+ *
+ * @param factoryPid PID of factory (not {@code null}).
+ * @return A new {@code Configuration} object.
+ * @throws IOException if access to persistent storage fails.
+ */
+ public Configuration createFactoryConfiguration(String factoryPid) throws IOException;
+
+ /**
+ * Create a new factory {@code Configuration} object with a new PID.
+ *
+ * The properties of the new {@code Configuration} object are {@code null}
+ * until the first time that its {@link Configuration#update(Dictionary)}
+ * method is called.
+ *
+ * <p>
+ * It is not required that the {@code factoryPid} maps to a registered
+ * Managed Service Factory.
+ *
+ * <p>
+ * The {@code Configuration} is bound to the location specified. If this
+ * location is {@code null} it will be bound to the location of the first
+ * bundle that registers a Managed Service Factory with a corresponding PID.
+ * It is possible that the same factoryPid has associated configurations
+ * that are bound to different bundles. Bundles should only see the factory
+ * configurations that they are bound to or have the proper permission.
+ *
+ * <p>
+ * If the location starts with {@code ?} then the configuration must be
+ * delivered to all targets with the corresponding PID.
+ *
+ * @param factoryPid PID of factory (not {@code null}).
+ * @param location A bundle location string, or {@code null}.
+ * @return a new {@code Configuration} object.
+ * @throws IOException if access to persistent storage fails.
+ * @throws SecurityException when the require permissions are not available
+ * @security ConfigurationPermission[location,CONFIGURE] if location is not
+ * {@code null}
+ * @security ConfigurationPermission["*",CONFIGURE] if location is
+ * {@code null}
+ */
+ public Configuration createFactoryConfiguration(String factoryPid, String location) throws IOException;
+
+ /**
+ * Get an existing {@code Configuration} object from the persistent store,
+ * or create a new {@code Configuration} object.
+ *
+ * <p>
+ * If a {@code Configuration} with this PID already exists in Configuration
+ * Admin service return it. The location parameter is ignored in this case
+ * though it is still used for a security check.
+ *
+ * <p>
+ * Else, return a new {@code Configuration} object. This new object is bound
+ * to the location and the properties are set to {@code null}. If the
+ * location parameter is {@code null}, it will be set when a Managed Service
+ * with the corresponding PID is registered for the first time. If the
+ * location starts with {@code ?} then the configuration is bound to all
+ * targets that are registered with the corresponding PID.
+ *
+ * @param pid Persistent identifier.
+ * @param location The bundle location string, or {@code null}.
+ * @return An existing or new {@code Configuration} object.
+ * @throws IOException if access to persistent storage fails.
+ * @throws SecurityException when the require permissions are not available
+ * @security ConfigurationPermission[*,CONFIGURE] if location is
+ * {@code null} or if the returned configuration {@code c} already
+ * exists and c.location is {@code null}
+ * @security ConfigurationPermission[location,CONFIGURE] if location is not
+ * {@code null}
+ * @security ConfigurationPermission[c.location,CONFIGURE] if the returned
+ * configuration {@code c} already exists and c.location is not
+ * {@code null}
+ */
+ public Configuration getConfiguration(String pid, String location) throws IOException;
+
+ /**
+ * Get an existing or new {@code Configuration} object from the persistent
+ * store.
+ *
+ * If the {@code Configuration} object for this PID does not exist, create a
+ * new {@code Configuration} object for that PID, where properties are
+ * {@code null}. Bind its location to the calling bundle's location.
+ *
+ * <p>
+ * Otherwise, if the location of the existing {@code Configuration} object
+ * is {@code null}, set it to the calling bundle's location.
+ *
+ * @param pid persistent identifier.
+ * @return an existing or new {@code Configuration} matching the PID.
+ * @throws IOException if access to persistent storage fails.
+ * @throws SecurityException when the required permission is not available
+ * @security ConfigurationPermission[c.location,CONFIGURE] If the
+ * configuration {@code c} already exists and c.location is not
+ * {@code null}
+ */
+ public Configuration getConfiguration(String pid) throws IOException;
+
+ /**
+ * Get an existing or new {@code Configuration} object from the persistent
+ * store.
+ *
+ * The PID for this {@code Configuration} object is generated from the
+ * provided factory PID and the alias by starting with the factory PID
+ * appending the character # and then appending the alias.
+ *
+ * <p>
+ * If a {@code Configuration} with this PID already exists in Configuration
+ * Admin service return it. The location parameter is ignored in this case
+ * though it is still used for a security check.
+ *
+ * <p>
+ * Else, return a new {@code Configuration} object. This new object is bound
+ * to the location and the properties are set to {@code null}. If the
+ * location parameter is {@code null}, it will be set when a Managed Service
+ * with the corresponding PID is registered for the first time. If the
+ * location starts with {@code ?} then the configuration is bound to all
+ * targets that are registered with the corresponding PID.
+ *
+ * @param factoryPid PID of factory (not {@code null}).
+ * @param alias An alias for {@code Configuration} (not {@code null}).
+ * @param location The bundle location string, or {@code null}.
+ * @return An existing or new {@code Configuration} object.
+ * @throws IOException if access to persistent storage fails.
+ * @throws SecurityException when the require permissions are not available
+ * @security ConfigurationPermission[*,CONFIGURE] if location is
+ * {@code null} or if the returned configuration {@code c} already
+ * exists and c.location is {@code null}
+ * @security ConfigurationPermission[location,CONFIGURE] if location is not
+ * {@code null}
+ * @security ConfigurationPermission[c.location,CONFIGURE] if the returned
+ * configuration {@code c} already exists and c.location is not
+ * {@code null}
+ * @since 1.6
+ */
+ public Configuration getFactoryConfiguration(String factoryPid, String alias, String location) throws IOException;
+
+ /**
+ * Get an existing or new {@code Configuration} object from the persistent
+ * store.
+ *
+ * The PID for this {@code Configuration} object is generated from the
+ * provided factory PID and the alias by starting with the factory PID
+ * appending the character # and then appending the alias.
+ *
+ * If the {@code Configuration} object for this PID does not exist, create a
+ * new {@code Configuration} object for that PID, where properties are
+ * {@code null}. Bind its location to the calling bundle's location.
+ *
+ * <p>
+ * Otherwise, if the location of the existing {@code Configuration} object
+ * is {@code null}, set it to the calling bundle's location.
+ *
+ * @param factoryPid PID of factory (not {@code null}).
+ * @param alias An alias for {@code Configuration} (not {@code null}).
+ * @return an existing or new {@code Configuration} matching the PID.
+ * @throws IOException if access to persistent storage fails.
+ * @throws SecurityException when the required permission is not available
+ * @security ConfigurationPermission[c.location,CONFIGURE] If the
+ * configuration {@code c} already exists and c.location is not
+ * {@code null}
+ * @since 1.6
+ */
+ public Configuration getFactoryConfiguration(String factoryPid, String alias) throws IOException;
+
+ /**
+ * List the current {@code Configuration} objects which match the filter.
+ *
+ * <p>
+ * Only {@code Configuration} objects with non- {@code null} properties are
+ * considered current. That is, {@code Configuration.getProperties()} is
+ * guaranteed not to return {@code null} for each of the returned
+ * {@code Configuration} objects.
+ *
+ * <p>
+ * When there is no security on then all configurations can be returned. If
+ * security is on, the caller must have
+ * ConfigurationPermission[location,CONFIGURE].
+ *
+ * <p>
+ * The syntax of the filter string is as defined in the {@link Filter}
+ * class. The filter can test any configuration properties including the
+ * following:
+ * <ul>
+ * <li>{@code service.pid} - the persistent identity</li>
+ * <li>{@code service.factoryPid} - the factory PID, if applicable</li>
+ * <li>{@code service.bundleLocation} - the bundle location</li>
+ * </ul>
+ * The filter can also be {@code null}, meaning that all
+ * {@code Configuration} objects should be returned.
+ *
+ * @param filter A filter string, or {@code null} to retrieve all
+ * {@code Configuration} objects.
+ * @return All matching {@code Configuration} objects, or {@code null} if
+ * there aren't any.
+ * @throws IOException if access to persistent storage fails
+ * @throws InvalidSyntaxException if the filter string is invalid
+ * @security ConfigurationPermission[c.location,CONFIGURE] Only
+ * configurations {@code c} are returned for which the caller has
+ * this permission
+ */
+ public Configuration[] listConfigurations(String filter) throws IOException, InvalidSyntaxException;
+}
Propchange: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationAdmin.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationAdmin.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Added: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationEvent.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationEvent.java?rev=1760997&view=auto
==============================================================================
--- felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationEvent.java (added)
+++ felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationEvent.java Fri Sep 16 06:11:25 2016
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2016). All Rights Reserved.
+ *
+ * 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.osgi.service.cm;
+
+import java.util.Dictionary;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * A Configuration Event.
+ *
+ * <p>
+ * {@code ConfigurationEvent} objects are delivered to all registered
+ * {@code ConfigurationListener} service objects. ConfigurationEvents must be
+ * delivered in chronological order with respect to each listener.
+ *
+ * <p>
+ * A type code is used to identify the type of event. The following event types
+ * are defined:
+ * <ul>
+ * <li>{@link #CM_UPDATED}</li>
+ * <li>{@link #CM_DELETED}</li>
+ * <li>{@link #CM_LOCATION_CHANGED}</li>
+ * </ul>
+ * Additional event types may be defined in the future.
+ *
+ * <p>
+ * Security Considerations. {@code ConfigurationEvent} objects do not provide
+ * {@code Configuration} objects, so no sensitive configuration information is
+ * available from the event. If the listener wants to locate the
+ * {@code Configuration} object for the specified pid, it must use
+ * {@code ConfigurationAdmin}.
+ *
+ * @see ConfigurationListener
+ * @Immutable
+ * @author $Id$
+ * @since 1.2
+ */
+public class ConfigurationEvent {
+ /**
+ * A {@code Configuration} has been updated.
+ *
+ * <p>
+ * This {@code ConfigurationEvent} type that indicates that a
+ * {@code Configuration} object has been updated with new properties.
+ *
+ * An event is fired when a call to {@link Configuration#update(Dictionary)}
+ * successfully changes a configuration.
+ */
+ public static final int CM_UPDATED = 1;
+ /**
+ * A {@code Configuration} has been deleted.
+ *
+ * <p>
+ * This {@code ConfigurationEvent} type that indicates that a
+ * {@code Configuration} object has been deleted.
+ *
+ * An event is fired when a call to {@link Configuration#delete()}
+ * successfully deletes a configuration.
+ */
+ public static final int CM_DELETED = 2;
+
+ /**
+ * The location of a {@code Configuration} has been changed.
+ *
+ * <p>
+ * This {@code ConfigurationEvent} type that indicates that the location of
+ * a {@code Configuration} object has been changed.
+ *
+ * An event is fired when a call to
+ * {@link Configuration#setBundleLocation(String)} successfully changes the
+ * location.
+ *
+ * @since 1.4
+ */
+ public static final int CM_LOCATION_CHANGED = 3;
+ /**
+ * Type of this event.
+ *
+ * @see #getType()
+ */
+ private final int type;
+ /**
+ * The factory pid associated with this event.
+ */
+ private final String factoryPid;
+ /**
+ * The pid associated with this event.
+ */
+ private final String pid;
+ /**
+ * The ConfigurationAdmin service which created this event.
+ */
+ private final ServiceReference<ConfigurationAdmin> reference;
+
+ /**
+ * Constructs a {@code ConfigurationEvent} object from the given
+ * {@code ServiceReference} object, event type, and pids.
+ *
+ * @param reference The {@code ServiceReference} object of the Configuration
+ * Admin service that created this event.
+ * @param type The event type. See {@link #getType()}.
+ * @param factoryPid The factory pid of the associated configuration if the
+ * target of the configuration is a ManagedServiceFactory. Otherwise
+ * {@code null} if the target of the configuration is a
+ * ManagedService.
+ * @param pid The pid of the associated configuration.
+ */
+ public ConfigurationEvent(ServiceReference<ConfigurationAdmin> reference, int type, String factoryPid, String pid) {
+ this.reference = reference;
+ this.type = type;
+ this.factoryPid = factoryPid;
+ this.pid = pid;
+ if ((reference == null) || (pid == null)) {
+ throw new NullPointerException("reference and pid must not be null");
+ }
+ }
+
+ /**
+ * Returns the factory pid of the associated configuration.
+ *
+ * @return Returns the factory pid of the associated configuration if the
+ * target of the configuration is a ManagedServiceFactory. Otherwise
+ * {@code null} if the target of the configuration is a
+ * ManagedService.
+ */
+ public String getFactoryPid() {
+ return factoryPid;
+ }
+
+ /**
+ * Returns the pid of the associated configuration.
+ *
+ * @return Returns the pid of the associated configuration.
+ */
+ public String getPid() {
+ return pid;
+ }
+
+ /**
+ * Return the type of this event.
+ * <p>
+ * The type values are:
+ * <ul>
+ * <li>{@link #CM_UPDATED}</li>
+ * <li>{@link #CM_DELETED}</li>
+ * <li>{@link #CM_LOCATION_CHANGED}</li>
+ * </ul>
+ *
+ * @return The type of this event.
+ */
+ public int getType() {
+ return type;
+ }
+
+ /**
+ * Return the {@code ServiceReference} object of the Configuration Admin
+ * service that created this event.
+ *
+ * @return The {@code ServiceReference} object for the Configuration Admin
+ * service that created this event.
+ */
+ public ServiceReference<ConfigurationAdmin> getReference() {
+ return reference;
+ }
+}
Propchange: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationEvent.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationEvent.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Added: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationException.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationException.java?rev=1760997&view=auto
==============================================================================
--- felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationException.java (added)
+++ felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationException.java Fri Sep 16 06:11:25 2016
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) OSGi Alliance (2001, 2016). All Rights Reserved.
+ *
+ * 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.osgi.service.cm;
+
+/**
+ * An {@code Exception} class to inform the Configuration Admin service of
+ * problems with configuration data.
+ *
+ * @author $Id$
+ */
+public class ConfigurationException extends Exception {
+ static final long serialVersionUID = -1690090413441769377L;
+
+ private final String property;
+ private final String reason;
+
+ /**
+ * Create a {@code ConfigurationException} object.
+ *
+ * @param property name of the property that caused the problem,
+ * {@code null} if no specific property was the cause
+ * @param reason reason for failure
+ */
+ public ConfigurationException(String property, String reason) {
+ super(property + " : " + reason);
+ this.property = property;
+ this.reason = reason;
+ }
+
+ /**
+ * Create a {@code ConfigurationException} object.
+ *
+ * @param property name of the property that caused the problem,
+ * {@code null} if no specific property was the cause
+ * @param reason reason for failure
+ * @param cause The cause of this exception.
+ * @since 1.2
+ */
+ public ConfigurationException(String property, String reason, Throwable cause) {
+ super(property + " : " + reason, cause);
+ this.property = property;
+ this.reason = reason;
+ }
+
+ /**
+ * Return the property name that caused the failure or null.
+ *
+ * @return name of property or null if no specific property caused the
+ * problem
+ */
+ public String getProperty() {
+ return property;
+ }
+
+ /**
+ * Return the reason for this exception.
+ *
+ * @return reason of the failure
+ */
+ public String getReason() {
+ return reason;
+ }
+
+ /**
+ * Returns the cause of this exception or {@code null} if no cause was set.
+ *
+ * @return The cause of this exception or {@code null} if no cause was set.
+ * @since 1.2
+ */
+ @Override
+ public Throwable getCause() {
+ return super.getCause();
+ }
+
+ /**
+ * Initializes the cause of this exception to the specified value.
+ *
+ * @param cause The cause of this exception.
+ * @return This exception.
+ * @throws IllegalArgumentException If the specified cause is this
+ * exception.
+ * @throws IllegalStateException If the cause of this exception has already
+ * been set.
+ * @since 1.2
+ */
+ @Override
+ public Throwable initCause(Throwable cause) {
+ return super.initCause(cause);
+ }
+}
Propchange: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationException.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationException.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Added: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationListener.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationListener.java?rev=1760997&view=auto
==============================================================================
--- felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationListener.java (added)
+++ felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationListener.java Fri Sep 16 06:11:25 2016
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2016). All Rights Reserved.
+ *
+ * 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.osgi.service.cm;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * Listener for Configuration Events. When a {@code ConfigurationEvent} is
+ * fired, it is asynchronously delivered to all {@code ConfigurationListener}s.
+ *
+ * <p>
+ * {@code ConfigurationListener} objects are registered with the Framework
+ * service registry and are notified with a {@code ConfigurationEvent} object
+ * when an event is fired.
+ * <p>
+ * {@code ConfigurationListener} objects can inspect the received
+ * {@code ConfigurationEvent} object to determine its type, the pid of the
+ * {@code Configuration} object with which it is associated, and the
+ * Configuration Admin service that fired the event.
+ *
+ * <p>
+ * Security Considerations. Bundles wishing to monitor configuration events will
+ * require {@code ServicePermission[ConfigurationListener,REGISTER]} to register
+ * a {@code ConfigurationListener} service.
+ *
+ * @author $Id$
+ * @since 1.2
+ * @ThreadSafe
+ */
+@ConsumerType
+public interface ConfigurationListener {
+ /**
+ * Receives notification of a Configuration that has changed.
+ *
+ * @param event The {@code ConfigurationEvent}.
+ */
+ public void configurationEvent(ConfigurationEvent event);
+}
Propchange: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationListener.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationListener.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url