FELIX-4561 - Unregistration fails sometimes:

- if the HttpService itself is stopping, it deregisters all of its
  servlets and filters. This causes the whiteboard service to also
  start deregistering its servlets & filters, causing exceptions in
  the HttpService;
- make the whiteboard unregister at best-effort, catching exceptions
  that occur during the unregistration & log a message instead;
- suppress throwing of exceptions when unregister is called on the
  HttpService while the bundle is stopping.



git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1634894 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java
index 1f48b06..3ba93d7 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java
@@ -68,7 +68,7 @@
             servletMap.remove(handler.getServlet(), handler);
 
             handler.destroy();
-            throw new NamespaceException("Servlet with alias already registered");
+            throw new NamespaceException("Servlet with alias '" + handler.getAlias() + "' already registered");
         }
 
         updateServletArray();
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/logger/SystemLogger.java b/http/base/src/main/java/org/apache/felix/http/base/internal/logger/SystemLogger.java
index b782017..4330e81 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/logger/SystemLogger.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/logger/SystemLogger.java
@@ -40,6 +40,11 @@
         getLogger().log(LogService.LOG_DEBUG, message);
     }
 
+    public static void debug(String message, Throwable cause)
+    {
+        getLogger().log(LogService.LOG_DEBUG, message, cause);
+    }
+
     public static void info(String message)
     {
         getLogger().log(LogService.LOG_INFO, message);
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
index 7e1e189..ce4cdc0 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
@@ -124,9 +124,17 @@
     public void unregister(String alias)
     {
         final Servlet servlet = this.handlerRegistry.getServletByAlias(alias);
-        if ( servlet == null )
+        if (servlet == null)
         {
-            throw new IllegalArgumentException("Nothing registered at " + alias);
+            // FELIX-4561 - don't bother throwing an exception if we're stopping anyway...
+            if ((bundle.getState() & Bundle.STOPPING) != 0)
+            {
+                throw new IllegalArgumentException("Nothing registered at " + alias);
+            }
+            else
+            {
+                SystemLogger.debug("Nothing registered at " + alias + "; ignoring this because the bundle is stopping!", null);
+            }
         }
         unregisterServlet(servlet);
     }
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java
index 961dcc5..0185f5b 100644
--- a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java
@@ -23,8 +23,7 @@
 import org.osgi.framework.Bundle;
 import org.osgi.service.http.HttpService;
 
-public final class FilterMapping
-    extends AbstractMapping
+public final class FilterMapping extends AbstractMapping
 {
     private final Filter filter;
     private final int ranking;
@@ -38,31 +37,50 @@
         this.ranking = ranking;
     }
 
+    public void register(HttpService httpService)
+    {
+        if (httpService instanceof ExtHttpService)
+        {
+            register((ExtHttpService) httpService);
+        }
+        else
+        {
+            // Warn the user that something strange is going on...
+            SystemLogger.warning("Unable to register filter for " + this.pattern + ", as no ExtHttpService seems to be present!", null);
+        }
+    }
+
+    public void unregister(HttpService httpService)
+    {
+        if (httpService instanceof ExtHttpService)
+        {
+            unregister((ExtHttpService) httpService);
+        }
+        else
+        {
+            // Warn the user that something strange is going on...
+            SystemLogger.warning("Unable to unregister filter for " + this.pattern + ", as no ExtHttpService seems to be present!", null);
+        }
+    }
+
     Filter getFilter()
     {
         return filter;
     }
 
-    int getRanking()
-    {
-        return ranking;
-    }
-
     String getPattern()
     {
         return pattern;
     }
 
-    public void register(HttpService httpService)
+    int getRanking()
     {
-       if (httpService instanceof ExtHttpService) {
-            register((ExtHttpService)httpService);
-        }
+        return ranking;
     }
 
     private void register(ExtHttpService httpService)
     {
-        if (!this.isRegistered() && getContext() != null)
+        if (!isRegistered() && getContext() != null)
         {
             try
             {
@@ -71,22 +89,31 @@
             }
             catch (Exception e)
             {
-                SystemLogger.error("Failed to register filter", e);
+                // Warn that something might have gone astray...
+                SystemLogger.warning("Failed to register filter for " + this.pattern, null);
+                SystemLogger.debug("Failed to register filter for " + this.pattern + "; details:", e);
             }
         }
     }
 
-    public void unregister(HttpService httpService)
-    {
-        if (httpService instanceof ExtHttpService && this.isRegistered())
-        {
-            unregister((ExtHttpService) httpService);
-            setRegistered(false);
-        }
-    }
-
     private void unregister(ExtHttpService httpService)
     {
-        httpService.unregisterFilter(this.filter);
+        if (isRegistered())
+        {
+            try
+            {
+                httpService.unregisterFilter(this.filter);
+            }
+            catch (Exception e)
+            {
+                // Warn that something might have gone astray...
+                SystemLogger.debug("Failed to unregister filter for " + this.pattern, e);
+            }
+            finally
+            {
+                // Best effort: avoid mappings that are registered which is reality aren't registered...
+                setRegistered(false);
+            }
+        }
     }
 }
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java
index 67b8d8c..eb19bdd 100644
--- a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java
@@ -22,8 +22,7 @@
 import org.osgi.framework.Bundle;
 import org.osgi.service.http.HttpService;
 
-public final class ServletMapping
-    extends AbstractMapping
+public final class ServletMapping extends AbstractMapping
 {
     private final Servlet servlet;
     private final String alias;
@@ -35,6 +34,44 @@
         this.alias = alias;
     }
 
+    public void register(HttpService httpService)
+    {
+        if (!isRegistered() && getContext() != null)
+        {
+            try
+            {
+                httpService.registerServlet(this.alias, this.servlet, getInitParams(), getContext());
+                setRegistered(true);
+            }
+            catch (Exception e)
+            {
+                // Warn that something might have gone astray...
+                SystemLogger.warning("Failed to register servlet for " + this.alias, e);
+            }
+        }
+    }
+
+    public void unregister(HttpService httpService)
+    {
+        if (isRegistered())
+        {
+            try
+            {
+                httpService.unregister(this.alias);
+            }
+            catch (Exception e)
+            {
+                // Warn that something might have gone astray...
+                SystemLogger.debug("Failed to unregister servlet for " + this.alias, e);
+            }
+            finally
+            {
+                // Best effort: avoid mappings that are registered which is reality aren't registered...
+                setRegistered(false);
+            }
+        }
+    }
+
     String getAlias()
     {
         return this.alias;
@@ -44,29 +81,4 @@
     {
         return this.servlet;
     }
-
-    public void register(HttpService httpService)
-    {
-        if (!this.isRegistered() && getContext() != null)
-        {
-            try
-            {
-                httpService.registerServlet(this.alias, this.servlet, getInitParams(), getContext());
-                this.setRegistered(true);
-            }
-            catch (Exception e)
-            {
-                SystemLogger.error("Failed to register servlet", e);
-            }
-        }
-    }
-
-    public void unregister(HttpService httpService)
-    {
-        if (this.isRegistered())
-        {
-            httpService.unregister(this.alias);
-            this.setRegistered(false);
-        }
-    }
 }