FELIX-1897 Add support for Configuration Admin configuration (in addition to the existing bundle context properties)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@884484 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/pom.xml b/scr/pom.xml
index e594202..beb59d6 100644
--- a/scr/pom.xml
+++ b/scr/pom.xml
@@ -140,6 +140,20 @@
<build>
<directory>${bundle.build.name}</directory>
<plugins>
+ <!-- generate the MetaType descriptor for the configuration -->
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-scr-plugin</artifactId>
+ <version>1.4.0</version>
+ <executions>
+ <execution>
+ <id>generate-scr-scrdescriptor</id>
+ <goals>
+ <goal>scr</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/Activator.java b/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
index 5638db5..d0465b7 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
@@ -25,6 +25,7 @@
import java.util.Map;
import org.apache.felix.scr.impl.config.ConfigurationComponentRegistry;
+import org.apache.felix.scr.impl.config.ScrConfiguration;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
@@ -46,6 +47,9 @@
// name of the LogService class (this is a string to not create a reference to the class)
static final String LOGSERVICE_CLASS = "org.osgi.service.log.LogService";
+ // Our configuration from bundle context properties and Config Admin
+ private ScrConfiguration m_configuration;
+
// Flag that sets error messages
private static int m_logLevel = LogService.LOG_ERROR;
@@ -64,7 +68,6 @@
// thread acting upon configurations
private ComponentActorThread m_componentActor;
-
/**
* Registers this instance as a (synchronous) bundle listener and loads the
* components of already registered bundles.
@@ -82,13 +85,15 @@
m_logService = new ServiceTracker( context, LOGSERVICE_CLASS, null );
m_logService.open();
+ // get the configuration
+ m_configuration = new ScrConfiguration( context );
+
// configure logging from context properties
- m_logLevel = getLogLevel( context );
- if ( "true".equalsIgnoreCase( context.getProperty( "ds.showversion" ) ) )
- {
- log( LogService.LOG_INFO, context.getBundle(), " Version = "
- + context.getBundle().getHeaders().get( Constants.BUNDLE_VERSION ), null );
- }
+ m_logLevel = m_configuration.getLogLevel();
+
+ // log SCR startup
+ log( LogService.LOG_INFO, context.getBundle(), " Version = "
+ + context.getBundle().getHeaders().get( Constants.BUNDLE_VERSION ), null );
// create and start the component actor
m_componentActor = new ComponentActorThread();
@@ -110,7 +115,7 @@
// Register "scr" impl command service as a
// wrapper for the bundle repository service.
context.registerService( org.apache.felix.shell.Command.class.getName(), new ScrCommand( m_context,
- m_componentRegistry ), null );
+ m_componentRegistry, m_configuration ), null );
}
catch ( Throwable th )
{
@@ -231,7 +236,7 @@
try
{
BundleComponentActivator ga = new BundleComponentActivator( m_componentRegistry, m_componentActor, context,
- m_logLevel );
+ m_configuration );
m_componentBundles.put( new Long( bundle.getBundleId() ), ga );
}
catch ( Exception e )
@@ -316,56 +321,6 @@
}
- private static int getLogLevel( BundleContext bundleContext )
- {
- String levelString = bundleContext.getProperty( "ds.loglevel" );
- if ( levelString != null )
- {
- try
- {
- return Integer.parseInt( levelString );
- }
- catch ( NumberFormatException nfe )
- {
- // might be a descriptive name
- }
-
- if ( "debug".equalsIgnoreCase( levelString ) )
- {
- return LogService.LOG_DEBUG;
- }
- else if ( "info".equalsIgnoreCase( levelString ) )
- {
- return LogService.LOG_INFO;
- }
- else if ( "warn".equalsIgnoreCase( levelString ) )
- {
- return LogService.LOG_WARNING;
- }
- else if ( "error".equalsIgnoreCase( levelString ) )
- {
- return LogService.LOG_ERROR;
- }
- }
-
- // check ds.showtrace property
- levelString = bundleContext.getProperty( "ds.trace" );
- if ( "true".equalsIgnoreCase( bundleContext.getProperty( "ds.showtrace" ) ) )
- {
- return LogService.LOG_DEBUG;
- }
-
- // next check ds.showerrors property
- if ( "false".equalsIgnoreCase( bundleContext.getProperty( "ds.showerrors" ) ) )
- {
- return -1; // no logging at all !!
- }
-
- // default log level (errors only)
- return LogService.LOG_ERROR;
- }
-
-
/**
* Method to actually emit the log message. If the LogService is available,
* the message will be logged through the LogService. Otherwise the message
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
index 1b1a3fe..2d6df6a 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
@@ -32,6 +32,7 @@
import java.util.StringTokenizer;
import org.apache.felix.scr.impl.config.ComponentHolder;
+import org.apache.felix.scr.impl.config.ScrConfiguration;
import org.apache.felix.scr.impl.helper.Logger;
import org.apache.felix.scr.impl.manager.AbstractComponentManager;
import org.apache.felix.scr.impl.metadata.ComponentMetadata;
@@ -69,8 +70,8 @@
// true as long as the dispose method is not called
private boolean m_active;
- // the logging level
- private int m_logLevel;
+ // the configuration
+ private ScrConfiguration m_configuration;
/**
@@ -85,7 +86,7 @@
* @throws ComponentException if any error occurrs initializing this class
*/
BundleComponentActivator( ComponentRegistry componentRegistry,
- ComponentActorThread componentActor, BundleContext context, int logLevel ) throws ComponentException
+ ComponentActorThread componentActor, BundleContext context, ScrConfiguration configuration ) throws ComponentException
{
// keep the parameters for later
m_componentRegistry = componentRegistry;
@@ -98,7 +99,7 @@
// have the LogService handy (if available)
m_logService = new ServiceTracker( context, Activator.LOGSERVICE_CLASS, null );
m_logService.open();
- m_logLevel = logLevel;
+ m_configuration = configuration;
// Get the Metadata-Location value from the manifest
String descriptorLocations = ( String ) m_context.getBundle().getHeaders().get( "Service-Component" );
@@ -366,6 +367,12 @@
}
+ public ScrConfiguration getConfiguration()
+ {
+ return m_configuration;
+ }
+
+
/**
* Implements the <code>ComponentContext.enableComponent(String)</code>
* method by first finding the component(s) for the <code>name</code> and
@@ -533,7 +540,7 @@
*/
public boolean isLogEnabled( int level )
{
- return m_logLevel >= level;
+ return m_configuration.getLogLevel() >= level;
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java b/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java
index 75ee6ec..1d0b2ab 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java
@@ -30,6 +30,7 @@
import org.apache.felix.scr.Component;
import org.apache.felix.scr.Reference;
import org.apache.felix.scr.ScrService;
+import org.apache.felix.scr.impl.config.ScrConfiguration;
import org.apache.felix.shell.Command;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -43,15 +44,18 @@
private static final String INFO_CMD = "info";
private static final String ENABLE_CMD = "enable";
private static final String DISABLE_CMD = "disable";
+ private static final String CONFIG_CMD = "config";
private final BundleContext bundleContext;
private final ScrService scrService;
+ private final ScrConfiguration scrConfiguration;
- ScrCommand( BundleContext bundleContext, ScrService scrService )
+ ScrCommand( BundleContext bundleContext, ScrService scrService, ScrConfiguration scrConfiguration )
{
this.bundleContext = bundleContext;
this.scrService = scrService;
+ this.scrConfiguration = scrConfiguration;
}
@@ -113,6 +117,10 @@
{
change( st, out, err, false );
}
+ else if ( command.equals( CONFIG_CMD ) )
+ {
+ config( out );
+ }
else
{
err.println( "Unknown command: " + command );
@@ -340,6 +348,17 @@
}
+ private void config( PrintStream out )
+ {
+ out.print( "Log Level: " );
+ out.println( scrConfiguration.getLogLevel() );
+ out.print( "Component Factory with Factory Configuration: " );
+ out.println( scrConfiguration.isFactoryEnabled() ? "Supported" : "Unsupported" );
+ out.print( "Update bound Service Properties: " );
+ out.println( scrConfiguration.isRebindEnabled() ? "Yes" : "No" );
+ }
+
+
private void help( PrintStream out, StringTokenizer st )
{
String command = HELP_CMD;
@@ -381,6 +400,14 @@
out.println( "This command disables the component whose component ID\n" + "is given as command argument." );
out.println( "" );
}
+ else if ( command.equals( CONFIG_CMD ) )
+ {
+ out.println( "" );
+ out.println( "scr " + CONFIG_CMD );
+ out.println( "" );
+ out.println( "This command lists the current SCR configuration." );
+ out.println( "" );
+ }
else
{
out.println( "scr " + HELP_CMD + " [" + LIST_CMD + "]" );
@@ -388,6 +415,7 @@
out.println( "scr " + INFO_CMD + " <componentId>" );
out.println( "scr " + ENABLE_CMD + " <componentId>" );
out.println( "scr " + DISABLE_CMD + " <componentId>" );
+ out.println( "scr " + CONFIG_CMD );
}
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/config/ScrConfiguration.java b/scr/src/main/java/org/apache/felix/scr/impl/config/ScrConfiguration.java
new file mode 100644
index 0000000..c72503b
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/config/ScrConfiguration.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scr.impl.config;
+
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.log.LogService;
+
+
+/**
+ * The <code>ScrConfiguration</code> class conveys configuration for the
+ * Felix DS implementation bundle. The basic configuration is retrieved from
+ * bundle context properties. In addition, this class registers a ManagedService
+ * service to receive configuration supplied from the Configuration Admin
+ * service overlaying the static context properties.
+ *
+ * @scr.component ds="false" name="org.apache.felix.scr.ScrService"
+ */
+public class ScrConfiguration
+{
+
+ private static final String VALUE_TRUE = "true";
+
+ private static final String PROP_FACTORY_ENABLED = "ds.factory.enabled";
+
+ private static final String PROP_REBIND_ENABLED = "ds.rebind.enabled";
+
+ private static final String PROP_LOGLEVEL = "ds.loglevel";
+
+ private static final String LOG_LEVEL_DEBUG = "debug";
+
+ private static final String LOG_LEVEL_INFO = "info";
+
+ private static final String LOG_LEVEL_WARN = "warn";
+
+ private static final String LOG_LEVEL_ERROR = "error";
+
+ private static final String PROP_SHOWTRACE = "ds.showtrace";
+
+ private static final String PROP_SHOWERRORS = "ds.showerrors";
+
+ private final BundleContext bundleContext;
+
+ /**
+ * @scr.property nameRef="PROP_LOGLEVEL" valueRef="LogService.LOG_ERROR"
+ * type="Integer"
+ * options 4="Debug" 3="Information" 2="Warnings" 1="Error"
+ */
+ private int logLevel;
+
+ /**
+ * @scr.property nameRef="PROP_FACTORY_ENABLED" value="false" type="Boolean"
+ */
+ private boolean factoryEnabled;
+
+ /**
+ * @scr.property nameRef="PROP_REBIND_ENABLED" value="false" type="Boolean"
+ */
+ private boolean rebindEnabled;
+
+
+ public ScrConfiguration( BundleContext bundleContext )
+ {
+ this.bundleContext = bundleContext;
+
+ // default configuration
+ configure( null );
+
+ // listen for Configuration Admin configuration
+ try
+ {
+ Object service = new ManagedService()
+ {
+ public void updated( Dictionary properties ) throws ConfigurationException
+ {
+ configure( properties );
+ }
+ };
+ Dictionary props = new Hashtable();
+ props.put( Constants.SERVICE_PID, "org.apache.felix.scr.ScrService" );
+ bundleContext.registerService( ManagedService.class.getName(), service, props );
+ }
+ catch ( Throwable t )
+ {
+ // don't care
+ }
+ }
+
+
+ void configure( Dictionary config )
+ {
+ if ( config == null )
+ {
+
+ logLevel = getLogLevel( bundleContext );
+ factoryEnabled = VALUE_TRUE.equals( bundleContext.getProperty( PROP_FACTORY_ENABLED ) );
+ rebindEnabled = VALUE_TRUE.equals( bundleContext.getProperty( PROP_REBIND_ENABLED ) );
+ }
+ else
+ {
+ logLevel = ( ( Integer ) config.get( PROP_LOGLEVEL ) ).intValue();
+ factoryEnabled = ( ( Boolean ) config.get( PROP_FACTORY_ENABLED ) ).booleanValue();
+ rebindEnabled = ( ( Boolean ) config.get( PROP_REBIND_ENABLED ) ).booleanValue();
+ }
+ }
+
+
+ public int getLogLevel()
+ {
+ return logLevel;
+ }
+
+
+ public boolean isFactoryEnabled()
+ {
+ return factoryEnabled;
+ }
+
+
+ public boolean isRebindEnabled()
+ {
+ return rebindEnabled;
+ }
+
+
+ private static int getLogLevel( BundleContext bundleContext )
+ {
+ String levelString = bundleContext.getProperty( PROP_LOGLEVEL );
+ if ( levelString != null )
+ {
+ try
+ {
+ return Integer.parseInt( levelString );
+ }
+ catch ( NumberFormatException nfe )
+ {
+ // might be a descriptive name
+ }
+
+ if ( LOG_LEVEL_DEBUG.equalsIgnoreCase( levelString ) )
+ {
+ return LogService.LOG_DEBUG;
+ }
+ else if ( LOG_LEVEL_INFO.equalsIgnoreCase( levelString ) )
+ {
+ return LogService.LOG_INFO;
+ }
+ else if ( LOG_LEVEL_WARN.equalsIgnoreCase( levelString ) )
+ {
+ return LogService.LOG_WARNING;
+ }
+ else if ( LOG_LEVEL_ERROR.equalsIgnoreCase( levelString ) )
+ {
+ return LogService.LOG_ERROR;
+ }
+ }
+
+ // check ds.showtrace property
+ if ( VALUE_TRUE.equalsIgnoreCase( bundleContext.getProperty( PROP_SHOWTRACE ) ) )
+ {
+ return LogService.LOG_DEBUG;
+ }
+
+ // next check ds.showerrors property
+ if ( "false".equalsIgnoreCase( bundleContext.getProperty( PROP_SHOWERRORS ) ) )
+ {
+ return -1; // no logging at all !!
+ }
+
+ // default log level (errors only)
+ return LogService.LOG_ERROR;
+ }
+}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
index 649a4f2..db888b6 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
@@ -92,7 +92,7 @@
{
super( activator, metadata );
m_componentInstances = new IdentityHashMap();
- m_isConfigurationFactory = "true".equals( activator.getBundleContext().getProperty( "ds.factory.enabled" ) );
+ m_isConfigurationFactory = activator.getConfiguration().isFactoryEnabled();
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
index 542c1ac..04bd06b 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
@@ -932,9 +932,7 @@
*/
private void update( final ServiceReference ref )
{
- // if ( m_componentManager.getActivator().getConfiguration().isRebindEnabled() )
- if ( "true".equalsIgnoreCase( m_componentManager.getBundle().getBundleContext().getProperty(
- "ds.rebind.enabled" ) ) )
+ if ( m_componentManager.getActivator().getConfiguration().isRebindEnabled() )
{
// The updated method is only invoked if the implementation object is not
// null. This is valid for both immediate and delayed components
diff --git a/scr/src/main/resources/OSGI-INF/metatype/metatype.properties b/scr/src/main/resources/OSGI-INF/metatype/metatype.properties
new file mode 100644
index 0000000..7d1c849
--- /dev/null
+++ b/scr/src/main/resources/OSGI-INF/metatype/metatype.properties
@@ -0,0 +1,49 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+
+#
+# This file contains localization strings for configuration labels and
+# descriptions as used in the metatype.xml descriptor generated by the
+# the Sling SCR plugin
+
+org.apache.felix.scr.ScrService.name = Apache Felix Declarative Service Implementation
+org.apache.felix.scr.ScrService.description = Configuration for the Apache \
+ Felix Declarative Services Implementation. This configuration overwrites \
+ configuration defined in framework properties of the same names.
+
+ds.loglevel.name = SCR Log Level
+ds.loglevel.description = Allows limiting the amount of logging information \
+ sent to the OSGi LogService. Supported values are DEBUG, INFO, WARN, and \
+ ERROR. Default is ERROR.
+
+ds.factory.enabled.name = Extended Factory Components
+ds.factory.enabled.description = Whether or not to enable the support for \
+ creating Factory Component instances based on factory configuration. This \
+ is an Apache Felix SCR specific extension, explicitly not supported by the \
+ Declarative Services specification. Reliance on this feature prevent the \
+ component from being used with other Declarative Services implementations. \
+ The default value is false to disable this feature.
+
+ds.rebind.enabled.name = Rebind Support
+ds.rebind.enabled.description = Whether or not to enable support for rebinding \
+ of bound services whose registration properties have been modified. This is \
+ an Apache Felix SCR specific extension filling the gap of the specification \
+ which does not desribe whether and how such property updates should be \
+ propagated. The default value is false to disable this feature.