FELIX-4060 : Implement HTTP Whiteboard Service (RFC-189). Clean up code, add some javadocs

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1680915 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterConfigImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterConfigImpl.java
index 4f91043..342260f 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterConfigImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterConfigImpl.java
@@ -23,6 +23,9 @@
 import javax.servlet.FilterConfig;
 import javax.servlet.ServletContext;
 
+/**
+ * Implementation of the filter configuration.
+ */
 public final class FilterConfigImpl implements FilterConfig
 {
     private final String name;
@@ -49,7 +52,7 @@
     }
 
     @Override
-    public String getInitParameter(String name)
+    public String getInitParameter(final String name)
     {
         return this.initParams.get(name);
     }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
index a1cc0e2..f896f0e 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
@@ -31,7 +31,8 @@
 import org.osgi.service.http.runtime.dto.DTOConstants;
 
 /**
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ * The filter handler handles the initialization and destruction of filter
+ * objects.
  */
 public class FilterHandler implements Comparable<FilterHandler>
 {
@@ -116,7 +117,7 @@
         {
             filter.init(new FilterConfigImpl(getName(), getContext(), getFilterInfo().getInitParameters()));
         }
-        catch (final ServletException e)
+        catch (final Exception e)
         {
             SystemLogger.error(this.getFilterInfo().getServiceReference(),
                     "Error during calling init() on filter " + this.filter,
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpServiceFilterHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpServiceFilterHandler.java
index 4055ecd..013af7f 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpServiceFilterHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpServiceFilterHandler.java
@@ -23,7 +23,7 @@
 import org.apache.felix.http.base.internal.service.HttpServiceFactory;
 
 /**
- * Servlet holder for filters registered through the ext http service.
+ * Servlet handler for filters registered through the ext http service.
  */
 public final class HttpServiceFilterHandler extends FilterHandler
 {
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletConfigImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletConfigImpl.java
index d66c5c5..4ac55d6 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletConfigImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletConfigImpl.java
@@ -23,6 +23,9 @@
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
 
+/**
+ * Implementation of the servlet configuration
+ */
 public final class ServletConfigImpl implements ServletConfig
 {
     private final String name;
@@ -51,7 +54,7 @@
     }
 
     @Override
-    public String getInitParameter(String name)
+    public String getInitParameter(final String name)
     {
         return this.initParams.get(name);
     }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
index b6c2cc7..1ea14dd 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
@@ -29,7 +29,8 @@
 import org.osgi.service.http.runtime.dto.DTOConstants;
 
 /**
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ * The servlet handler handles the initialization and destruction of
+ * a servlet.
  */
 public abstract class ServletHandler implements Comparable<ServletHandler>
 {
@@ -120,7 +121,7 @@
         {
             servlet.init(new ServletConfigImpl(getName(), getContext(), getServletInfo().getInitParameters()));
         }
-        catch (final ServletException e)
+        catch (final Exception e)
         {
             SystemLogger.error(this.getServletInfo().getServiceReference(),
                     "Error during calling init() on servlet " + this.servlet,
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardFilterHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardFilterHandler.java
index 698cbf4..dc33ff7 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardFilterHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardFilterHandler.java
@@ -57,7 +57,10 @@
         final int reason = super.init();
         if ( reason != -1 )
         {
-            so.ungetService(this.getFilter());
+            if ( so != null )
+            {
+                so.ungetService(this.getFilter());
+            }
             this.setFilter(null);
         }
         return reason;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardServletHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardServletHandler.java
index 25d8792..1d1a59d 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardServletHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardServletHandler.java
@@ -57,7 +57,10 @@
         final int reason = super.init();
         if ( reason != -1 )
         {
-            so.ungetService(this.getServlet());
+            if ( so != null )
+            {
+                so.ungetService(this.getServlet());
+            }
             this.setServlet(null);
         }
         return reason;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java
index e059c9d..4a3e6d8 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java
@@ -43,7 +43,7 @@
  * for a single servlet context.
  *
  * TODO - sort active servlet mappings by pattern length, longest first (avoids looping over all)
- *
+ * TODO - we could collapse all three maps into a single map (activeServletMappings, inactiveServletMappings and statusMapping)
  */
 public final class ServletRegistry
 {
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailedDTOHolder.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailedDTOHolder.java
index 023aec0..6f69af9 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailedDTOHolder.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailedDTOHolder.java
@@ -19,8 +19,8 @@
 package org.apache.felix.http.base.internal.runtime.dto;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.felix.http.base.internal.logger.SystemLogger;
@@ -41,17 +41,17 @@
 public final class FailedDTOHolder
 {
 
-    public Collection<FailedFilterDTO> failedFilterDTOs = new ArrayList<FailedFilterDTO>();
+    public final List<FailedFilterDTO> failedFilterDTOs = new ArrayList<FailedFilterDTO>();
 
-    public Collection<FailedListenerDTO> failedListenerDTOs = new ArrayList<FailedListenerDTO>();
+    public final List<FailedListenerDTO> failedListenerDTOs = new ArrayList<FailedListenerDTO>();
 
-    public Collection<FailedServletDTO> failedServletDTOs = new ArrayList<FailedServletDTO>();
+    public final List<FailedServletDTO> failedServletDTOs = new ArrayList<FailedServletDTO>();
 
-    public Collection<FailedResourceDTO> failedResourceDTOs = new ArrayList<FailedResourceDTO>();
+    public final List<FailedResourceDTO> failedResourceDTOs = new ArrayList<FailedResourceDTO>();
 
-    public Collection<FailedErrorPageDTO> failedErrorPageDTOs = new ArrayList<FailedErrorPageDTO>();
+    public final List<FailedErrorPageDTO> failedErrorPageDTOs = new ArrayList<FailedErrorPageDTO>();
 
-    public Collection<FailedServletContextDTO> failedServletContextDTO = new ArrayList<FailedServletContextDTO>();
+    public final List<FailedServletContextDTO> failedServletContextDTO = new ArrayList<FailedServletContextDTO>();
 
     public void add(Map<AbstractInfo<?>, Integer> failureInfos)
     {
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/ResourceServlet.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/ResourceServlet.java
index 3243627..19f459d 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/ResourceServlet.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/ResourceServlet.java
@@ -28,31 +28,29 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+/**
+ * The resource servlet
+ */
 public final class ResourceServlet extends HttpServlet
 {
-    private final String path;
+    private static final long serialVersionUID = 1L;
 
-    public ResourceServlet(String path)
+    /** The path of the resource registration. */
+    private final String prefix;
+
+    public ResourceServlet(final String prefix)
     {
-        this.path = path;
+        this.prefix = prefix;
     }
 
     @Override
-    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
+    protected void doGet(final HttpServletRequest req, final HttpServletResponse res)
+            throws ServletException, IOException
     {
-        String target = req.getPathInfo();
-        if (target == null)
-        {
-            target = "";
-        }
+        final String target = req.getPathInfo();
+        final String resName = (target == null ? this.prefix : this.prefix + target);
 
-        if (!target.startsWith("/"))
-        {
-            target += "/" + target;
-        }
-
-        String resName = this.path + target;
-        URL url = getServletContext().getResource(resName);
+        final URL url = getServletContext().getResource(resName);
 
         if (url == null)
         {
@@ -64,15 +62,17 @@
         }
     }
 
-    private void handle(HttpServletRequest req, HttpServletResponse res, URL url, String resName) throws IOException
+    private void handle(final HttpServletRequest req,
+            final HttpServletResponse res, final URL url, final String resName)
+    throws IOException
     {
-        String contentType = getServletContext().getMimeType(resName);
+        final String contentType = getServletContext().getMimeType(resName);
         if (contentType != null)
         {
             res.setContentType(contentType);
         }
 
-        long lastModified = getLastModified(url);
+        final long lastModified = getLastModified(url);
         if (lastModified != 0)
         {
             res.setDateHeader("Last-Modified", lastModified);
@@ -88,26 +88,26 @@
         }
     }
 
-    private long getLastModified(URL url)
+    private long getLastModified(final URL url)
     {
         long lastModified = 0;
 
         try
         {
-            URLConnection conn = url.openConnection();
+            final URLConnection conn = url.openConnection();
             lastModified = conn.getLastModified();
         }
-        catch (Exception e)
+        catch (final Exception e)
         {
             // Do nothing
         }
 
         if (lastModified == 0)
         {
-            String filepath = url.getPath();
+            final String filepath = url.getPath();
             if (filepath != null)
             {
-                File f = new File(filepath);
+                final File f = new File(filepath);
                 if (f.exists())
                 {
                     lastModified = f.lastModified();
@@ -126,7 +126,7 @@
         return resTimestamp == 0 || modSince == -1 || resTimestamp > modSince;
     }
 
-    private void copyResource(URL url, HttpServletResponse res) throws IOException
+    private void copyResource(final URL url, final HttpServletResponse res) throws IOException
     {
         URLConnection conn = null;
         OutputStream os = null;
@@ -138,7 +138,7 @@
 
             is = conn.getInputStream();
             os = res.getOutputStream();
-            // FELIX-3987 content length should be set *before* any streaming is done 
+            // FELIX-3987 content length should be set *before* any streaming is done
             // as headers should be written before the content is actually written...
             int len = getContentLength(conn);
             if (len >= 0)
@@ -168,20 +168,20 @@
         }
     }
 
-    private int getContentLength(URLConnection conn)
+    private int getContentLength(final URLConnection conn)
     {
         int length = -1;
 
         length = conn.getContentLength();
         if (length < 0)
         {
-            // Unknown, try whether it is a file, and if so, use the file 
+            // Unknown, try whether it is a file, and if so, use the file
             // API to get the length of the content...
             String path = conn.getURL().getPath();
             if (path != null)
             {
                 File f = new File(path);
-                // In case more than 2GB is streamed 
+                // In case more than 2GB is streamed
                 if (f.length() < Integer.MAX_VALUE)
                 {
                     length = (int) f.length();
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ResourceServlet.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ResourceServlet.java
deleted file mode 100644
index e53e835..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ResourceServlet.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.felix.http.base.internal.whiteboard;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URL;
-import java.net.URLConnection;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * The resource servlet used for resource whiteboard registrations.
- */
-public final class ResourceServlet extends HttpServlet
-{
-    private static final long serialVersionUID = 1L;
-
-    /** The path of the resource registration. */
-    private final String prefix;
-
-    public ResourceServlet(final String prefix)
-    {
-        this.prefix = prefix;
-    }
-
-    @Override
-    protected void doGet(final HttpServletRequest req, final HttpServletResponse res)
-            throws ServletException, IOException
-    {
-        final String target = req.getPathInfo();
-        final String resName = (target == null ? this.prefix : this.prefix + target);
-
-        final URL url = getServletContext().getResource(resName);
-
-        if (url == null)
-        {
-            res.sendError(HttpServletResponse.SC_NOT_FOUND);
-        }
-        else
-        {
-            handle(req, res, url, resName);
-        }
-    }
-
-    private void handle(final HttpServletRequest req,
-            final HttpServletResponse res, final URL url, final String resName)
-    throws IOException
-    {
-        final String contentType = getServletContext().getMimeType(resName);
-        if (contentType != null)
-        {
-            res.setContentType(contentType);
-        }
-
-        final long lastModified = getLastModified(url);
-        if (lastModified != 0)
-        {
-            res.setDateHeader("Last-Modified", lastModified);
-        }
-
-        if (!resourceModified(lastModified, req.getDateHeader("If-Modified-Since")))
-        {
-            res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
-        }
-        else
-        {
-            copyResource(url, res);
-        }
-    }
-
-    private long getLastModified(final URL url)
-    {
-        long lastModified = 0;
-
-        try
-        {
-            final URLConnection conn = url.openConnection();
-            lastModified = conn.getLastModified();
-        }
-        catch (final Exception e)
-        {
-            // Do nothing
-        }
-
-        if (lastModified == 0)
-        {
-            final String filepath = url.getPath();
-            if (filepath != null)
-            {
-                final File f = new File(filepath);
-                if (f.exists())
-                {
-                    lastModified = f.lastModified();
-                }
-            }
-        }
-
-        return lastModified;
-    }
-
-    private boolean resourceModified(long resTimestamp, long modSince)
-    {
-        modSince /= 1000;
-        resTimestamp /= 1000;
-
-        return resTimestamp == 0 || modSince == -1 || resTimestamp > modSince;
-    }
-
-    private void copyResource(final URL url, final HttpServletResponse res) throws IOException
-    {
-        URLConnection conn = null;
-        OutputStream os = null;
-        InputStream is = null;
-
-        try
-        {
-            conn = url.openConnection();
-
-            is = conn.getInputStream();
-            os = res.getOutputStream();
-            // FELIX-3987 content length should be set *before* any streaming is done
-            // as headers should be written before the content is actually written...
-            int len = getContentLength(conn);
-            if (len >= 0)
-            {
-                res.setContentLength(len);
-            }
-
-            byte[] buf = new byte[1024];
-            int n;
-
-            while ((n = is.read(buf, 0, buf.length)) >= 0)
-            {
-                os.write(buf, 0, n);
-            }
-        }
-        finally
-        {
-            if (is != null)
-            {
-                is.close();
-            }
-
-            if (os != null)
-            {
-                os.close();
-            }
-        }
-    }
-
-    private int getContentLength(final URLConnection conn)
-    {
-        int length = -1;
-
-        length = conn.getContentLength();
-        if (length < 0)
-        {
-            // Unknown, try whether it is a file, and if so, use the file
-            // API to get the length of the content...
-            String path = conn.getURL().getPath();
-            if (path != null)
-            {
-                File f = new File(path);
-                // In case more than 2GB is streamed
-                if (f.length() < Integer.MAX_VALUE)
-                {
-                    length = (int) f.length();
-                }
-            }
-        }
-        return length;
-    }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java
index ad473a7..659e284 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java
@@ -27,6 +27,7 @@
 import org.apache.felix.http.base.internal.runtime.FilterInfo;
 import org.apache.felix.http.base.internal.runtime.ResourceInfo;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.apache.felix.http.base.internal.service.ResourceServlet;
 import org.osgi.framework.BundleContext;
 
 public final class WhiteboardHttpService