You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by fm...@apache.org on 2011/12/19 13:54:03 UTC

svn commit: r1220723 - in /felix/trunk/webconsole: ./ src/main/java/org/apache/felix/webconsole/internal/servlet/ src/main/resources/res/ui/

Author: fmeschbe
Date: Mon Dec 19 12:54:03 2011
New Revision: 1220723

URL: http://svn.apache.org/viewvc?rev=1220723&view=rev
Log:
FELIX-2117 Reduce the static dependencies
  - Import most Compendium services dynamically
    (still require Http, Startlevel, and PackageAdmin)
  - Embed Metatype service package and import optionally
    (allows to synthesize descriptors but still use imported
    package if available)
  - Make sure existing factory configurations are displayed even
    in the absence of a Metatype service

Added:
    felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/ConfigurationSupport.java
      - copied, changed from r1215540, felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/ConfigurationListener.java
Removed:
    felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/ConfigurationListener.java
    felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/ConfigurationListener2.java
Modified:
    felix/trunk/webconsole/pom.xml
    felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
    felix/trunk/webconsole/src/main/resources/res/ui/config.js

Modified: felix/trunk/webconsole/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole/pom.xml?rev=1220723&r1=1220722&r2=1220723&view=diff
==============================================================================
--- felix/trunk/webconsole/pom.xml (original)
+++ felix/trunk/webconsole/pom.xml Mon Dec 19 12:54:03 2011
@@ -130,22 +130,28 @@
                             org.apache.felix.webconsole.internal.OsgiManagerActivator
                         </Bundle-Activator>
                         <Import-Package>
-                            org.osgi.service.http,
-                            org.apache.felix.shell;
-                            org.osgi.service.*;resolution:=optional,
+                            org.osgi.service.metatype;resolution:=optional,
                             javax.servlet.*;version=2.4,
                             *
                         </Import-Package>
                         <DynamicImport-Package>
-                            org.apache.felix.bundlerepository,
-                            org.osgi.service.obr
+                            org.apache.felix.bundlerepository;version="[2.0,3)",
+                            org.osgi.service.obr;version="[1.0,2)",
+                            org.osgi.service.cm;version="[1.2,2)",
+                            org.osgi.service.condpermadmin;version="[1.0,2)",
+                            org.osgi.service.log;version="[1.3,2)",
+                            org.osgi.service.metatype;version="[1.1,2)",
+                            org.osgi.service.permissionadmin;version="[1.2,2)",
+                            org.osgi.service.prefs;version="[1.1,2)",
+                            org.osgi.service.wireadmin;version="[1.0,2)"
                         </DynamicImport-Package>
                         <Include-Resource>
                             {maven-resources},META-INF=src/main/bare-resources
                         </Include-Resource>
                         <Embed-Dependency>
                             org.apache.felix.utils;inline=org/apache/felix/utils/manifest/**,
-                            org.apache.felix.framework;inline=org/apache/felix/framework/util/VersionRange**
+                            org.apache.felix.framework;inline=org/apache/felix/framework/util/VersionRange**,
+                            org.osgi.compendium;inline=org/osgi/service/metatype/**
                         </Embed-Dependency>
                         <_removeheaders>
                             Embed-Dependency,Private-Package,Include-Resource
@@ -199,7 +205,6 @@
             <artifactId>commons-fileupload</artifactId>
             <version>1.2.1</version>
             <scope>provided</scope>
-            <optional>true</optional>
         </dependency>
 
         <dependency>
@@ -207,7 +212,6 @@
             <artifactId>commons-io</artifactId>
             <version>1.4</version>
             <scope>provided</scope>
-            <optional>true</optional>
         </dependency>
 
         <dependency>

Copied: felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/ConfigurationSupport.java (from r1215540, felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/ConfigurationListener.java)
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/ConfigurationSupport.java?p2=felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/ConfigurationSupport.java&p1=felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/ConfigurationListener.java&r1=1215540&r2=1220723&rev=1220723&view=diff
==============================================================================
--- felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/ConfigurationListener.java (original)
+++ felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/ConfigurationSupport.java Mon Dec 19 12:54:03 2011
@@ -19,52 +19,276 @@
 package org.apache.felix.webconsole.internal.servlet;
 
 
+import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.Dictionary;
-import java.util.Hashtable;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceRegistration;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.TreeMap;
+
+import org.apache.felix.webconsole.internal.Util;
 import org.osgi.service.cm.ManagedService;
+import org.osgi.service.metatype.AttributeDefinition;
+import org.osgi.service.metatype.MetaTypeProvider;
+import org.osgi.service.metatype.ObjectClassDefinition;
 
 
-class ConfigurationListener implements ManagedService
+class ConfigurationSupport implements ManagedService, MetaTypeProvider
 {
+    private static final String[] CONF_PROPS = new String[] {
+        OsgiManager.PROP_MANAGER_ROOT, OsgiManager.DEFAULT_MANAGER_ROOT, //
+        OsgiManager.PROP_HTTP_SERVICE_SELECTOR, OsgiManager.DEFAULT_HTTP_SERVICE_SELECTOR, //
+        OsgiManager.PROP_DEFAULT_RENDER, OsgiManager.DEFAULT_PAGE, //
+        OsgiManager.PROP_REALM, OsgiManager.DEFAULT_REALM, //
+        OsgiManager.PROP_USER_NAME, OsgiManager.DEFAULT_USER_NAME, //
+        OsgiManager.PROP_PASSWORD, OsgiManager.DEFAULT_PASSWORD, //
+        OsgiManager.PROP_LOCALE, "" , //$NON-NLS-1$
+    };
+
+    // used by an inner class, to prevent synthetic methods
+    final OsgiManager osgiManager;
+
+    private final Object ocdLock = new Object();
+    private String ocdLocale;
+    private ObjectClassDefinition ocd;
 
-    private final OsgiManager osgiManager;
-
-
-    static ServiceRegistration create( OsgiManager osgiManager )
+    ConfigurationSupport( OsgiManager osgiManager )
     {
-        ConfigurationListener cl = new ConfigurationListener( osgiManager );
-        return registerService( cl, new String[]
-            { ManagedService.class.getName() } );
+        this.osgiManager = osgiManager;
     }
 
 
-    static ServiceRegistration registerService( ConfigurationListener listener, final String[] serviceNames )
+    //---------- ManagedService
+
+    @SuppressWarnings("unchecked")
+    public void updated( @SuppressWarnings("rawtypes") Dictionary config )
     {
-        final OsgiManager osgiManager = listener.osgiManager;
+        osgiManager.updateConfiguration( config );
+    }
 
-        Dictionary<String, String> props = new Hashtable<String, String>();
-        props.put( Constants.SERVICE_VENDOR, "The Apache Software Foundation" );
-        props.put( Constants.SERVICE_DESCRIPTION, "OSGi Management Console Configuration Receiver" );
-        props.put( Constants.SERVICE_PID, osgiManager.getConfigurationPid() );
+    //---------- MetaTypeProvider
 
-        return osgiManager.getBundleContext().registerService( serviceNames, listener, props );
+    public String[] getLocales()
+    {
+        // there is no locale support here
+        return null;
     }
 
-
-    protected ConfigurationListener( OsgiManager osgiManager )
+    static final String getString(ResourceBundle rb, String key, String def)
     {
-        this.osgiManager = osgiManager;
+        try
+        {
+            return rb.getString(key);
+        }
+        catch (Throwable t)
+        {
+            return def;
+        }
     }
 
+    public ObjectClassDefinition getObjectClassDefinition( String id, String locale )
+    {
+        if ( !osgiManager.getConfigurationPid().equals( id ) )
+        {
+            return null;
+        }
+
+        if (locale == null) locale = Locale.ENGLISH.getLanguage();
+
+        // check if OCD is already initialized and it's locale is the same as the requested one
+        synchronized (ocdLock)
+        {
+            if ( ocd != null && ocdLocale != null && ocdLocale.equals(locale) )
+            {
+                return ocd;
+            }
+        }
+
+        ObjectClassDefinition xocd = null;
+        final Locale localeObj = Util.parseLocaleString(locale);
+        final ResourceBundle rb = osgiManager.resourceBundleManager.getResourceBundle(osgiManager.getBundleContext().getBundle(), localeObj);
+        final Map<String, ?> defaultConfig = osgiManager.getDefaultConfiguration();
+
+        // simple configuration properties
+        final ArrayList<AttributeDefinition> adList = new ArrayList<AttributeDefinition>();
+        for (int i = 0; i < CONF_PROPS.length; i++)
+        {
+            final String key = CONF_PROPS[i++];
+            final String defaultValue = ConfigurationUtil.getProperty( defaultConfig, key, CONF_PROPS[i] );
+            final String name = getString(rb, "metadata." + key + ".name", key); //$NON-NLS-1$ //$NON-NLS-2$
+            final String descr = getString(rb, "metadata." + key + ".description", key); //$NON-NLS-1$ //$NON-NLS-2$
+            adList.add( new AttributeDefinitionImpl(key, name, descr, defaultValue) );
+        }
+
+        // log level is select - so no simple default value; requires localized option labels
+        adList.add( new AttributeDefinitionImpl( OsgiManager.PROP_LOG_LEVEL,
+            getString(rb, "metadata.loglevel.name", OsgiManager.PROP_LOG_LEVEL), //$NON-NLS-1$
+            getString(rb, "metadata.loglevel.description", OsgiManager.PROP_LOG_LEVEL), //$NON-NLS-1$
+            AttributeDefinition.INTEGER, // type
+            new String[]
+                { String.valueOf( ConfigurationUtil.getProperty( defaultConfig, OsgiManager.PROP_LOG_LEVEL,
+                    OsgiManager.DEFAULT_LOG_LEVEL ) ) }, // default values
+            0, // cardinality
+            new String[] { // option labels
+                getString(rb, "log.level.debug", "Debug"), //$NON-NLS-1$ //$NON-NLS-2$
+                getString(rb, "log.level.info", "Information"), //$NON-NLS-1$ //$NON-NLS-2$
+                getString(rb, "log.level.warn", "Warn"), //$NON-NLS-1$ //$NON-NLS-2$
+                getString(rb, "log.level.error", "Error"), //$NON-NLS-1$ //$NON-NLS-2$
+            },
+            new String[] { "4", "3", "2", "1" } ) ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+        // list plugins - requires localized plugin titles
+        final TreeMap<String, String> namesByClassName = new TreeMap<String, String>();
+        final String[] defaultPluginsClasses = OsgiManager.PLUGIN_MAP;
+        for ( int i = 0; i < defaultPluginsClasses.length; i++ )
+        {
+            final String clazz = defaultPluginsClasses[i++];
+            final String label = defaultPluginsClasses[i];
+            final String name = getString(rb, label + ".pluginTitle", label); //$NON-NLS-1$
+            namesByClassName.put(clazz, name);
+        }
+        final String[] classes = namesByClassName.keySet().toArray(
+            new String[namesByClassName.size()] );
+        final String[] names = namesByClassName.values().toArray( new String[namesByClassName.size()] );
+
+        adList.add( new AttributeDefinitionImpl( OsgiManager.PROP_ENABLED_PLUGINS,
+            getString(rb, "metadata.plugins.name", OsgiManager.PROP_ENABLED_PLUGINS), //$NON-NLS-1$
+            getString(rb, "metadata.plugins.description", OsgiManager.PROP_ENABLED_PLUGINS), //$NON-NLS-1$
+            AttributeDefinition.STRING, classes, Integer.MIN_VALUE, names, classes ) );
+
+        xocd = new ObjectClassDefinition()
+        {
+
+            private final AttributeDefinition[] attrs = adList
+                .toArray( new AttributeDefinition[adList.size()] );
+
+
+            public String getName()
+            {
+                return getString(rb, "metadata.name", "Apache Felix OSGi Management Console"); //$NON-NLS-1$ //$NON-NLS-2$
+            }
+
+
+            public InputStream getIcon( int arg0 )
+            {
+                return null;
+            }
+
+
+            public String getID()
+            {
+                return osgiManager.getConfigurationPid();
+            }
+
+
+            public String getDescription()
+            {
+                return getString(rb, "metadata.description", "Configuration of the Apache Felix OSGi Management Console."); //$NON-NLS-1$ //$NON-NLS-2$
+            }
+
+
+            public AttributeDefinition[] getAttributeDefinitions( int filter )
+            {
+                return ( filter == OPTIONAL ) ? null : attrs;
+            }
+        };
+
+        synchronized(ocdLock) {
+            this.ocd = xocd;
+            this.ocdLocale = locale;
+        }
 
-    //---------- ManagedService
+        return ocd;
+    }
 
-    @SuppressWarnings("unchecked")
-    public void updated( @SuppressWarnings("rawtypes") Dictionary config )
+    private static class AttributeDefinitionImpl implements AttributeDefinition
     {
-        osgiManager.updateConfiguration( config );
+
+        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 String defaultValue )
+        {
+            this( id, name, description, STRING, new String[]
+                { 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;
+        }
     }
 
 }
\ No newline at end of file

Modified: felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java?rev=1220723&r1=1220722&r2=1220723&view=diff
==============================================================================
--- felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java (original)
+++ felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java Mon Dec 19 12:54:03 2011
@@ -35,6 +35,8 @@ import java.util.ResourceBundle;
 import java.util.Set;
 
 import javax.servlet.GenericServlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
@@ -59,6 +61,7 @@ import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceFactory;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.http.HttpContext;
@@ -218,6 +221,7 @@ public class OsgiManager extends Generic
 
     private int logLevel = DEFAULT_LOG_LEVEL;
 
+    @SuppressWarnings("serial")
     public OsgiManager(BundleContext bundleContext)
     {
         this.bundleContext = bundleContext;
@@ -314,23 +318,28 @@ public class OsgiManager extends Generic
         // configure and start listening for configuration
         updateConfiguration(null);
 
-        try
-        {
-            this.configurationListener = ConfigurationListener2.create(this);
-        }
-        catch (Throwable t2)
-        {
-            // might be caused by Metatype API not available
-            // try without MetaTypeProvider
-            try
+        // register managed service as a service factory
+        this.configurationListener = bundleContext.registerService( "org.osgi.service.cm.ManagedService", //$NON-NLS-1$
+            new ServiceFactory()
             {
-                this.configurationListener = ConfigurationListener.create(this);
-            }
-            catch (Throwable t)
+                public Object getService( Bundle bundle, ServiceRegistration registration )
+                {
+                    return new ConfigurationSupport( OsgiManager.this );
+                }
+
+
+                public void ungetService( Bundle bundle, ServiceRegistration registration, Object service )
+                {
+                    // do nothing
+                }
+            }, new Hashtable<String, String>()
             {
-                // might be caused by CM API not available
-            }
-        }
+                {
+                    put( Constants.SERVICE_VENDOR, "The Apache Software Foundation" ); //$NON-NLS-1$
+                    put( Constants.SERVICE_DESCRIPTION, "OSGi Management Console Configuration Receiver" ); //$NON-NLS-1$
+                    put( Constants.SERVICE_PID, getConfigurationPid() );
+                }
+            } );
     }
 
     public void dispose()
@@ -551,14 +560,18 @@ public class OsgiManager extends Generic
         return getClass().getName();
     }
 
+
     /**
-     * Calls the <code>GenericServlet.log(String)</code> method if the
+     * Calls the <code>ServletContext.log(String)</code> method if the
      * configured log level is less than or equal to the given <code>level</code>.
      * <p>
      * Note, that the <code>level</code> parameter is only used to decide whether
      * the <code>GenericServlet.log(String)</code> method is called or not. The
      * actual implementation of the <code>GenericServlet.log</code> method is
      * outside of the control of this method.
+     * <p>
+     * If the servlet has not been initialized yet or has already been destroyed
+     * the message is printed to stderr.
      *
      * @param level The log level at which to log the message
      * @param message The message to log
@@ -567,12 +580,23 @@ public class OsgiManager extends Generic
     {
         if (logLevel >= level)
         {
-            log(message);
+            ServletConfig config = getServletConfig();
+            if ( config != null )
+            {
+                ServletContext context = config.getServletContext();
+                if ( context != null )
+                {
+                    context.log( message );
+                    return;
+                }
+            }
+
+            System.err.println( message );
         }
     }
 
     /**
-     * Calls the <code>GenericServlet.log(String, Throwable)</code> method if
+     * Calls the <code>ServletContext.log(String, Throwable)</code> method if
      * the configured log level is less than or equal to the given
      * <code>level</code>.
      * <p>
@@ -580,6 +604,9 @@ public class OsgiManager extends Generic
      * the <code>GenericServlet.log(String, Throwable)</code> method is called
      * or not. The actual implementation of the <code>GenericServlet.log</code>
      * method is outside of the control of this method.
+     * <p>
+     * If the servlet has not been initialized yet or has already been destroyed
+     * the message is printed to stderr.
      *
      * @param level The log level at which to log the message
      * @param message The message to log
@@ -589,7 +616,22 @@ public class OsgiManager extends Generic
     {
         if (logLevel >= level)
         {
-            log(message, t);
+            ServletConfig config = getServletConfig();
+            if ( config != null )
+            {
+                ServletContext context = config.getServletContext();
+                if ( context != null )
+                {
+                    context.log( message, t );
+                    return;
+                }
+            }
+
+            System.err.println( message );
+            if ( t != null )
+            {
+                t.printStackTrace( System.err );
+            }
         }
     }
 

Modified: felix/trunk/webconsole/src/main/resources/res/ui/config.js
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/resources/res/ui/config.js?rev=1220723&r1=1220722&r2=1220723&view=diff
==============================================================================
--- felix/trunk/webconsole/src/main/resources/res/ui/config.js (original)
+++ felix/trunk/webconsole/src/main/resources/res/ui/config.js Mon Dec 19 12:54:03 2011
@@ -541,11 +541,22 @@ $(document).ready(function() {
 		for(var i in configData.fpids) {
 			addFactoryConfig(configData.fpids[i]);
 
-			var confs = factories[ configData.fpids[i].id ];
-			if (confs) for (var j in confs) {
-				addConfig(confs[j]);
+			var fpid = configData.fpids[i].id;
+			var confs = factories[ fpid ];
+			if (confs) {
+			    for (var j in confs) {
+			        addConfig(confs[j]);
+			    }
+			    delete factories[ fpid ];
 			}
 		}
+		for(var fpid in factories) {
+		    var flist = factories[fpid];
+		    for(var i in flist) {
+		        delete flist[i].fpid; // render as regular config
+		        addConfig(flist[i]);
+		    }
+		}
 		initStaticWidgets(configTable);
 
 		// init tablesorte