FELIX-1997 : Actual configuration might not be reflected in the web console

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@901223 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/pom.xml b/scr/pom.xml
index 8cfc253..3226d1c 100644
--- a/scr/pom.xml
+++ b/scr/pom.xml
@@ -140,20 +140,6 @@
     <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>
@@ -206,6 +192,12 @@
                             org.osgi.service.cm;version="[1.2,2)";resolution:=optional,
                             
                             <!--
+                                Metatype is optional and if it is
+                                present, version 1.1 (from R4.1) is enough  
+                            -->
+                            org.osgi.service.metatype;version="[1.1,2)";resolution:=optional,
+
+                            <!--
                                 SCR API is required (we also export it) and must
                                 be of any 1.1 version, because we implement that
                                 exact version. This import is only used if the
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/config/MetaTypeProviderImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/config/MetaTypeProviderImpl.java
new file mode 100644
index 0000000..9d0c09f
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/config/MetaTypeProviderImpl.java
@@ -0,0 +1,221 @@
+/*
+ * 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.io.InputStream;
+import java.util.ArrayList;
+import java.util.Dictionary;
+
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.metatype.*;
+
+public class MetaTypeProviderImpl
+    implements MetaTypeProvider, ManagedService
+{
+
+    private final int logLevel;
+
+    private final boolean factoryEnabled;
+
+    private final ManagedService delegatee;
+
+    public MetaTypeProviderImpl(final int logLevel,
+                                final boolean factoryEnabled,
+                                final ManagedService delegatee)
+    {
+        this.logLevel = logLevel;
+        this.factoryEnabled = factoryEnabled;
+        this.delegatee = delegatee;
+    }
+
+    private ObjectClassDefinition ocd;
+
+    public void updated(Dictionary properties) throws ConfigurationException
+    {
+        this.delegatee.updated(properties);
+    }
+
+    /**
+     * @see org.osgi.service.metatype.MetaTypeProvider#getLocales()
+     */
+    public String[] getLocales()
+    {
+        return null;
+    }
+
+    /**
+     * @see org.osgi.service.metatype.MetaTypeProvider#getObjectClassDefinition(java.lang.String, java.lang.String)
+     */
+    public ObjectClassDefinition getObjectClassDefinition( String id, String locale )
+    {
+        if ( !ScrConfiguration.PID.equals( id ) )
+        {
+            return null;
+        }
+
+        if ( ocd == null )
+        {
+            final ArrayList adList = new ArrayList();
+
+            adList.add( new AttributeDefinitionImpl( ScrConfiguration.PROP_LOGLEVEL, "SCR Log Level",
+                    "Allows limiting the amount of logging information sent to the OSGi LogService." +
+                    " Supported values are DEBUG, INFO, WARN, and ERROR. Default is ERROR.",
+                    AttributeDefinition.INTEGER,
+                    new String[] {String.valueOf(this.logLevel)}, 0,
+                    new String[] {"Debug", "Information", "Warnings", "Error"},
+                    new String[] {"4", "3", "2", "1"} ) );
+
+            adList.add( new AttributeDefinitionImpl( ScrConfiguration.PROP_FACTORY_ENABLED, "Extended Factory Components",
+                "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.",
+                this.factoryEnabled ) );
+
+            ocd = new ObjectClassDefinition()
+            {
+
+                private final AttributeDefinition[] attrs = ( AttributeDefinition[] ) adList
+                    .toArray( new AttributeDefinition[adList.size()] );
+
+
+                public String getName()
+                {
+                    return "Apache Felix Declarative Service Implementation";
+                }
+
+
+                public InputStream getIcon( int arg0 )
+                {
+                    return null;
+                }
+
+
+                public String getID()
+                {
+                    return ScrConfiguration.PID;
+                }
+
+
+                public String getDescription()
+                {
+                    return "Configuration for the Apache Felix Declarative Services Implementation." +
+                           " This configuration overwrites configuration defined in framework properties of the same names.";
+                }
+
+
+                public AttributeDefinition[] getAttributeDefinitions( int filter )
+                {
+                    return ( filter == OPTIONAL ) ? null : attrs;
+                }
+            };
+        }
+
+        return ocd;
+    }
+
+    class AttributeDefinitionImpl implements AttributeDefinition
+    {
+
+        private final String id;
+        private final String name;
+        private final String description;
+        private final int type;
+        private final String[] defaultValues;
+        private final int cardinality;
+        private final String[] optionLabels;
+        private final String[] optionValues;
+
+
+        AttributeDefinitionImpl( final String id, final String name, final String description, final boolean defaultValue )
+        {
+            this( id, name, description, BOOLEAN, new String[]
+                { String.valueOf(defaultValue) }, 0, null, null );
+        }
+
+        AttributeDefinitionImpl( final String id, final String name, final String description, final int type,
+            final String[] defaultValues, final int cardinality, final String[] optionLabels,
+            final String[] optionValues )
+        {
+            this.id = id;
+            this.name = name;
+            this.description = description;
+            this.type = type;
+            this.defaultValues = defaultValues;
+            this.cardinality = cardinality;
+            this.optionLabels = optionLabels;
+            this.optionValues = optionValues;
+        }
+
+
+        public int getCardinality()
+        {
+            return cardinality;
+        }
+
+
+        public String[] getDefaultValue()
+        {
+            return defaultValues;
+        }
+
+
+        public String getDescription()
+        {
+            return description;
+        }
+
+
+        public String getID()
+        {
+            return id;
+        }
+
+
+        public String getName()
+        {
+            return name;
+        }
+
+
+        public String[] getOptionLabels()
+        {
+            return optionLabels;
+        }
+
+
+        public String[] getOptionValues()
+        {
+            return optionValues;
+        }
+
+
+        public int getType()
+        {
+            return type;
+        }
+
+
+        public String validate( String arg0 )
+        {
+            return null;
+        }
+    }
+}
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
index 6ba1e58..c640525 100644
--- 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
@@ -27,6 +27,7 @@
 import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.cm.ManagedService;
 import org.osgi.service.log.LogService;
+import org.osgi.service.metatype.MetaTypeProvider;
 
 
 /**
@@ -35,17 +36,15 @@
  * 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";
+    static final String PROP_FACTORY_ENABLED = "ds.factory.enabled";
 
-    private static final String PROP_LOGLEVEL = "ds.loglevel";
+    static final String PROP_LOGLEVEL = "ds.loglevel";
 
     private static final String LOG_LEVEL_DEBUG = "debug";
 
@@ -61,18 +60,11 @@
 
     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;
 
+    static final String PID = "org.apache.felix.scr.ScrService";
 
     public ScrConfiguration( BundleContext bundleContext )
     {
@@ -91,9 +83,21 @@
                     configure( properties );
                 }
             };
+            // add meta type provider if interfaces are available
+            Object enhancedService = tryToCreateMetaTypeProvider(service);
+            final String[] interfaceNames;
+            if ( enhancedService == null )
+            {
+                interfaceNames = new String[] {ManagedService.class.getName()};
+            }
+            else
+            {
+                interfaceNames = new String[] {ManagedService.class.getName(), MetaTypeProvider.class.getName()};
+                service = enhancedService;
+            }
             Dictionary props = new Hashtable();
-            props.put( Constants.SERVICE_PID, "org.apache.felix.scr.ScrService" );
-            bundleContext.registerService( ManagedService.class.getName(), service, props );
+            props.put( Constants.SERVICE_PID, PID );
+            bundleContext.registerService( interfaceNames, service, props );
         }
         catch ( Throwable t )
         {
@@ -101,14 +105,13 @@
         }
     }
 
-
     void configure( Dictionary config )
     {
         if ( config == null )
         {
 
             logLevel = getLogLevel( bundleContext );
-            factoryEnabled = VALUE_TRUE.equals( bundleContext.getProperty( PROP_FACTORY_ENABLED ) );
+            factoryEnabled = getDefaultFactoryEnabled();
         }
         else
         {
@@ -117,6 +120,10 @@
         }
     }
 
+    private boolean getDefaultFactoryEnabled() {
+        return VALUE_TRUE.equals( bundleContext.getProperty( PROP_FACTORY_ENABLED ) );
+    }
+
 
     public int getLogLevel()
     {
@@ -177,4 +184,17 @@
         // default log level (errors only)
         return LogService.LOG_ERROR;
     }
+
+    private Object tryToCreateMetaTypeProvider(final Object managedService)
+    {
+        try
+        {
+            return new MetaTypeProviderImpl(getLogLevel( bundleContext ),
+                    getDefaultFactoryEnabled(), (ManagedService)managedService);
+        } catch (Throwable t)
+        {
+            // we simply ignore this
+        }
+        return null;
+    }
 }
diff --git a/scr/src/main/resources/OSGI-INF/metatype/metatype.properties b/scr/src/main/resources/OSGI-INF/metatype/metatype.properties
deleted file mode 100644
index f8507eb..0000000
--- a/scr/src/main/resources/OSGI-INF/metatype/metatype.properties
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-#  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.