FELIX-6621 : Regressions caused by FELIX-6607
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java
index 2b2818c..c58294e 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java
@@ -29,6 +29,7 @@
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;
@@ -263,4 +264,13 @@
return Locale.getDefault();
}
}
+
+
+ public static String getStringProperty( final ServiceReference<?> service, final String propertyName ) {
+ final Object property = service.getProperty( propertyName );
+ if ( property instanceof String ) {
+ return ( String ) property;
+ }
+ return null;
+ }
}
\ No newline at end of file
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
index b122e11..d52ede4 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
@@ -63,7 +63,7 @@
import org.apache.felix.webconsole.internal.core.BundlesServlet;
import org.apache.felix.webconsole.internal.filter.FilteringResponseWrapper;
import org.apache.felix.webconsole.internal.i18n.ResourceBundleManager;
-import org.apache.felix.webconsole.internal.servlet.PluginHolder.InternalPlugin;
+import org.apache.felix.webconsole.internal.servlet.Plugin.InternalPlugin;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/Plugin.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/Plugin.java
index 0b63c79..9ea34a5 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/Plugin.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/Plugin.java
@@ -20,6 +20,7 @@
import java.util.Collections;
import java.util.Enumeration;
+import java.util.NoSuchElementException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
@@ -27,9 +28,14 @@
import javax.servlet.ServletException;
import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.apache.felix.webconsole.WebConsoleConstants;
+import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
+import org.apache.felix.webconsole.internal.Util;
+import org.apache.felix.webconsole.internal.WebConsolePluginAdapter;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
public abstract class Plugin implements ServletConfig, Comparable<Plugin> {
@@ -38,7 +44,9 @@
private final ServiceReference<Servlet> serviceReference; // used for comparing conflicting services
- private volatile String title;
+ protected volatile String title;
+
+ protected volatile String category;
private volatile AbstractWebConsolePlugin consolePlugin;
@@ -52,8 +60,6 @@
return this.serviceReference;
}
- public abstract String getId();
-
public Bundle getBundle() {
if ( this.serviceReference != null ) {
return this.serviceReference.getBundle();
@@ -62,6 +68,22 @@
}
/**
+ * Initialize everything including title and category
+ */
+ public boolean init() {
+ final AbstractWebConsolePlugin plugin = this.doGetConsolePlugin();
+ if ( plugin != null ) {
+ try {
+ plugin.init(this);
+ } catch (final ServletException e) {
+ // ignore this
+ }
+ this.consolePlugin = plugin;
+ }
+ return this.getConsolePlugin() != null;
+ }
+
+ /**
* Cleans up this plugin when it is not used any longer. This means
* destroying the plugin servlet and, if it was registered as an OSGi
* service, ungetting the service.
@@ -90,67 +112,42 @@
@Override
public int compareTo(final Plugin other) {
- // serviceReference = null means internal (i.e. service.ranking=0 and service.id=0)
- final Long id = serviceReference != null ? (Long) serviceReference.getProperty(Constants.SERVICE_ID) : 0;
- final Long otherId = other.serviceReference != null ? (Long) other.serviceReference.getProperty(Constants.SERVICE_ID) : 0;
- if (id.compareTo(otherId) == 0) {
- return 0; // same service or both internal
+ int result = this.getLabel().compareTo(other.getLabel());
+ if (result == 0) {
+ // serviceReference = null means internal (i.e. service.ranking=0 and service.id=0)
+ final Long id = serviceReference != null ? (Long) serviceReference.getProperty(Constants.SERVICE_ID) : 0;
+ final Long otherId = other.serviceReference != null ? (Long) other.serviceReference.getProperty(Constants.SERVICE_ID) : 0;
+ result = id.compareTo(otherId);
+ if (result != 0) { // same service or both internal if 0
+ final Integer rank = getRanking(this.serviceReference);
+ final Integer otherRank = getRanking(other.serviceReference);
+ result = rank.compareTo(otherRank);
+ if (result == 0) {
+ // If ranks are equal, then sort by service id in descending order.
+ result = -1 * id.compareTo(otherId);
+ }
+ }
}
-
- final Integer rank = getRanking(this.serviceReference);
- final Integer otherRank = getRanking(other.serviceReference);
-
- // Sort by rank in ascending order.
- if (rank.compareTo(otherRank) < 0) {
- return -1; // lower rank
- } else if (rank.compareTo(otherRank) > 0) {
- return 1; // higher rank
- }
-
- // If ranks are equal, then sort by service id in descending order.
- return -1 * id.compareTo(otherId);
- }
-
- protected PluginHolder getHolder() {
- return holder;
+ return result;
}
public String getLabel() {
return label;
}
- protected void setTitle(final String title ) {
- this.title = title;
+ protected PluginHolder getHolder() {
+ return holder;
}
public String getTitle() {
return this.title != null ? this.title : this.getLabel();
}
- // methods added to support categories
-
- final String getCategory() {
- return doGetCategory();
+ public String getCategory() {
+ return this.category;
}
- protected String doGetCategory() {
- // get the service now
- final AbstractWebConsolePlugin plugin = getConsolePlugin();
- return ( plugin != null ) ? plugin.getCategory() : null;
- }
-
- public final AbstractWebConsolePlugin getConsolePlugin() {
- if ( this.consolePlugin == null ) {
- final AbstractWebConsolePlugin plugin = this.doGetConsolePlugin();
- if ( plugin != null ) {
- try {
- plugin.init(this);
- } catch (final ServletException e) {
- // ignore this
- }
- this.consolePlugin = plugin;
- }
- }
+ public AbstractWebConsolePlugin getConsolePlugin() {
return this.consolePlugin;
}
@@ -158,6 +155,8 @@
return true;
}
+ public abstract String getId();
+
protected abstract AbstractWebConsolePlugin doGetConsolePlugin();
protected abstract void doUngetConsolePlugin( AbstractWebConsolePlugin consolePlugin );
@@ -183,4 +182,135 @@
public String getServletName() {
return getTitle();
}
+
+ public static class ServletPlugin extends Plugin {
+
+ public ServletPlugin( final PluginHolder holder, final ServiceReference<Servlet> serviceReference, final String label ) {
+ super(holder, serviceReference, label);
+ }
+
+ public String getId() {
+ return this.getServiceReference().toString();
+ }
+
+ protected AbstractWebConsolePlugin doGetConsolePlugin() {
+ final Servlet service = getHolder().getBundleContext().getService( this.getServiceReference() );
+ if ( service != null ) {
+ this.title = Util.getStringProperty( this.getServiceReference(), WebConsoleConstants.PLUGIN_TITLE );
+ this.category = Util.getStringProperty( this.getServiceReference(), WebConsoleConstants.PLUGIN_CATEGORY );
+ final AbstractWebConsolePlugin servlet;
+ if ( service instanceof AbstractWebConsolePlugin ) {
+ servlet = ( AbstractWebConsolePlugin ) service;
+ if (this.title == null) {
+ this.title = servlet.getTitle();
+ }
+ if (this.category == null) {
+ this.category = servlet.getCategory();
+ }
+ } else {
+ servlet = new WebConsolePluginAdapter( getLabel(), service, this.getServiceReference() );
+ }
+ return servlet;
+ }
+ return null;
+ }
+
+ protected void doUngetConsolePlugin( AbstractWebConsolePlugin consolePlugin ) {
+ try {
+ getHolder().getBundleContext().ungetService( this.getServiceReference() );
+ } catch ( final IllegalStateException ise ) {
+ // ignore - bundle context is no longer valid
+ }
+ }
+
+ //---------- ServletConfig overwrite (based on ServletReference)
+
+ @Override
+ public String getInitParameter( final String name ) {
+ Object property = this.getServiceReference().getProperty( name );
+ if ( property != null && !property.getClass().isArray() ) {
+ return property.toString();
+ }
+
+ return super.getInitParameter( name );
+ }
+
+ @Override
+ public Enumeration<?> getInitParameterNames() {
+ final String[] keys = this.getServiceReference().getPropertyKeys();
+ return new Enumeration<Object>() {
+ int idx = 0;
+
+ public boolean hasMoreElements() {
+ return idx < keys.length;
+ }
+
+ public Object nextElement() {
+ if ( hasMoreElements() ) {
+ return keys[idx++];
+ }
+ throw new NoSuchElementException();
+ }
+ };
+ }
+ }
+
+ public static class InternalPlugin extends Plugin {
+
+ private final String pluginClassName;
+ private final OsgiManager osgiManager;
+ private volatile boolean doLog = true;
+
+ public InternalPlugin(PluginHolder holder, OsgiManager osgiManager, String pluginClassName, String label) {
+ super(holder, null, label);
+ this.osgiManager = osgiManager;
+ this.pluginClassName = pluginClassName;
+ }
+
+ public String getId() {
+ return this.pluginClassName;
+ }
+
+ protected final boolean isEnabled() {
+ // check if the plugin is enabled
+ return !osgiManager.isPluginDisabled(pluginClassName);
+ }
+
+ protected AbstractWebConsolePlugin doGetConsolePlugin() {
+ if (!isEnabled()) {
+ if (doLog) {
+ osgiManager.log( LogService.LOG_INFO, "Ignoring plugin " + pluginClassName + ": Disabled by configuration" );
+ doLog = false;
+ }
+ return null;
+ }
+
+ AbstractWebConsolePlugin plugin = null;
+ try {
+ Class<?> pluginClass = getClass().getClassLoader().loadClass(pluginClassName);
+ plugin = (AbstractWebConsolePlugin) pluginClass.getDeclaredConstructor().newInstance();
+
+ if (plugin instanceof OsgiManagerPlugin) {
+ ((OsgiManagerPlugin) plugin).activate(osgiManager.getBundleContext());
+ }
+ this.title = plugin.getTitle();
+ this.category = plugin.getCategory();
+ doLog = true; // reset logging if it succeeded
+ } catch (final Throwable t) {
+ plugin = null; // in case only activate has faled!
+ if (doLog) {
+ osgiManager.log( LogService.LOG_WARNING, "Failed to instantiate plugin " + pluginClassName, t );
+ doLog = false;
+ }
+ }
+
+ return plugin;
+ }
+
+ protected void doUngetConsolePlugin(final AbstractWebConsolePlugin plugin) {
+ if (plugin instanceof OsgiManagerPlugin) {
+ ((OsgiManagerPlugin) plugin).deactivate();
+ }
+ }
+ }
}
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/PluginHolder.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/PluginHolder.java
index e7bbc25..05e69fd 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/PluginHolder.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/PluginHolder.java
@@ -20,12 +20,10 @@
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.NoSuchElementException;
import java.util.ResourceBundle;
import javax.servlet.Servlet;
@@ -33,9 +31,10 @@
import org.apache.felix.webconsole.AbstractWebConsolePlugin;
import org.apache.felix.webconsole.WebConsoleConstants;
-import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
-import org.apache.felix.webconsole.internal.WebConsolePluginAdapter;
+import org.apache.felix.webconsole.internal.Util;
import org.apache.felix.webconsole.internal.i18n.ResourceBundleManager;
+import org.apache.felix.webconsole.internal.servlet.Plugin.InternalPlugin;
+import org.apache.felix.webconsole.internal.servlet.Plugin.ServletPlugin;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
@@ -328,7 +327,7 @@
@Override
public Plugin addingService(final ServiceReference<Servlet> reference) {
Plugin plugin = null;
- final String label = getProperty( reference, WebConsoleConstants.PLUGIN_LABEL );
+ final String label = Util.getStringProperty( reference, WebConsoleConstants.PLUGIN_LABEL );
if ( label != null ) {
plugin = new ServletPlugin( this, reference, label );
addPlugin( plugin );
@@ -357,11 +356,15 @@
Collections.sort(list);
Collections.reverse(list);
final Plugin first = list.get(0);
- if (first == plugin && oldPlugin != null) {
- osgiManager.log(LogService.LOG_WARNING, "Overwriting existing plugin " + oldPlugin.getId()
- + " having label " + plugin.getLabel() + " with new plugin " + plugin.getId()
- + " due to higher ranking " );
- oldPlugin.dispose();
+ if (first == plugin) {
+ if (!first.init()) {
+ list.remove(plugin);
+ } else if (oldPlugin != null) {
+ osgiManager.log(LogService.LOG_WARNING, "Overwriting existing plugin " + oldPlugin.getId()
+ + " having label " + plugin.getLabel() + " with new plugin " + plugin.getId()
+ + " due to higher ranking " );
+ oldPlugin.dispose();
+ }
}
if (first == oldPlugin) {
osgiManager.log(LogService.LOG_WARNING, "Ignoring new plugin " + plugin.getId()
@@ -374,159 +377,17 @@
synchronized ( plugins ) {
final List<Plugin> list = plugins.get( plugin.getLabel() );
if ( list != null ) {
+ final boolean isFirst = !list.isEmpty() && list.get(0) == plugin;
list.remove( plugin );
if ( list.isEmpty() ) {
plugins.remove( plugin.getLabel() );
+ } else if ( isFirst ) {
+ while ( !list.isEmpty() && !list.get(0).init() ) {
+ list.remove(0);
+ }
}
}
plugin.dispose();
}
}
-
- static String getProperty( final ServiceReference<?> service, final String propertyName ) {
- final Object property = service.getProperty( propertyName );
- if ( property instanceof String ) {
- return ( String ) property;
- }
- return null;
- }
-
- private static class ServletPlugin extends Plugin {
-
- ServletPlugin( final PluginHolder holder, final ServiceReference<Servlet> serviceReference, final String label ) {
- super(holder, serviceReference, label);
- }
-
- public String getId() {
- return this.getServiceReference().toString();
- }
-
- // added to support categories
- protected String doGetCategory() {
- // check service Reference
- final String category = getProperty( this.getServiceReference(), WebConsoleConstants.PLUGIN_CATEGORY );
- if ( category != null ) {
- return category;
- }
-
- return super.doGetCategory();
- }
-
- protected AbstractWebConsolePlugin doGetConsolePlugin() {
- final Servlet service = getHolder().getBundleContext().getService( this.getServiceReference() );
- if ( service != null ) {
- String title = getProperty( this.getServiceReference(), WebConsoleConstants.PLUGIN_TITLE );
- final AbstractWebConsolePlugin servlet;
- if ( service instanceof AbstractWebConsolePlugin ) {
- servlet = ( AbstractWebConsolePlugin ) service;
- if (title == null) {
- title = servlet.getTitle();
- }
- } else {
- servlet = new WebConsolePluginAdapter( getLabel(), service, this.getServiceReference() );
- }
- this.setTitle(title);
-
- return servlet;
- }
- return null;
- }
-
- protected void doUngetConsolePlugin( AbstractWebConsolePlugin consolePlugin ) {
- try {
- getHolder().getBundleContext().ungetService( this.getServiceReference() );
- } catch ( final IllegalStateException ise ) {
- // ignore - bundle context is no longer valid
- }
- }
-
- //---------- ServletConfig overwrite (based on ServletReference)
-
- @Override
- public String getInitParameter( final String name ) {
- Object property = this.getServiceReference().getProperty( name );
- if ( property != null && !property.getClass().isArray() ) {
- return property.toString();
- }
-
- return super.getInitParameter( name );
- }
-
- @Override
- public Enumeration<?> getInitParameterNames() {
- final String[] keys = this.getServiceReference().getPropertyKeys();
- return new Enumeration<Object>() {
- int idx = 0;
-
- public boolean hasMoreElements() {
- return idx < keys.length;
- }
-
- public Object nextElement() {
- if ( hasMoreElements() ) {
- return keys[idx++];
- }
- throw new NoSuchElementException();
- }
- };
- }
- }
-
- static class InternalPlugin extends Plugin {
-
- private final String pluginClassName;
- private final OsgiManager osgiManager;
- private volatile boolean doLog = true;
-
- protected InternalPlugin(PluginHolder holder, OsgiManager osgiManager, String pluginClassName, String label) {
- super(holder, null, label);
- this.osgiManager = osgiManager;
- this.pluginClassName = pluginClassName;
- }
-
- public String getId() {
- return this.pluginClassName;
- }
-
- protected final boolean isEnabled() {
- // check if the plugin is enabled
- return !osgiManager.isPluginDisabled(pluginClassName);
- }
-
- protected AbstractWebConsolePlugin doGetConsolePlugin() {
- if (!isEnabled()) {
- if (doLog) {
- osgiManager.log( LogService.LOG_INFO, "Ignoring plugin " + pluginClassName + ": Disabled by configuration" );
- doLog = false;
- }
- return null;
- }
-
- AbstractWebConsolePlugin plugin = null;
- try {
- Class<?> pluginClass = getClass().getClassLoader().loadClass(pluginClassName);
- plugin = (AbstractWebConsolePlugin) pluginClass.getDeclaredConstructor().newInstance();
-
- if (plugin instanceof OsgiManagerPlugin) {
- ((OsgiManagerPlugin) plugin).activate(osgiManager.getBundleContext());
- }
- this.setTitle(plugin.getTitle());
- doLog = true; // reset logging if it succeeded
- } catch (final Throwable t) {
- plugin = null; // in case only activate has faled!
- if (doLog) {
- osgiManager.log( LogService.LOG_WARNING, "Failed to instantiate plugin " + pluginClassName, t );
- doLog = false;
- }
- }
-
- return plugin;
- }
-
- protected void doUngetConsolePlugin(final AbstractWebConsolePlugin plugin) {
- if (plugin instanceof OsgiManagerPlugin) {
- ((OsgiManagerPlugin) plugin).deactivate();
- }
- }
- }
}