You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pd...@apache.org on 2010/03/06 23:23:58 UTC

svn commit: r919860 - in /felix/trunk/dependencymanager/core: ./ src/main/java/org/apache/felix/dm/ src/main/java/org/apache/felix/dm/dependencies/ src/main/java/org/apache/felix/dm/impl/dependencies/ src/main/java/org/apache/felix/dm/impl/metatype/

Author: pderop
Date: Sat Mar  6 22:23:57 2010
New Revision: 919860

URL: http://svn.apache.org/viewvc?rev=919860&view=rev
Log:
added MetaType support in DependencyManager API

Added:
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/dependencies/PropertyMetaData.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/AttributeDefinitionImpl.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/MetaTypeProviderImpl.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/ObjectClassDefinitionImpl.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/PropertyMetaDataImpl.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/Resource.java
Modified:
    felix/trunk/dependencymanager/core/pom.xml
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/dependencies/ConfigurationDependency.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ConfigurationDependencyImpl.java

Modified: felix/trunk/dependencymanager/core/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/pom.xml?rev=919860&r1=919859&r2=919860&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/pom.xml (original)
+++ felix/trunk/dependencymanager/core/pom.xml Sat Mar  6 22:23:57 2010
@@ -54,7 +54,7 @@
             <Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
             <Export-Package>org.apache.felix.dm;version="3.0.0",org.apache.felix.dm.service;version="3.0.0",org.apache.felix.dm.management;version="3.0.0",org.apache.felix.dm.dependencies;version="3.0.0",org.apache.felix.dm.resources;version="3.0.0"</Export-Package>
             <Import-Package>!org.apache.felix.dm,!org.apache.felix.dm.service,!org.apache.felix.dm.management,!org.apache.felix.dm.dependencies,!org.apache.felix.dm.resources,*</Import-Package>
-	        <Private-Package>org.apache.felix.dm.impl,org.apache.felix.dm.impl.dependencies,org.apache.felix.dm.impl.tracker</Private-Package>
+	        <Private-Package>org.apache.felix.dm.impl,org.apache.felix.dm.impl.dependencies,org.apache.felix.dm.impl.tracker,org.apache.felix.dm.impl.metatype</Private-Package>
 	        <!-- Uncomment this line to include source code in the bundle.-->
             <Include-Resource>src/main/java</Include-Resource>
             <!-- -->

Modified: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java?rev=919860&r1=919859&r2=919860&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java (original)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java Sat Mar  6 22:23:57 2010
@@ -23,6 +23,7 @@
 
 import org.apache.felix.dm.dependencies.BundleDependency;
 import org.apache.felix.dm.dependencies.ConfigurationDependency;
+import org.apache.felix.dm.dependencies.PropertyMetaData;
 import org.apache.felix.dm.dependencies.ResourceDependency;
 import org.apache.felix.dm.dependencies.ServiceDependency;
 import org.apache.felix.dm.dependencies.TemporalServiceDependency;
@@ -134,6 +135,14 @@
     public ConfigurationDependency createConfigurationDependency() {
     	return m_manager.createConfigurationDependency();
     }
+    
+    /**
+     * Creates a new configuration property MetaData.
+     * @return a new configuration property MetaData
+     */
+    public PropertyMetaData createPropertyMetaData() {
+        return m_manager.createPropertyMetaData();
+    }
 
     /**
      * Creates a new bundle dependency.

Modified: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java?rev=919860&r1=919859&r2=919860&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java (original)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java Sat Mar  6 22:23:57 2010
@@ -25,6 +25,7 @@
 
 import org.apache.felix.dm.dependencies.BundleDependency;
 import org.apache.felix.dm.dependencies.ConfigurationDependency;
+import org.apache.felix.dm.dependencies.PropertyMetaData;
 import org.apache.felix.dm.dependencies.ResourceDependency;
 import org.apache.felix.dm.dependencies.ServiceDependency;
 import org.apache.felix.dm.dependencies.TemporalServiceDependency;
@@ -39,6 +40,7 @@
 import org.apache.felix.dm.impl.dependencies.ResourceDependencyImpl;
 import org.apache.felix.dm.impl.dependencies.ServiceDependencyImpl;
 import org.apache.felix.dm.impl.dependencies.TemporalServiceDependencyImpl;
+import org.apache.felix.dm.impl.metatype.PropertyMetaDataImpl;
 import org.apache.felix.dm.resources.Resource;
 import org.apache.felix.dm.service.Service;
 import org.osgi.framework.BundleContext;
@@ -136,6 +138,14 @@
     }
     
     /**
+     * Creates a new configuration property MetaData.
+     * @return a new Configuration property MetaData.
+     */
+    public PropertyMetaData createPropertyMetaData() {
+        return new PropertyMetaDataImpl();
+    }
+
+    /**
      * Creates a new bundle dependency.
      * 
      * @return

Modified: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/dependencies/ConfigurationDependency.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/dependencies/ConfigurationDependency.java?rev=919860&r1=919859&r2=919860&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/dependencies/ConfigurationDependency.java (original)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/dependencies/ConfigurationDependency.java Sat Mar  6 22:23:57 2010
@@ -11,23 +11,7 @@
  */
 package org.apache.felix.dm.dependencies;
 
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Properties;
-import java.util.Set;
-
-import org.apache.felix.dm.dependencies.Dependency;
-import org.apache.felix.dm.impl.Logger;
 import org.apache.felix.dm.management.ServiceComponentDependency;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedService;
 
 /**
  * Configuration dependency that can track the availability of a (valid) configuration. To use
@@ -61,4 +45,29 @@
    * service properties specified directly are merged with these.
    */
   ConfigurationDependency setPropagate(boolean propagate);
+  
+  /**
+   * The label used to display the tab name (or section) where the properties are displayed. Example: "Printer Service".
+   * @return The label used to display the tab name where the properties are displayed (may be localized)
+   */
+  ConfigurationDependency setHeading(String heading);
+
+  /**
+   * A human readable description of the PID this annotation is associated with. Example: "Configuration for the PrinterService bundle".
+   * @return A human readable description of the PID this annotation is associated with (may be localized)
+   */
+  ConfigurationDependency setDescription(String description);
+
+  /**
+   * Points to the basename of the Properties file that can localize the Meta Type informations.
+   * By default, (e.g. <code>setLocalization("person")</code> would match person_du_NL.properties in the root bundle directory.
+   * The default localization base name for the properties is OSGI-INF/l10n/bundle, but can
+   * be overridden by the manifest Bundle-Localization header (see core specification, in section Localization on page 68).
+   */
+  ConfigurationDependency setLocalization(String path);
+
+  /**
+   * Add Configuration MetaData
+   */
+  ConfigurationDependency add(PropertyMetaData properties);
 }

Added: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/dependencies/PropertyMetaData.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/dependencies/PropertyMetaData.java?rev=919860&view=auto
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/dependencies/PropertyMetaData.java (added)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/dependencies/PropertyMetaData.java Sat Mar  6 22:23:57 2010
@@ -0,0 +1,72 @@
+package org.apache.felix.dm.dependencies;
+
+public interface PropertyMetaData
+{
+    /**
+     * The label used to display the property. Example: "Log Level".
+     * @return The label used to display the property (may be localized)
+     */
+    PropertyMetaData setHeading(String heading);
+
+    /**
+     * The key of a ConfigurationAdmin property. Example: "printer.logLevel"
+     * @return The Configuration Admin property name
+     */
+    PropertyMetaData setId(String id);
+
+    /**
+     * Return the property primitive type. If must be either one of the following types:<p>
+     * <ul>
+     *    <li>String.class</li>
+     *    <li>Long.class</li>
+     *    <li>Integer.class</li>
+     *    <li>Character.class</li>
+     *    <li>Byte.class</li>
+     *    <li>Double.class</li>
+     *    <li>Float.class</li>
+     *    <li>Boolean.class</li>
+     * </ul>
+     */
+    PropertyMetaData setType(Class type);
+
+    /**
+     * Return a default for this property. The object must be of the appropriate type as defined by the cardinality and getType(). 
+     * The return type is a list of String  objects that can be converted to the appropriate type. The cardinality of the return 
+     * array must follow the absolute cardinality of this type. E.g. if the cardinality = 0, the array must contain 1 element. 
+     * If the cardinality is 1, it must contain 0 or 1 elements. If it is -5, it must contain from 0 to max 5 elements. Note that 
+     * the special case of a 0 cardinality, meaning a single value, does not allow arrays or vectors of 0 elements. 
+     */
+    PropertyMetaData setDefaults(String[] defaults);
+
+    /**
+     * Returns the property description. The description may be localized and must describe the semantics of this type and any 
+     * constraints. Example: "Select the log level for the Printer Service".
+     * @return The localized description of the definition.
+     */
+    PropertyMetaData setDescription(String description);
+
+    /**
+     * Return the cardinality of this property. The OSGi environment handles multi valued properties in arrays ([]) or in Vector objects. 
+     * The return value is defined as follows:<p>
+     *
+     * <ul>
+     * <li> x = Integer.MIN_VALUE    no limit, but use Vector</li>
+     * <li> x < 0                    -x = max occurrences, store in Vector</li>
+     * <li> x > 0                     x = max occurrences, store in array []</li>
+     * <li> x = Integer.MAX_VALUE    no limit, but use array []</li>
+     * <li> x = 0                     1 occurrence required</li>
+     * </ul>
+     */
+    PropertyMetaData setCardinality(int cardinality);
+
+    /**
+     * Tells if this property is required or not.
+     */
+    PropertyMetaData setRequired(boolean required);
+
+    /**
+     * Return a list of valid options for this property (the labels may be localized).
+     * @return the list of valid options for this property.
+     */
+    PropertyMetaData addOption(String optionLabel, String optionValue);
+}
\ No newline at end of file

Modified: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ConfigurationDependencyImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ConfigurationDependencyImpl.java?rev=919860&r1=919859&r2=919860&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ConfigurationDependencyImpl.java (original)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ConfigurationDependencyImpl.java Sat Mar  6 22:23:57 2010
@@ -28,7 +28,9 @@
 import java.util.Set;
 
 import org.apache.felix.dm.dependencies.ConfigurationDependency;
+import org.apache.felix.dm.dependencies.PropertyMetaData;
 import org.apache.felix.dm.impl.Logger;
+import org.apache.felix.dm.impl.metatype.MetaTypeProviderImpl;
 import org.apache.felix.dm.management.ServiceComponentDependency;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -67,6 +69,7 @@
     private String m_callback;
     private boolean m_isStarted;
 	private final Set m_updateInvokedCache = new HashSet();
+    private MetaTypeProviderImpl m_metaType;
 	
 	public ConfigurationDependencyImpl(BundleContext context, Logger logger) {
 		m_context = context;
@@ -115,7 +118,11 @@
 	    if (needsStarting) {
 	        Properties props = new Properties();
 	        props.put(Constants.SERVICE_PID, m_pid);
-	        m_registration = m_context.registerService(ManagedService.class.getName(), this, props);
+	        ManagedService ms = this;
+	        if (m_metaType != null) {
+	            ms = m_metaType;
+	        }
+	        m_registration = m_context.registerService(ManagedService.class.getName(), ms, props);
 	    }
 	}
 
@@ -307,4 +314,46 @@
     public Dictionary getProperties() {
         return getConfiguration();
     }
+    
+    public BundleContext getBundleContext() {
+        return m_context;
+    }
+    
+    public Logger getLogger() {
+        return m_logger;
+    }
+    
+    public ConfigurationDependency add(PropertyMetaData properties)
+    {
+        createMetaTypeImpl();
+        m_metaType.add(properties);
+       return this;
+    }
+
+    public ConfigurationDependency setDescription(String description)
+    {
+        createMetaTypeImpl();
+        m_metaType.setDescription(description);
+       return this;
+    }
+
+    public ConfigurationDependency setHeading(String heading)
+    {
+        createMetaTypeImpl();
+        m_metaType.setName(heading);
+       return this;
+    }
+    
+    public ConfigurationDependency setLocalization(String path)
+    {
+        createMetaTypeImpl();
+        m_metaType.setLocalization(path);
+        return this;
+    }
+    
+    private synchronized void createMetaTypeImpl() {
+        if (m_metaType == null) {
+            m_metaType = new MetaTypeProviderImpl(this);
+        }
+    }
 }

Added: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/AttributeDefinitionImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/AttributeDefinitionImpl.java?rev=919860&view=auto
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/AttributeDefinitionImpl.java (added)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/AttributeDefinitionImpl.java Sat Mar  6 22:23:57 2010
@@ -0,0 +1,86 @@
+/*
+ * 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.dm.impl.metatype;
+
+import org.osgi.service.metatype.AttributeDefinition;
+
+public class AttributeDefinitionImpl implements AttributeDefinition
+{
+    private PropertyMetaDataImpl m_propertyMetaData;
+    private Resource m_resource;
+
+    public AttributeDefinitionImpl(PropertyMetaDataImpl propertyMetaData, Resource resource)
+    {
+        m_propertyMetaData = propertyMetaData;
+        m_resource = resource;
+    }
+
+    public int getCardinality()
+    {
+        return m_propertyMetaData.getCardinality();
+    }
+
+    public String[] getDefaultValue()
+    {
+        return m_propertyMetaData.getDefaults();
+    }
+
+    public String getDescription()
+    {
+        return m_resource.localize(m_propertyMetaData.getDescription());
+    }
+
+    public String getID()
+    {
+        return m_propertyMetaData.getId();
+    }
+
+    public String getName()
+    {
+        return m_resource.localize(m_propertyMetaData.getHeading());
+    }
+
+    public String[] getOptionLabels()
+    {
+        String[] labels = m_propertyMetaData.getOptionLabels();
+        if (labels != null)
+        {
+            for (int i = 0; i < labels.length; i++)
+            {
+                labels[i] = m_resource.localize(labels[i]);
+            }
+        }
+        return labels;
+    }
+
+    public String[] getOptionValues()
+    {
+        return m_propertyMetaData.getOptionValues();
+    }
+
+    public int getType()
+    {
+        return m_propertyMetaData.getType();
+    }
+
+    public String validate(String value)
+    {
+        return null;
+    }
+}

Added: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/MetaTypeProviderImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/MetaTypeProviderImpl.java?rev=919860&view=auto
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/MetaTypeProviderImpl.java (added)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/MetaTypeProviderImpl.java Sat Mar  6 22:23:57 2010
@@ -0,0 +1,265 @@
+/*
+ * 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.dm.impl.metatype;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.TreeSet;
+
+import org.apache.felix.dm.dependencies.PropertyMetaData;
+import org.apache.felix.dm.impl.Logger;
+import org.apache.felix.dm.impl.dependencies.ConfigurationDependencyImpl;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.log.LogService;
+import org.osgi.service.metatype.MetaTypeProvider;
+import org.osgi.service.metatype.ObjectClassDefinition;
+
+/**
+ * When a ConfigurationDepdendency is configured with properties metadata, we provide
+ * a specific ManagedService which also implements the MetaTypeProvider interface. This interface
+ * allows the MetaTypeService to retrieve our properties metadata, which will then be handled by webconsole.
+ */
+public class MetaTypeProviderImpl implements MetaTypeProvider, ManagedService
+{
+    private ConfigurationDependencyImpl m_configDependency;
+    private List m_propertiesMetaData = new ArrayList();
+    private String m_description;
+    private String m_heading;
+    private String m_localization;
+    private Map m_localesProperties = new HashMap();
+    private Logger m_logger;
+
+    public MetaTypeProviderImpl(ConfigurationDependencyImpl configurationDependency)
+    {
+        m_configDependency = configurationDependency;
+        m_logger = configurationDependency.getLogger();
+        // Set the default localization file base name (see core specification, in section Localization on page 68).
+        // By default, this file can be stored in OSGI-INF/l10n/bundle.properties (and corresponding localized version
+        // in OSGI-INF/l10n/bundle_en_GB_welsh.properties,  OSGI-INF/l10n/bundle_en_GB.properties, etc ...
+        // This default localization property file name can be overriden using the PropertyMetaData.setLocalization method.
+        m_localization = (String) m_configDependency.getBundleContext().getBundle().getHeaders().get(
+            Constants.BUNDLE_LOCALIZATION);
+        if (m_localization == null)
+        {
+            m_localization = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
+        }
+    }
+
+    /**
+     * Registers the metatype information of a given configuration property
+     * @param property
+     */
+    public void add(PropertyMetaData property)
+    {
+        m_propertiesMetaData.add(property);
+    }
+
+    /**
+     * A human readable description of the PID this annotation is associated with. Example: "Configuration for the PrinterService bundle".
+     * @return A human readable description of the PID this annotation is associated with (may be localized)
+     */
+    public void setDescription(String description)
+    {
+        m_description = description;
+    }
+
+    /**
+     * The label used to display the tab name (or section) where the properties are displayed. Example: "Printer Service".
+     * @return The label used to display the tab name where the properties are displayed (may be localized)
+     */
+    public void setName(String heading)
+    {
+        m_heading = heading;
+    }
+
+    /**
+     * Points to the basename of the Properties file that can localize the Meta Type informations.
+     * By default, (e.g. <code>setLocalization("person")</code> would match person_du_NL.properties in the root bundle directory.
+     * The default localization base name for the properties is OSGI-INF/l10n/bundle, but can
+     * be overridden by the manifest Bundle-Localization header (see core specification, in section Localization on page 68).
+     */
+    public void setLocalization(String path)
+    {
+        if (path.endsWith(".properties"))
+        {
+            throw new IllegalArgumentException(
+                "path must point to the base name of the propertie file, "
+                    + "excluding local suffixes. For example: "
+                    + "foo/bar/person is valid and matches the property file \"foo/bar/person_bundle_en_GB_welsh.properties\"");
+        }
+        m_localization = path.startsWith("/") ? path.substring(1) : path;
+    }
+
+    // --------------- MetaTypeProvider interface -------------------------------------------------
+
+    /**
+     * Returns all the Locales our bundle is containing. For instance, if our bundle contains the following localization files:
+     * OSGI-INF/l10n/bundle_en_GB_welsh.properties and OSGI-INF/l10n/bundle_en_GB.properties, then this method will return
+     * "en_GB", "en_GB_welsh" ...
+     * @return the list of Locale supported by our bundle.
+     */
+    public String[] getLocales()
+    {
+        int lastSlash = m_localization.lastIndexOf("/");
+        String path = (lastSlash == -1) ? "/" : ("/" + m_localization.substring(0, lastSlash - 1));
+        String base = (lastSlash == -1) ? m_localization : m_localization.substring(lastSlash + 1);
+        Enumeration e = m_configDependency.getBundleContext().getBundle().findEntries(path,
+            base + "*.properties", false);
+        TreeSet set = new TreeSet();
+        while (e.hasMoreElements())
+        {
+            // We have found a locale property file in the form of "path/file[_language[_ country[_variation]].properties"
+            // And now, we have to get the "language[_country[_variation]]" part ...
+            URL url = (URL) e.nextElement();
+            String name = url.getPath();
+            name = name.substring(name.lastIndexOf("/") + 1);
+            int underscore = name.indexOf("_");
+            if (underscore != -1)
+            {
+                name = name.substring(underscore + 1, name.length() - ".properties".length());
+            }
+            if (name.length() > 0)
+            {
+                set.add(name);
+            }
+        }
+
+        String[] locales = (String[]) set.toArray(new String[set.size()]);
+        return locales.length == 0 ? null : locales;
+    }
+
+    /**
+     * Returns the ObjectClassDefinition for a given Pid/Locale.
+     */
+    public ObjectClassDefinition getObjectClassDefinition(String id, String locale)
+    {
+        try
+        {
+            // Check if the id matches our PID
+            if (!id.equals(m_configDependency.getName()))
+            {
+                m_configDependency.getLogger().log(LogService.LOG_ERROR,
+                    "id " + id + " does not match pid " + m_configDependency.getName());
+                return null;
+            }
+
+            Properties localeProperties = getLocaleProperties(locale);
+            return new ObjectClassDefinitionImpl(m_configDependency.getName(), m_heading,
+                m_description, m_propertiesMetaData, new Resource(localeProperties));
+        }
+
+        catch (Throwable t)
+        {
+            m_configDependency.getLogger().log(
+                Logger.LOG_ERROR,
+                "Unexpected exception while geting ObjectClassDefinition for " + id + " (locale="
+                    + locale + ")", t);
+            return null;
+        }
+    }
+
+    /**
+     * We also implements the ManagedService and we just delegates the configuration handling to
+     * our associated ConfigurationDependency.
+     */
+    public void updated(Dictionary properties) throws ConfigurationException
+    {
+        m_configDependency.updated(properties);
+    }
+
+    /**
+     * Gets the properties for a given Locale.
+     * @param locale
+     * @return
+     * @throws IOException
+     */
+    private synchronized Properties getLocaleProperties(String locale) throws IOException
+    {
+        locale = locale == null ? Locale.getDefault().toString() : locale;
+        Properties properties = (Properties) m_localesProperties.get(locale);
+        if (properties == null)
+        {
+            properties = new Properties();
+            URL url = m_configDependency.getBundleContext().getBundle().getEntry(
+                m_localization + ".properties");
+            if (url != null)
+            {
+                loadLocale(properties, url);
+            }
+
+            String path = m_localization;
+            StringTokenizer tok = new StringTokenizer(locale, "_");
+            while (tok.hasMoreTokens())
+            {
+                path += "_" + tok.nextToken();
+                url = m_configDependency.getBundleContext().getBundle().getEntry(path + ".properties");
+                if (url != null)
+                {
+                    properties = new Properties(properties);
+                    loadLocale(properties, url);
+                }
+            }
+
+            m_localesProperties.put(locale, properties);
+        }
+
+        return properties;
+    }
+
+    /**
+     * Loads a Locale Properties file.
+     * @param properties
+     * @param url
+     * @throws IOException
+     */
+    private void loadLocale(Properties properties, URL url) throws IOException
+    {
+        InputStream in = null;
+        try
+        {
+            in = url.openStream();
+            properties.load(in);
+        }
+        finally
+        {
+            if (in != null)
+            {
+                try
+                {
+                    in.close();
+                }
+                catch (IOException ignored)
+                {
+                }
+            }
+        }
+    }
+}

Added: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/ObjectClassDefinitionImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/ObjectClassDefinitionImpl.java?rev=919860&view=auto
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/ObjectClassDefinitionImpl.java (added)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/ObjectClassDefinitionImpl.java Sat Mar  6 22:23:57 2010
@@ -0,0 +1,110 @@
+/*
+ * 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.dm.impl.metatype;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.osgi.service.metatype.AttributeDefinition;
+import org.osgi.service.metatype.ObjectClassDefinition;
+
+/**
+ * ObjectClassDefinition implementation.
+ */
+public class ObjectClassDefinitionImpl implements ObjectClassDefinition
+{
+    // Our OCD name (may be localized)
+    private String m_name;
+    
+    // Our OCD description (may be localized)
+    private String m_description;
+    
+    // Our OCD id
+    private String m_id;
+    
+    // The list of Properties MetaData objects (from DependencyManager API)
+    private List m_propertiesMetaData;
+    
+    // The localized resource that can be used when localizing some parameters
+    private Resource m_resource;
+
+    public ObjectClassDefinitionImpl(String id, String name, String description, List propertiesMetaData, Resource resource)
+    {
+        m_id = id;
+        m_name = name;
+        m_description = description;
+        m_propertiesMetaData = propertiesMetaData;
+        m_resource = resource;
+    }
+
+    // --------------------- ObjectClassDefinition ----------------------------------------
+
+    public AttributeDefinition[] getAttributeDefinitions(int filter)
+    {
+        List attrs = new ArrayList();
+        for (int i = 0; i < m_propertiesMetaData.size(); i++)
+        {
+            PropertyMetaDataImpl metaData = (PropertyMetaDataImpl) m_propertiesMetaData.get(i);
+            switch (filter)
+            {
+                case ObjectClassDefinition.ALL:
+                    attrs.add(new AttributeDefinitionImpl(metaData, m_resource));
+                    break;
+                case ObjectClassDefinition.OPTIONAL:
+                    if (!metaData.isRequired())
+                    {
+                        attrs.add(new AttributeDefinitionImpl(metaData, m_resource));
+                    }
+                    break;
+                case ObjectClassDefinition.REQUIRED:
+                    if (metaData.isRequired())
+                    {
+                        attrs.add(new AttributeDefinitionImpl(metaData, m_resource));
+                    }
+                    break;
+            }
+        }
+
+        AttributeDefinition[] array = new AttributeDefinitionImpl[attrs.size()];
+        return (AttributeDefinition[]) attrs.toArray(array);
+    }
+
+    public String getDescription()
+    {
+        return m_resource.localize(m_description);
+    }
+
+    public String getID()
+    {
+        return m_id;
+    }
+
+    public InputStream getIcon(int size) throws IOException
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String getName()
+    {
+        return m_resource.localize(m_name);
+    }
+}

Added: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/PropertyMetaDataImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/PropertyMetaDataImpl.java?rev=919860&view=auto
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/PropertyMetaDataImpl.java (added)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/PropertyMetaDataImpl.java Sat Mar  6 22:23:57 2010
@@ -0,0 +1,224 @@
+/*
+ * 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.dm.impl.metatype;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.dm.dependencies.PropertyMetaData;
+import org.osgi.service.metatype.AttributeDefinition;
+
+/**
+ * DependencyManager PropertyMetaData Implementation. This class describes meta informations regarding
+ * one given configuration property.
+ */
+public class PropertyMetaDataImpl implements PropertyMetaData
+{
+    /**
+     * List of option labels (may be localized)
+     */
+    List m_optionsLabels = new ArrayList();
+    
+    /**
+     * List of option values
+     */
+    List m_optionsValues = new ArrayList();
+    
+    /**
+     * Property cardinality.
+     * @see {@link AttributeDefinition#getCardinality()}
+     */
+    private int m_cardinality;
+    
+    /**
+     * Valid default property values
+     */
+    private String[] m_defaults;
+    
+    /**
+     * Property description.
+     */
+    private String m_description;
+    
+    /**
+     * Property title.
+     */
+    private String m_heading;
+    
+    /**
+     * Property unique Id
+     */
+    private String m_id;
+    
+    /**
+     * Required flag.
+     */
+    private boolean m_required;
+    
+    /**
+     * Property Type.
+     * @see {@link AttributeDefinition#getType()}
+     */
+    private int m_type = AttributeDefinition.STRING;
+    
+    /**
+     * Mapping between java types and valid MetaType types.
+     * @see {@link AttributeDefinition#getType()}
+     */
+    private final static Map m_typeMapping = new HashMap()
+    {
+        {
+            put(Boolean.class, new Integer(AttributeDefinition.BOOLEAN));
+            put(Byte.class, new Integer(AttributeDefinition.BYTE));
+            put(Character.class, new Integer(AttributeDefinition.CHARACTER));
+            put(Double.class, new Integer(AttributeDefinition.FLOAT));
+            put(Integer.class, new Integer(AttributeDefinition.INTEGER));
+            put(Long.class, new Integer(AttributeDefinition.LONG));
+            put(Short.class, new Integer(AttributeDefinition.SHORT));
+            put(String.class, new Integer(AttributeDefinition.STRING));
+        }
+    };
+
+    public PropertyMetaData addOption(String optionLabel, String optionValue)
+    {
+        m_optionsLabels.add(optionLabel);
+        m_optionsValues.add(optionValue);
+        return this;
+    }
+
+    public PropertyMetaData setCardinality(int cardinality)
+    {
+        m_cardinality = cardinality;
+        return this;
+    }
+
+    public PropertyMetaData setDefaults(String[] defaults)
+    {
+        m_defaults = defaults;
+        return this;
+    }
+
+    public PropertyMetaData setDescription(String description)
+    {
+        m_description = description;
+        return this;
+    }
+
+    public PropertyMetaData setHeading(String heading)
+    {
+        m_heading = heading;
+        return this;
+    }
+
+    public PropertyMetaData setId(String id)
+    {
+        m_id = id;
+        return this;
+    }
+
+    public PropertyMetaData setRequired(boolean required)
+    {
+        m_required = required;
+        return this;
+    }
+
+    public PropertyMetaData setType(Class classType)
+    {
+        Integer type = (Integer) m_typeMapping.get(classType);
+        if (type == null)
+        {
+            throw new IllegalArgumentException("Invalid type: " + classType + ". Valid types are "
+                + m_typeMapping.keySet());
+        }
+        m_type = type.intValue();
+        return this;
+    }
+
+    public String[] getOptionLabels()
+    {
+        String[] optionLabels = new String[m_optionsLabels.size()];
+        return (String[]) m_optionsLabels.toArray(optionLabels);
+    }
+
+    public String[] getOptionValues()
+    {
+        String[] optionValues = new String[m_optionsValues.size()];
+        return (String[]) m_optionsValues.toArray(optionValues);
+    }
+
+    public int getCardinality()
+    {
+        return m_cardinality;
+    }
+
+    public String[] getDefaults()
+    {
+        return m_defaults;
+    }
+
+    public String getDescription()
+    {
+        return m_description;
+    }
+
+    public String getHeading()
+    {
+        return m_heading;
+    }
+
+    public String getId()
+    {
+        return m_id;
+    }
+
+    public boolean isRequired()
+    {
+        return m_required;
+    }
+
+    public int getType()
+    {
+        return m_type;
+    }
+    
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append("cardinality=").append(m_cardinality);
+        sb.append("; defaults="); 
+        for (int i = 0; i < m_defaults.length; i ++) {
+            sb.append(m_defaults[i]).append(" ");
+        }
+        sb.append("; description=").append(m_description);
+        sb.append("; heading=").append(m_heading);
+        sb.append("; id=").append(m_id);
+        sb.append("; required=").append(m_required);
+        sb.append("; type=").append(getType());
+        sb.append("; optionLabels=");
+        for (int i = 0; i < m_optionsLabels.size(); i ++) {
+            sb.append(m_optionsLabels.get(i)).append(" ");
+        }
+        sb.append("; optionValues=");
+        for (int i = 0; i < m_optionsValues.size(); i ++) {
+            sb.append(m_optionsValues.get(i)).append(" ");
+        }
+        return sb.toString();
+    }
+}

Added: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/Resource.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/Resource.java?rev=919860&view=auto
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/Resource.java (added)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/metatype/Resource.java Sat Mar  6 22:23:57 2010
@@ -0,0 +1,43 @@
+/*
+ * 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.dm.impl.metatype;
+
+import java.util.Properties;
+
+/**
+ * Helper class used to localize a given Property Meta Data.
+ */
+public class Resource
+{
+    private Properties m_properties;
+
+    public Resource(Properties properties) {
+        m_properties = properties;
+    }
+    
+    public String localize(String param)
+    {
+        if (m_properties != null && param != null && param.startsWith("%"))
+        {
+            param = param.substring(1);
+            return m_properties.getProperty(param);
+        }
+        return param;
+    }
+}