FELIX-4888 : ServletHandler's are not sorted by longest matching path. DTO handling (WiP)

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1680059 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistry.java
index 90101e6..74253e9 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistry.java
@@ -17,7 +17,6 @@
 package org.apache.felix.http.base.internal.registry;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -29,7 +28,6 @@
 import java.util.regex.Pattern;
 
 import javax.annotation.Nonnull;
-import javax.servlet.Servlet;
 
 import org.apache.felix.http.base.internal.handler.ServletHandler;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
@@ -85,9 +83,9 @@
 
     private final Map<ServletInfo, ErrorRegistrationStatus> statusMapping = new ConcurrentHashMap<ServletInfo, ErrorRegistrationStatus>();
 
-    private static final class ErrorRegistration {
-        final Set<Long> errorCodes = new TreeSet<Long>();
-        final Set<String> exceptions = new TreeSet<String>();
+    public static final class ErrorRegistration {
+        public final Set<Long> errorCodes = new TreeSet<Long>();
+        public final Set<String> exceptions = new TreeSet<String>();
     }
 
     private static final class ErrorRegistrationStatus {
@@ -96,7 +94,7 @@
         final Map<String, Integer> exceptionMapping = new ConcurrentHashMap<String, Integer>();
     }
 
-    private ErrorRegistration getErrorRegistration(@Nonnull final ServletInfo info)
+    public static ErrorRegistration getErrorRegistration(@Nonnull final ServletInfo info)
     {
         if ( info.getErrorPage() != null )
         {
@@ -386,8 +384,8 @@
         return result == -1;
     }
 
-    public void getRuntimeInfo(final Collection<ServletState> servletStates,
-            final Collection<FailureServletState> failureServletStates)
+    public void getRuntimeInfo(final Map<Long, ServletState> servletStates,
+            final Map<Long, Map<Integer, FailureServletState>> failureServletStates)
     {
         for(final ErrorRegistrationStatus status : this.statusMapping.values())
         {
@@ -431,94 +429,56 @@
             }
             if ( !active.errorCodes.isEmpty() || !active.exceptions.isEmpty() )
             {
-                servletStates.add(new ServletState()
+                ServletState state = servletStates.get(status.handler.getServletInfo().getServiceId());
+                if ( state == null )
                 {
-
-                    @Override
-                    public Servlet getServlet()
+                    state = new ServletState(status.handler);
+                    servletStates.put(status.handler.getServletInfo().getServiceId(), state);
+                }
+                if ( !active.errorCodes.isEmpty() )
+                {
+                    final long[] codes = new long[active.errorCodes.size()];
+                    final Iterator<Long> iter = active.errorCodes.iterator();
+                    for(int i=0; i<codes.length; i++)
                     {
-                        return status.handler.getServlet();
+                        codes[i] = iter.next();
                     }
-
-                    @Override
-                    public ServletInfo getServletInfo()
-                    {
-                        return status.handler.getServletInfo();
-                    }
-
-                    @Override
-                    public String[] getPatterns()
-                    {
-                        return null;
-                    }
-
-                    @Override
-                    public long[] getErrorCodes()
-                    {
-                        final long[] codes = new long[active.errorCodes.size()];
-                        final Iterator<Long> iter = active.errorCodes.iterator();
-                        for(int i=0; i<codes.length; i++)
-                        {
-                            codes[i] = iter.next();
-                        }
-                        return codes;
-                    }
-
-                    @Override
-                    public String[] getErrorExceptions()
-                    {
-                        return active.exceptions.toArray(new String[active.exceptions.size()]);
-                    }
-                });
+                    state.setErrorCodes(codes);
+                }
+                if ( !active.exceptions.isEmpty() )
+                {
+                    state.setErrorExceptions(active.exceptions.toArray(new String[active.exceptions.size()]));
+                }
             }
             for(final Map.Entry<Integer, ErrorRegistration> entry : inactive.entrySet())
             {
-                failureServletStates.add(new FailureServletState()
+                Map<Integer, FailureServletState> failureStates = failureServletStates.get(status.handler.getServletInfo().getServiceId());
+                if ( failureStates == null )
                 {
+                    failureStates = new HashMap<Integer, FailureServletState>();
+                    failureServletStates.put(status.handler.getServletInfo().getServiceId(), failureStates);
+                }
 
-                    @Override
-                    public Servlet getServlet()
+                FailureServletState state = failureStates.get(entry.getKey());
+                if ( state == null )
+                {
+                    state = new FailureServletState(status.handler, entry.getKey());
+                    failureStates.put(entry.getKey(), state);
+                }
+                if ( !entry.getValue().errorCodes.isEmpty() )
+                {
+                    final long[] codes = new long[entry.getValue().errorCodes.size()];
+                    final Iterator<Long> iter = entry.getValue().errorCodes.iterator();
+                    for(int i=0; i<codes.length; i++)
                     {
-                        return status.handler.getServlet();
+                        codes[i] = iter.next();
                     }
-
-                    @Override
-                    public ServletInfo getServletInfo()
-                    {
-                        return status.handler.getServletInfo();
-                    }
-
-                    @Override
-                    public String[] getPatterns()
-                    {
-                        return null;
-                    }
-
-                    @Override
-                    public long[] getErrorCodes()
-                    {
-                        final long[] codes = new long[entry.getValue().errorCodes.size()];
-                        final Iterator<Long> iter = entry.getValue().errorCodes.iterator();
-                        for(int i=0; i<codes.length; i++)
-                        {
-                            codes[i] = iter.next();
-                        }
-                        return codes;
-                    }
-
-                    @Override
-                    public String[] getErrorExceptions()
-                    {
-                        return entry.getValue().exceptions.toArray(new String[entry.getValue().exceptions.size()]);
-                    }
-
-                    @Override
-                    public long getReason()
-                    {
-                        return entry.getKey();
-                    }
-
-                });
+                    state.setErrorCodes(codes);
+                }
+                if ( !entry.getValue().exceptions.isEmpty() )
+                {
+                    state.setErrorExceptions(entry.getValue().exceptions.toArray(new String[entry.getValue().exceptions.size()]));
+                }
             }
         }
     }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java
index b69cac8..63c18c5 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java
@@ -53,7 +53,7 @@
             return handler.getFilterInfo();
         }
         @Override
-        public long getReason() {
+        public int getReason() {
             return result;
         }
     }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
index 937a963..bf0d4f7 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
@@ -17,6 +17,8 @@
 package org.apache.felix.http.base.internal.registry;
 
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.TreeSet;
 
 import javax.annotation.Nonnull;
@@ -192,22 +194,30 @@
 
     public ContextRuntime getRuntime()
     {
+        // collect filters
         final Collection<FilterState> filterRuntimes = new TreeSet<FilterState>(FilterState.COMPARATOR);
         final Collection<FailureFilterState> failureFilterRuntimes = new TreeSet<FailureFilterState>(FailureFilterState.COMPARATOR);
         this.filterRegistry.getRuntimeInfo(filterRuntimes, failureFilterRuntimes);
 
-        final Collection<ServletState> errorPageRuntimes = new TreeSet<ServletState>(ServletState.COMPARATOR);
-        final Collection<FailureServletState> failureErrorPageRuntimes = new TreeSet<FailureServletState>(FailureServletState.COMPARATOR);
-        this.errorPageRegistry.getRuntimeInfo(errorPageRuntimes, failureErrorPageRuntimes);
-        // TODO - add servlets
-        // TODO - add failures from filters and error pages
+        // collect error pages
+        final Map<Long, ServletState> servletStates = new HashMap<Long, ServletState>();
+        final Map<Long, Map<Integer, FailureServletState>> failureServletStates = new HashMap<Long, Map<Integer,FailureServletState>>();
+        this.errorPageRegistry.getRuntimeInfo(servletStates, failureServletStates);
+
+        // collect servlets and resources
+        this.servletRegistry.getRuntimeInfo(servletStates, failureServletStates);
+
+        final Collection<ServletState> sortedServletStates = new TreeSet<ServletState>(ServletState.COMPARATOR);
+        sortedServletStates.addAll(servletStates.values());
+        final Collection<FailureServletState> sortedFailureServletStates = new TreeSet<FailureServletState>(ServletState.COMPARATOR);
+        for(final Map<Integer, FailureServletState> val : failureServletStates.values())
+        {
+            sortedFailureServletStates.addAll(val.values());
+        }
+
         return new ContextRuntime(filterRuntimes,
-                errorPageRuntimes,
-                null,
-                null,
+                sortedServletStates,
                 failureFilterRuntimes,
-                failureErrorPageRuntimes,
-                null,
-                null);
+                sortedFailureServletStates);
     }
 }
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 745eae0..dbcf29d 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
@@ -29,6 +29,8 @@
 
 import org.apache.felix.http.base.internal.handler.ServletHandler;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.apache.felix.http.base.internal.runtime.dto.state.FailureServletState;
+import org.apache.felix.http.base.internal.runtime.dto.state.ServletState;
 import org.apache.felix.http.base.internal.util.PatternUtil;
 import org.osgi.service.http.runtime.dto.DTOConstants;
 
@@ -52,28 +54,12 @@
 
     private final Map<ServletInfo, ServletRegistrationStatus> statusMapping = new ConcurrentHashMap<ServletInfo, ServletRegistry.ServletRegistrationStatus>();
 
-    private final Map<String, List<ServletNameStatus>> servletsByName = new ConcurrentHashMap<String, List<ServletNameStatus>>();
-
-    private static final class ServletNameStatus implements Comparable<ServletNameStatus>
-    {
-        public volatile boolean isActive = false;
-        public final ServletHandler handler;
-
-        public ServletNameStatus(final ServletHandler h)
-        {
-            this.handler = h;
-        }
-
-        @Override
-        public int compareTo(final ServletNameStatus o)
-        {
-            return handler.compareTo(o.handler);
-        }
-    }
+    private final Map<String, List<ServletHandler>> servletsByName = new ConcurrentHashMap<String, List<ServletHandler>>();
 
     public static final class ServletRegistrationStatus
     {
         public final Map<String, Integer> pathToStatus = new ConcurrentHashMap<String, Integer>();
+        public ServletHandler handler;
     }
 
     public PathResolution resolve(final String relativeRequestURI)
@@ -104,7 +90,9 @@
         if ( handler.getServletInfo().getPatterns() != null )
         {
             final ServletRegistrationStatus status = new ServletRegistrationStatus();
+            status.handler = handler;
 
+            boolean isActive = false;
             for(final String pattern : handler.getServletInfo().getPatterns())
             {
                 final ServletRegistration regHandler = this.activeServletMappings.get(pattern);
@@ -115,10 +103,16 @@
                         // replace if no error with new servlet
                         if ( this.tryToActivate(pattern, handler, status) )
                         {
-//                            nameStatus.isActive = true;
+                            isActive = true;
+                            final String oldName = regHandler.getServletHandler().getName();
                             regHandler.getServletHandler().destroy();
 
                             this.addToInactiveList(pattern, regHandler.getServletHandler(), this.statusMapping.get(regHandler.getServletHandler().getServletInfo()));
+
+                            if ( regHandler.getServletHandler().getServlet() == null )
+                            {
+                                removeFromNameMapping(oldName, regHandler.getServletHandler());
+                            }
                         }
                     }
                     else
@@ -132,11 +126,60 @@
                     // add to active
                     if ( this.tryToActivate(pattern, handler, status) )
                     {
-//                        nameStatus.isActive = true;
+                        isActive = true;
                     }
                 }
             }
             this.statusMapping.put(handler.getServletInfo(), status);
+            if ( isActive )
+            {
+                addToNameMapping(handler);
+            }
+        }
+    }
+
+    private void addToNameMapping(final ServletHandler handler)
+    {
+        final String servletName = handler.getName();
+        List<ServletHandler> list = this.servletsByName.get(servletName);
+        if ( list == null )
+        {
+            list = new ArrayList<ServletHandler>();
+            list.add(handler);
+        }
+        else
+        {
+            list = new ArrayList<ServletHandler>(list);
+            list.add(handler);
+            Collections.sort(list);
+        }
+        this.servletsByName.put(servletName, list);
+    }
+
+    private void removeFromNameMapping(final String servletName, final ServletHandler handler)
+    {
+        List<ServletHandler> list = this.servletsByName.get(servletName);
+        if ( list != null )
+        {
+            final List<ServletHandler> newList = new ArrayList<ServletHandler>(list);
+            final Iterator<ServletHandler> i = newList.iterator();
+            while ( i.hasNext() )
+            {
+                final ServletHandler s = i.next();
+                if ( s == handler )
+                {
+                    i.remove();
+                    break;
+                }
+            }
+            if ( newList.isEmpty() )
+            {
+                this.servletsByName.remove(servletName);
+            }
+            else
+            {
+                this.servletsByName.put(servletName, newList);
+            }
         }
     }
 
@@ -149,15 +192,16 @@
         if ( info.getPatterns() != null )
         {
             this.statusMapping.remove(info);
-            ServletHandler cleanuphandler = null;
+            ServletHandler cleanupHandler = null;
 
             for(final String pattern : info.getPatterns())
             {
-
                 final ServletRegistration regHandler = this.activeServletMappings.get(pattern);
                 if ( regHandler != null && regHandler.getServletHandler().getServletInfo().equals(info) )
                 {
-                    cleanuphandler = regHandler.getServletHandler();
+                    cleanupHandler = regHandler.getServletHandler();
+                    removeFromNameMapping(cleanupHandler.getName(), cleanupHandler);
+
                     final List<ServletHandler> inactiveList = this.inactiveServletMappings.get(pattern);
                     if ( inactiveList == null )
                     {
@@ -169,11 +213,19 @@
                         while ( !done )
                         {
                             final ServletHandler h = inactiveList.remove(0);
+                            boolean activate = h.getServlet() == null;
                             done = this.tryToActivate(pattern, h, this.statusMapping.get(h.getServletInfo()));
                             if ( !done )
                             {
                                 done = inactiveList.isEmpty();
                             }
+                            else
+                            {
+                                if ( activate )
+                                {
+                                    this.addToNameMapping(h);
+                                }
+                            }
                         }
                         if ( inactiveList.isEmpty() )
                         {
@@ -193,7 +245,7 @@
                             if ( h.getServletInfo().equals(info) )
                             {
                                 i.remove();
-                                cleanuphandler = h;
+                                cleanupHandler = h;
                                 break;
                             }
                         }
@@ -205,9 +257,9 @@
                 }
             }
 
-            if ( cleanuphandler != null )
+            if ( cleanupHandler != null )
             {
-                cleanuphandler.dispose();
+                cleanupHandler.dispose();
             }
         }
     }
@@ -247,22 +299,78 @@
         }
     }
 
-    public Map<ServletInfo, ServletRegistrationStatus> getServletStatusMapping()
+    Map<ServletInfo, ServletRegistrationStatus> getServletStatusMapping()
     {
         return this.statusMapping;
     }
 
-    public ServletHandler resolveByName(@Nonnull String name)
+    public ServletHandler resolveByName(final @Nonnull String name)
     {
-        final List<ServletNameStatus> handlerList = this.servletsByName.get(name);
+        final List<ServletHandler> handlerList = this.servletsByName.get(name);
         if ( handlerList != null )
         {
-            final ServletNameStatus status = handlerList.get(0);
-            if ( status != null && status.isActive )
-            {
-                return status.handler;
-            }
+            return handlerList.get(0);
         }
         return null;
     }
+
+    public void getRuntimeInfo(final Map<Long, ServletState> servletStates,
+            final Map<Long, Map<Integer, FailureServletState>> failureServletStates)
+    {
+        // TODO we could already do some pre calculation in the ServletRegistrationStatus
+        for(final Map.Entry<ServletInfo, ServletRegistrationStatus> entry : statusMapping.entrySet())
+        {
+            final long serviceId = entry.getKey().getServiceId();
+            for(final Map.Entry<String, Integer> map : entry.getValue().pathToStatus.entrySet())
+            {
+                if ( map.getValue() == - 1)
+                {
+                    ServletState state = servletStates.get(serviceId);
+                    if ( state == null )
+                    {
+                        state = new ServletState(entry.getValue().handler);
+                        servletStates.put(serviceId, state);
+                    }
+                    String[] patterns = state.getPatterns();
+                    if ( patterns.length ==  0 )
+                    {
+                        state.setPatterns(new String[] {map.getKey()});
+                    }
+                    else
+                    {
+                        patterns = new String[patterns.length + 1];
+                        System.arraycopy(state.getPatterns(), 0, patterns, 0, patterns.length - 1);
+                        patterns[patterns.length - 1] = map.getKey();
+                    }
+                }
+                else
+                {
+                    Map<Integer, FailureServletState> fmap = failureServletStates.get(serviceId);
+                    if ( fmap == null )
+                    {
+                        fmap = new HashMap<Integer, FailureServletState>();
+                        failureServletStates.put(serviceId, fmap);
+                    }
+                    FailureServletState state = fmap.get(map.getValue());
+                    if ( state == null )
+                    {
+                        state = new FailureServletState(entry.getValue().handler, map.getValue());
+                        fmap.put(map.getValue(), state);
+                    }
+                    String[] patterns = state.getPatterns();
+                    if ( patterns.length ==  0 )
+                    {
+                        state.setPatterns(new String[] {map.getKey()});
+                    }
+                    else
+                    {
+                        patterns = new String[patterns.length + 1];
+                        System.arraycopy(state.getPatterns(), 0, patterns, 0, patterns.length - 1);
+                        patterns[patterns.length - 1] = map.getKey();
+                    }
+                }
+
+            }
+        }
+    }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ContextRuntime.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ContextRuntime.java
index 08010c1..dfe2d29 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ContextRuntime.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ContextRuntime.java
@@ -31,32 +31,20 @@
 public final class ContextRuntime
 {
     private final Collection<FilterState> filterRuntimes;
-    private final Collection<ServletState> errorPageRuntimes;
     private final Collection<ServletState> servletRuntimes;
-    private final Collection<ServletState> resourceRuntimes;
 
     private final Collection<FailureFilterState> failureFilterRuntimes;
-    private final Collection<FailureServletState> failureErrorPageRuntimes;
     private final Collection<FailureServletState> failureServletRuntimes;
-    private final Collection<FailureServletState> failureResourceRuntimes;
 
     public ContextRuntime(final Collection<FilterState> filterRuntimes,
-            final Collection<ServletState> errorPageRuntimes,
             final Collection<ServletState> servletRuntimes,
-            final Collection<ServletState> resourceRuntimes,
             final Collection<FailureFilterState> failureFilterRuntimes,
-            final Collection<FailureServletState> failureErrorPageRuntimes,
-            final Collection<FailureServletState> failureServletRuntimes,
-            final Collection<FailureServletState> failureResourceRuntimes)
+            final Collection<FailureServletState> failureServletRuntimes)
     {
         this.filterRuntimes = filterRuntimes;
-        this.errorPageRuntimes = errorPageRuntimes;
         this.servletRuntimes = servletRuntimes;
-        this.resourceRuntimes = resourceRuntimes;
         this.failureFilterRuntimes = failureFilterRuntimes;
-        this.failureErrorPageRuntimes = failureErrorPageRuntimes;
         this.failureServletRuntimes = failureServletRuntimes;
-        this.failureResourceRuntimes = failureResourceRuntimes;
     }
 
     Collection<ServletState> getServletRuntimes()
@@ -64,38 +52,18 @@
         return servletRuntimes;
     }
 
-    Collection<ServletState> getResourceRuntimes()
-    {
-        return resourceRuntimes;
-    }
-
     Collection<FilterState> getFilterRuntimes()
     {
         return filterRuntimes;
     }
 
-    Collection<ServletState> getErrorPageRuntimes()
-    {
-        return errorPageRuntimes;
-    }
-
     Collection<FailureServletState> getFailureServletRuntimes()
     {
         return failureServletRuntimes;
     }
 
-    Collection<FailureServletState> getFailureResourceRuntimes()
-    {
-        return failureResourceRuntimes;
-    }
-
     Collection<FailureFilterState> getFailureFilterRuntimes()
     {
         return failureFilterRuntimes;
     }
-
-    Collection<FailureServletState> getFailureErrorPageRuntimes()
-    {
-        return failureErrorPageRuntimes;
-    }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ErrorPageDTOBuilder.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ErrorPageDTOBuilder.java
index 8cd2c35..89ecac9 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ErrorPageDTOBuilder.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ErrorPageDTOBuilder.java
@@ -18,6 +18,10 @@
  */
 package org.apache.felix.http.base.internal.runtime.dto;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
 import org.apache.felix.http.base.internal.runtime.dto.state.ServletState;
 import org.osgi.service.http.runtime.dto.ErrorPageDTO;
 
@@ -34,6 +38,20 @@
     }
 
     @Override
+    Collection<T> build(Collection<? extends ServletState> whiteboardServices,
+            long servletContextId) {
+        List<T> dtoList = new ArrayList<T>();
+        for (ServletState whiteboardService : whiteboardServices)
+        {
+            if ( whiteboardService.getErrorCodes().length > 0 || whiteboardService.getErrorExceptions().length > 0 )
+            {
+                dtoList.add(buildDTO(whiteboardService, servletContextId));
+            }
+        }
+        return dtoList;
+    }
+
+    @Override
     T buildDTO(ServletState errorPage, long servletConextId)
     {
         T errorPageDTO = super.buildDTO(errorPage, servletConextId);
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailureRuntime.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailureRuntime.java
index bf9fc35..5a61148 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailureRuntime.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailureRuntime.java
@@ -26,19 +26,24 @@
 import static org.apache.felix.http.base.internal.runtime.dto.BuilderConstants.SERVLET_FAILURE_DTO_ARRAY;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
+import javax.servlet.ServletContext;
+
+import org.apache.felix.http.base.internal.registry.ErrorPageRegistry;
 import org.apache.felix.http.base.internal.runtime.AbstractInfo;
 import org.apache.felix.http.base.internal.runtime.FilterInfo;
 import org.apache.felix.http.base.internal.runtime.ListenerInfo;
 import org.apache.felix.http.base.internal.runtime.ResourceInfo;
 import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
-import org.apache.felix.http.base.internal.runtime.dto.state.FilterState;
-import org.apache.felix.http.base.internal.runtime.dto.state.ServletState;
+import org.apache.felix.http.base.internal.runtime.dto.state.FailureFilterState;
+import org.apache.felix.http.base.internal.runtime.dto.state.FailureServletState;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.runtime.dto.FailedErrorPageDTO;
 import org.osgi.service.http.runtime.dto.FailedFilterDTO;
@@ -49,10 +54,7 @@
 
 public final class FailureRuntime
 {
-    private static final FailureComparator<ServletState> ERROR_PAGE_COMPARATOR = FailureComparator.<ServletState>create(ServletState.COMPARATOR);
-    private static final FailureComparator<FilterState> FILTER_COMPARATOR = FailureComparator.create(FilterState.COMPARATOR);
     private static final FailureComparator<ServletContextHelperRuntime> CONTEXT_COMPARATOR = FailureComparator.create(ServletContextHelperRuntime.COMPARATOR);
-    private static final FailureComparator<ServletState> SERVLET_COMPARATOR = FailureComparator.create(ServletState.COMPARATOR);
     private static final Comparator<Failure<ServiceReference<?>>> REFERENCE_COMPARATOR = new Comparator<Failure<ServiceReference<?>>>()
     {
         @Override
@@ -63,18 +65,18 @@
     };
 
     private final List<Failure<ServletContextHelperRuntime>> contextRuntimes;
-    private final List<Failure<ServletState>> servletRuntimes;
-    private final List<Failure<FilterState>> filterRuntimes;
-    private final List<Failure<ServletState>> resourceRuntimes;
-    private final List<Failure<ServletState>> errorPageRuntimes;
+    private final List<FailureServletState> servletRuntimes;
+    private final List<FailureFilterState> filterRuntimes;
+    private final List<FailureServletState> resourceRuntimes;
+    private final List<FailureServletState> errorPageRuntimes;
     private final List<Failure<ServiceReference<?>>> listenerRuntimes;
 
     private FailureRuntime(List<Failure<ServletContextHelperRuntime>> contextRuntimes,
             List<Failure<ServiceReference<?>>> listenerRuntimes,
-            List<Failure<ServletState>> servletRuntimes,
-            List<Failure<FilterState>> filterRuntimes,
-            List<Failure<ServletState>> resourceRuntimes,
-            List<Failure<ServletState>> errorPageRuntimes)
+            List<FailureServletState> servletRuntimes,
+            List<FailureFilterState> filterRuntimes,
+            List<FailureServletState> resourceRuntimes,
+            List<FailureServletState> errorPageRuntimes)
     {
         this.contextRuntimes = contextRuntimes;
         this.servletRuntimes = servletRuntimes;
@@ -84,16 +86,6 @@
         this.errorPageRuntimes = errorPageRuntimes;
     }
 
-    public static FailureRuntime empty()
-    {
-        return new FailureRuntime(Collections.<Failure<ServletContextHelperRuntime>>emptyList(),
-                Collections.<Failure<ServiceReference<?>>>emptyList(),
-                Collections.<Failure<ServletState>>emptyList(),
-                Collections.<Failure<FilterState>>emptyList(),
-                Collections.<Failure<ServletState>>emptyList(),
-                Collections.<Failure<ServletState>>emptyList());
-    }
-
     public static FailureRuntime.Builder builder()
     {
         return new Builder();
@@ -101,73 +93,73 @@
 
     public FailedServletDTO[] getServletDTOs()
     {
-        List<FailedServletDTO> servletDTOs = new ArrayList<FailedServletDTO>();
-        for (Failure<ServletState> failure : servletRuntimes)
+        final List<FailedServletDTO> servletDTOs = new ArrayList<FailedServletDTO>();
+        for (final FailureServletState failure : servletRuntimes)
         {
-            servletDTOs.add(getServletDTO(failure.service, failure.failureCode));
+            servletDTOs.add(getServletDTO(failure));
         }
         return servletDTOs.toArray(SERVLET_FAILURE_DTO_ARRAY);
     }
 
-    private FailedServletDTO getServletDTO(ServletState failedServlet, int failureCode)
+    private FailedServletDTO getServletDTO(FailureServletState failedServlet)
     {
         ServletDTOBuilder<FailedServletDTO> dtoBuilder = new ServletDTOBuilder<FailedServletDTO>(DTOFactories.FAILED_SERVLET);
         FailedServletDTO servletDTO = dtoBuilder.buildDTO(failedServlet, 0);
-        servletDTO.failureReason = failureCode;
+        servletDTO.failureReason = failedServlet.getReason();
         return servletDTO;
     }
 
     public FailedFilterDTO[] getFilterDTOs()
     {
         List<FailedFilterDTO> filterDTOs = new ArrayList<FailedFilterDTO>();
-        for (Failure<FilterState> failure : filterRuntimes)
+        for (FailureFilterState failure : filterRuntimes)
         {
-            filterDTOs.add(getFilterDTO(failure.service, failure.failureCode));
+            filterDTOs.add(getFilterDTO(failure));
         }
         return filterDTOs.toArray(FILTER_FAILURE_DTO_ARRAY);
     }
 
-    private FailedFilterDTO getFilterDTO(FilterState failedFilter, int failureCode)
+    private FailedFilterDTO getFilterDTO(FailureFilterState failedFilter)
     {
         FilterDTOBuilder<FailedFilterDTO> dtoBuilder = new FilterDTOBuilder<FailedFilterDTO>(DTOFactories.FAILED_FILTER);
         FailedFilterDTO filterDTO = dtoBuilder.buildDTO(failedFilter, 0);
-        filterDTO.failureReason = failureCode;
+        filterDTO.failureReason = failedFilter.getReason();
         return filterDTO;
     }
 
     public FailedResourceDTO[] getResourceDTOs()
     {
         List<FailedResourceDTO> resourceDTOs = new ArrayList<FailedResourceDTO>();
-        for (Failure<ServletState> failure : resourceRuntimes)
+        for (FailureServletState failure : resourceRuntimes)
         {
-            resourceDTOs.add(getResourceDTO(failure.service, failure.failureCode));
+            resourceDTOs.add(getResourceDTO(failure));
         }
         return resourceDTOs.toArray(RESOURCE_FAILURE_DTO_ARRAY);
     }
 
-    private FailedResourceDTO getResourceDTO(ServletState failedResource, int failureCode)
+    private FailedResourceDTO getResourceDTO(FailureServletState failedResource)
     {
         ResourceDTOBuilder<FailedResourceDTO> dtoBuilder = new ResourceDTOBuilder<FailedResourceDTO>(DTOFactories.FAILED_RESOURCE);
         FailedResourceDTO resourceDTO = dtoBuilder.buildDTO(failedResource, 0);
-        resourceDTO.failureReason = failureCode;
+        resourceDTO.failureReason = failedResource.getReason();
         return resourceDTO;
     }
 
     public FailedErrorPageDTO[] getErrorPageDTOs()
     {
         List<FailedErrorPageDTO> errorPageDTOs = new ArrayList<FailedErrorPageDTO>();
-        for (Failure<ServletState> failure : errorPageRuntimes)
+        for (FailureServletState failure : errorPageRuntimes)
         {
-            errorPageDTOs.add(getErrorPageDTO(failure.service, failure.failureCode));
+            errorPageDTOs.add(getErrorPageDTO(failure));
         }
         return errorPageDTOs.toArray(ERROR_PAGE_FAILURE_DTO_ARRAY);
     }
 
-    private FailedErrorPageDTO getErrorPageDTO(ServletState failedErrorPage, int failureCode)
+    private FailedErrorPageDTO getErrorPageDTO(FailureServletState failedErrorPage)
     {
         ErrorPageDTOBuilder<FailedErrorPageDTO> dtoBuilder = new ErrorPageDTOBuilder<FailedErrorPageDTO>(DTOFactories.FAILED_ERROR_PAGE);
         FailedErrorPageDTO errorPageDTO = dtoBuilder.buildDTO(failedErrorPage, 0);
-        errorPageDTO.failureReason = failureCode;
+        errorPageDTO.failureReason = failedErrorPage.getReason();
         return errorPageDTO;
     }
 
@@ -210,10 +202,10 @@
     public static class Builder
     {
         private final List<Failure<ServletContextHelperRuntime>> contextRuntimes = new ArrayList<FailureRuntime.Failure<ServletContextHelperRuntime>>();
-        private final List<Failure<ServletState>> servletRuntimes = new ArrayList<Failure<ServletState>>();
-        private final List<Failure<FilterState>> filterRuntimes = new ArrayList<Failure<FilterState>>();
-        private final List<Failure<ServletState>> resourceRuntimes = new ArrayList<Failure<ServletState>>();
-        private final List<Failure<ServletState>> errorPageRuntimes = new ArrayList<Failure<ServletState>>();
+        private final List<FailureServletState> servletRuntimes = new ArrayList<FailureServletState>();
+        private final List<FailureFilterState> filterRuntimes = new ArrayList<FailureFilterState>();
+        private final List<FailureServletState> resourceRuntimes = new ArrayList<FailureServletState>();
+        private final List<FailureServletState> errorPageRuntimes = new ArrayList<FailureServletState>();
         private final List<Failure<ServiceReference<?>>> listenerRuntimes = new ArrayList<Failure<ServiceReference<?>>>();
 
         public FailureRuntime.Builder add(Map<AbstractInfo<?>, Integer> failureInfos)
@@ -225,37 +217,91 @@
             return this;
         }
 
-        public FailureRuntime.Builder add(AbstractInfo<?> info, int failureCode)
+        private FailureRuntime.Builder add(final AbstractInfo<?> info, final int failureCode)
         {
             if (info instanceof ServletContextHelperInfo)
             {
-                // TODO
-//                ServletContextHelperRuntime servletRuntime = new InfoServletContextHelperRuntime((ServletContextHelperInfo) info);
-//                contextRuntimes.add(new Failure<ServletContextHelperRuntime>(servletRuntime, failureCode));
+                ServletContextHelperRuntime servletRuntime = new ServletContextHelperRuntime()
+                {
+
+                    @Override
+                    public ServletContext getSharedContext() {
+                        return null;
+                    }
+
+                    @Override
+                    public ServletContextHelperInfo getContextInfo() {
+                        return (ServletContextHelperInfo) info;
+                    }
+
+                    @Override
+                    public ContextRuntime getContextRuntime() {
+                        return null;
+                    }
+
+                    @Override
+                    public Collection<ServiceReference<?>> getListeners() {
+                        return null;
+                    }
+                };
+                contextRuntimes.add(new Failure<ServletContextHelperRuntime>(servletRuntime, failureCode));
             }
-            else if (info instanceof ServletInfo && ((ServletInfo) info).getErrorPage() != null)
+            else if (info instanceof ServletInfo )
             {
-                // TODO
-//                FailureServletState servletRuntime = new FailureServletRuntime((ServletInfo) info);
-//                ErrorPageRuntime errorPageRuntime = ErrorPageRuntime.fromServletRuntime(servletRuntime);
-//                errorPageRuntimes.add(new Failure<ErrorPageRuntime>(errorPageRuntime, failureCode));
-            }
-            else if (info instanceof ServletInfo)
-            {
-                // TODO
-//                ServletState servletRuntime = new FailureServletState((ServletInfo) info);
-//                servletRuntimes.add(new Failure<ServletRuntime>(servletRuntime, failureCode));
+                boolean isError = false;
+                if ( ((ServletInfo) info).getErrorPage() != null)
+                {
+                    isError = true;
+                    final FailureServletState servletRuntime = new FailureServletState((ServletInfo) info, failureCode);
+                    ErrorPageRegistry.ErrorRegistration  reg = ErrorPageRegistry.getErrorRegistration((ServletInfo)info);
+                    if ( !reg.errorCodes.isEmpty() )
+                    {
+                        final long[] codes = new long[reg.errorCodes.size()];
+                        int index = 0;
+                        final Iterator<Long> i = reg.errorCodes.iterator();
+                        while ( i.hasNext() )
+                        {
+                            codes[index++] = i.next();
+                        }
+                        servletRuntime.setErrorCodes(codes);
+                    }
+                    if ( !reg.exceptions.isEmpty() )
+                    {
+                        servletRuntime.setErrorExceptions(reg.exceptions.toArray(new String[reg.exceptions.size()]));
+                    }
+                    errorPageRuntimes.add(servletRuntime);
+                }
+                if ( ((ServletInfo) info).getPatterns() != null || !isError )
+                {
+                    FailureServletState servletRuntime = new FailureServletState((ServletInfo) info, failureCode);
+                    if ( ((ServletInfo) info).getPatterns() != null )
+                    {
+                        servletRuntime.setPatterns(((ServletInfo) info).getPatterns());
+                    }
+                    servletRuntimes.add(servletRuntime);
+                }
             }
             else if (info instanceof FilterInfo)
             {
-                // TODO
-//                FilterState filterRuntime = new FailureFilterState((FilterInfo) info, failureCode);
-//                filterRuntimes.add(new Failure<FilterState>(filterRuntime, failureCode));
+                FailureFilterState filterRuntime = new FailureFilterState() {
+
+                    @Override
+                    public FilterInfo getFilterInfo() {
+                        return (FilterInfo)info;
+                    }
+
+                    @Override
+                    public int getReason() {
+                        return failureCode;
+                    }
+
+                };
+                filterRuntimes.add(filterRuntime);
             }
             else if (info instanceof ResourceInfo)
             {
-//                ServletState servletRuntime = new FailureServletRuntime(new ServletInfo((ResourceInfo) info));
-//                resourceRuntimes.add(new Failure<ServletRuntime>(servletRuntime, failureCode));
+                FailureServletState servletRuntime = new FailureServletState(new ServletInfo((ResourceInfo) info), failureCode);
+                resourceRuntimes.add(servletRuntime);
             }
             else if (info instanceof ListenerInfo)
             {
@@ -273,10 +319,10 @@
         {
             Collections.sort(contextRuntimes, CONTEXT_COMPARATOR);
             Collections.sort(listenerRuntimes, REFERENCE_COMPARATOR);
-            Collections.sort(servletRuntimes, SERVLET_COMPARATOR);
-            Collections.sort(filterRuntimes, FILTER_COMPARATOR);
-            Collections.sort(resourceRuntimes, SERVLET_COMPARATOR);
-            Collections.sort(errorPageRuntimes, ERROR_PAGE_COMPARATOR);
+            Collections.sort(servletRuntimes, FailureServletState.COMPARATOR);
+            Collections.sort(filterRuntimes, FailureFilterState.COMPARATOR);
+            Collections.sort(resourceRuntimes, FailureServletState.COMPARATOR);
+            Collections.sort(errorPageRuntimes, FailureServletState.COMPARATOR);
 
             return new FailureRuntime(contextRuntimes,
                     listenerRuntimes,
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RegistryRuntime.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RegistryRuntime.java
index 08a1341..1c4e6c9 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RegistryRuntime.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RegistryRuntime.java
@@ -18,13 +18,7 @@
  */
 package org.apache.felix.http.base.internal.runtime.dto;
 
-import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME;
-
 import java.util.Collection;
-import java.util.Collections;
-
-import org.apache.felix.http.base.internal.runtime.dto.state.ServletState;
-import org.osgi.framework.ServiceReference;
 
 public final class RegistryRuntime
 {
@@ -38,61 +32,6 @@
         this.failureRuntime = failureRuntime;
     }
 
-
-
-    public ContextRuntime getHandlerRuntime(ServletContextHelperRuntime contextRuntime)
-    {
-        long serviceId = contextRuntime.getContextInfo().getServiceId();
-/**
-        if (handlerRuntimes.containsKey(serviceId) && isDefaultContext(contextRuntime))
-        {
-            // TODO Merge with the default context of the HttpService ( handlerRuntimes.get(0) )
-            return handlerRuntimes.get(serviceId);
-        }
-        else if (handlerRuntimes.containsKey(serviceId))
-        {
-            return handlerRuntimes.get(serviceId);
-        }**/
-        return null; //ContextRuntime.empty(serviceId);
-    }
-
-    public Collection<ServletState> getServletRuntimes(ServletContextHelperRuntime contextRuntime)
-    {
-        /* TODO
-        if (servletRuntimes.containsKey(contextRuntime.getContextInfo().getServiceId()))
-        {
-            return servletRuntimes.get(contextRuntime.getContextInfo().getServiceId());
-        }
-        */
-        return Collections.emptyList();
-    }
-
-    public Collection<ServletState> getResourceRuntimes(ServletContextHelperRuntime contextRuntime)
-    {
-        /* TODO
-        if (resourceRuntimes.containsKey(contextRuntime.getContextInfo().getServiceId()))
-        {
-            return resourceRuntimes.get(contextRuntime.getContextInfo().getServiceId());
-        }
-        */
-        return Collections.emptyList();
-    }
-
-    private boolean isDefaultContext(ServletContextHelperRuntime contextRuntime)
-    {
-        return contextRuntime.getContextInfo().getName().equals(HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME);
-    }
-
-    public Collection<ServiceReference<?>> getListenerRuntimes(ServletContextHelperRuntime contextRuntime)
-    {
-        /**
-        if (listenerRuntimes.containsKey(contextRuntime.getContextInfo().getServiceId()))
-        {
-            return listenerRuntimes.get(contextRuntime.getContextInfo().getServiceId());
-        }*/
-        return Collections.emptyList();
-    }
-
     public Collection<ServletContextHelperRuntime> getContexts()
     {
         return contexts;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RequestInfoDTOBuilder.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RequestInfoDTOBuilder.java
index e27f2c9..7250bdf 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RequestInfoDTOBuilder.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RequestInfoDTOBuilder.java
@@ -18,12 +18,9 @@
 
 import static java.util.Arrays.asList;
 
-import javax.servlet.Servlet;
-
 import org.apache.felix.http.base.internal.handler.FilterHandler;
 import org.apache.felix.http.base.internal.registry.HandlerRegistry;
 import org.apache.felix.http.base.internal.registry.PathResolution;
-import org.apache.felix.http.base.internal.runtime.ServletInfo;
 import org.apache.felix.http.base.internal.runtime.dto.state.ServletState;
 import org.osgi.service.http.runtime.dto.FilterDTO;
 import org.osgi.service.http.runtime.dto.RequestInfoDTO;
@@ -56,81 +53,18 @@
         requestInfoDTO.servletContextId = pr.handler.getContextServiceId();
         if (pr.handler.getServletInfo().isResource())
         {
+            final ServletState state = new ServletState(pr.handler);
+            state.setPatterns(pr.handler.getServletInfo().getPatterns());
             requestInfoDTO.resourceDTO = ResourceDTOBuilder.create()
-                    .buildDTO(new ServletState()
-                    {
-
-                        @Override
-                        public ServletInfo getServletInfo()
-                        {
-                            // TODO Auto-generated method stub
-                            return pr.handler.getServletInfo();
-                        }
-
-                        @Override
-                        public Servlet getServlet()
-                        {
-                            // TODO Auto-generated method stub
-                            return pr.handler.getServlet();
-                        }
-
-                        @Override
-                        public String[] getPatterns()
-                        {
-                            return pr.handler.getServletInfo().getPatterns();
-                        }
-
-                        @Override
-                        public String[] getErrorExceptions()
-                        {
-                            return null;
-                        }
-
-                        @Override
-                        public long[] getErrorCodes()
-                        {
-                            return null;
-                        }
-                    },
-
+                    .buildDTO(state,
                             pr.handler.getContextServiceId());
         }
         else
         {
+            final ServletState state = new ServletState(pr.handler);
+            state.setPatterns(pr.handler.getServletInfo().getPatterns());
             requestInfoDTO.servletDTO = ServletDTOBuilder.create()
-                    .buildDTO(new ServletState()
-                    {
-
-                        @Override
-                        public ServletInfo getServletInfo()
-                        {
-                            return pr.handler.getServletInfo();
-                        }
-
-                        @Override
-                        public Servlet getServlet()
-                        {
-                            return pr.handler.getServlet();
-                        }
-
-                        @Override
-                        public String[] getPatterns()
-                        {
-                            return pr.handler.getServletInfo().getPatterns();
-                        }
-
-                        @Override
-                        public String[] getErrorExceptions()
-                        {
-                            return new String[0];
-                        }
-
-                        @Override
-                        public long[] getErrorCodes()
-                        {
-                            return new long[0];
-                        }
-                    }, pr.handler.getContextServiceId());
+                    .buildDTO(state, pr.handler.getContextServiceId());
         }
 
         final FilterHandler[] filterHandlers = registry.getFilters(pr, null, path);
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ResourceDTOBuilder.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ResourceDTOBuilder.java
index 552e4ef..8aa815c 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ResourceDTOBuilder.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ResourceDTOBuilder.java
@@ -18,6 +18,10 @@
  */
 package org.apache.felix.http.base.internal.runtime.dto;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
 import org.apache.felix.http.base.internal.runtime.dto.state.ServletState;
 import org.osgi.service.http.runtime.dto.ResourceDTO;
@@ -35,6 +39,20 @@
     }
 
     @Override
+    Collection<T> build(Collection<? extends ServletState> whiteboardServices,
+            long servletContextId) {
+        List<T> dtoList = new ArrayList<T>();
+        for (ServletState whiteboardService : whiteboardServices)
+        {
+            if ( whiteboardService.getPatterns().length > 0 && whiteboardService.getServletInfo().isResource() )
+            {
+                dtoList.add(buildDTO(whiteboardService, servletContextId));
+            }
+        }
+        return dtoList;
+    }
+
+    @Override
     T buildDTO(ServletState runtime, long servletContextId)
     {
         ServletInfo servletInfo = runtime.getServletInfo();
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RuntimeDTOBuilder.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RuntimeDTOBuilder.java
index e4794b7..ea12e78 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RuntimeDTOBuilder.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RuntimeDTOBuilder.java
@@ -22,8 +22,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.felix.http.base.internal.runtime.dto.state.FilterState;
-import org.apache.felix.http.base.internal.runtime.dto.state.ServletState;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
@@ -102,28 +100,22 @@
         for (final ServletContextHelperRuntime context : contexts)
         {
             result[index++] = createContextDTO(context,
-                    registry.getHandlerRuntime(context),
-                    registry.getServletRuntimes(context),
-                    registry.getResourceRuntimes(context),
-                    registry.getListenerRuntimes(context));
+                    context.getContextRuntime(),
+                    context.getListeners());
         }
         return result;
     }
 
-    private ServletContextDTO createContextDTO(ServletContextHelperRuntime context,
-            ContextRuntime contextRuntime,
-            Collection<ServletState> servletRuntimes,
-            Collection<ServletState> resourceRuntimes,
-            Collection<ServiceReference<?>> listenerRuntimes)
+    private ServletContextDTO createContextDTO(final ServletContextHelperRuntime context,
+            final ContextRuntime contextRuntime,
+            final Collection<ServiceReference<?>> listenerRuntimes)
     {
-        Collection<FilterState> filterRuntimes = contextRuntime.getFilterRuntimes();
-        Collection<ServletState> errorPageRuntimes = contextRuntime.getErrorPageRuntimes();
-        long servletContextId = context.getContextInfo().getServiceId();
+        final long servletContextId = context.getContextInfo().getServiceId();
 
-        Collection<ServletDTO> servletDTOs = ServletDTOBuilder.create().build(servletRuntimes, servletContextId);
-        Collection<ResourceDTO> resourceDTOs = ResourceDTOBuilder.create().build(resourceRuntimes, servletContextId);
-        Collection<FilterDTO> filterDTOs = FilterDTOBuilder.create().build(filterRuntimes, servletContextId);
-        Collection<ErrorPageDTO> errorDTOs = ErrorPageDTOBuilder.create().build(errorPageRuntimes, servletContextId);
+        Collection<ServletDTO> servletDTOs = ServletDTOBuilder.create().build(contextRuntime.getServletRuntimes(), servletContextId);
+        Collection<ResourceDTO> resourceDTOs = ResourceDTOBuilder.create().build(contextRuntime.getServletRuntimes(), servletContextId);
+        Collection<FilterDTO> filterDTOs = FilterDTOBuilder.create().build(contextRuntime.getFilterRuntimes(), servletContextId);
+        Collection<ErrorPageDTO> errorDTOs = ErrorPageDTOBuilder.create().build(contextRuntime.getServletRuntimes(), servletContextId);
         Collection<ListenerDTO> listenerDTOs = ListenerDTOBuilder.create().build(listenerRuntimes, servletContextId);
 
         return new ServletContextDTOBuilder(context,
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ServletDTOBuilder.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ServletDTOBuilder.java
index 94c8fa9..09dbab9 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ServletDTOBuilder.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ServletDTOBuilder.java
@@ -18,6 +18,10 @@
  */
 package org.apache.felix.http.base.internal.runtime.dto;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
 import org.apache.felix.http.base.internal.runtime.dto.state.ServletState;
 import org.osgi.service.http.runtime.dto.ServletDTO;
@@ -34,6 +38,21 @@
         super(dtoFactory);
     }
 
+
+    @Override
+    Collection<T> build(Collection<? extends ServletState> whiteboardServices,
+            long servletContextId) {
+        List<T> dtoList = new ArrayList<T>();
+        for (ServletState whiteboardService : whiteboardServices)
+        {
+            if ( whiteboardService.getPatterns().length > 0 && !whiteboardService.getServletInfo().isResource() )
+            {
+                dtoList.add(buildDTO(whiteboardService, servletContextId));
+            }
+        }
+        return dtoList;
+    }
+
     @Override
     T buildDTO(ServletState servletRuntime, long servletContextId)
     {
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/state/FailureFilterState.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/state/FailureFilterState.java
index 7147f04..918a7dd 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/state/FailureFilterState.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/state/FailureFilterState.java
@@ -21,5 +21,5 @@
 
 public interface FailureFilterState extends FilterState {
 
-    long getReason();
+    int getReason();
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/state/FailureServletState.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/state/FailureServletState.java
index d2ce336..4d1d8f0 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/state/FailureServletState.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/state/FailureServletState.java
@@ -18,8 +18,27 @@
  */
 package org.apache.felix.http.base.internal.runtime.dto.state;
 
+import org.apache.felix.http.base.internal.handler.ServletHandler;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
 
-public interface FailureServletState extends ServletState
+
+public class FailureServletState extends ServletState
 {
-    long getReason();
+    private final int reason;
+
+    public FailureServletState(final ServletHandler handler, final int reason)
+    {
+        super(handler);
+        this.reason = reason;
+    }
+
+    public FailureServletState(final ServletInfo info, final int reason)
+    {
+        super(info);
+        this.reason = reason;
+    }
+
+    public int getReason() {
+        return reason;
+    }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/state/ServletState.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/state/ServletState.java
index 517dd81..9a53d16 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/state/ServletState.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/state/ServletState.java
@@ -22,11 +22,15 @@
 
 import javax.servlet.Servlet;
 
+import org.apache.felix.http.base.internal.handler.ServletHandler;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
 
-public interface ServletState
+public class ServletState
 {
-    static final Comparator<ServletState> COMPARATOR = new Comparator<ServletState>()
+    private static final String[] EMPTY_STRING_ARRAY = new String[0];
+    private static final long[] EMPTY_LONG_ARRAY = new long[0];
+
+    public static final Comparator<ServletState> COMPARATOR = new Comparator<ServletState>()
     {
         @Override
         public int compare(ServletState o1, ServletState o2)
@@ -35,13 +39,65 @@
         }
     };
 
-    Servlet getServlet();
+    private final ServletHandler handler;
 
-    ServletInfo getServletInfo();
+    private final ServletInfo info;
 
-    String[] getPatterns();
+    private String[] patterns = EMPTY_STRING_ARRAY;
 
-    long[] getErrorCodes();
+    private String[] exceptions = EMPTY_STRING_ARRAY;
 
-    String[] getErrorExceptions();
+    private long[] errorCodes = EMPTY_LONG_ARRAY;
+
+    public ServletState(final ServletHandler handler)
+    {
+        this.handler = handler;
+        this.info = handler.getServletInfo();
+    }
+
+    public ServletState(final ServletInfo info)
+    {
+        this.handler = null;
+        this.info = info;
+    }
+
+    public Servlet getServlet()
+    {
+        return (handler != null ? this.handler.getServlet() : null);
+    }
+
+    public ServletInfo getServletInfo()
+    {
+        return this.info;
+    }
+
+    public String[] getPatterns()
+    {
+        return this.patterns;
+    }
+
+    public long[] getErrorCodes()
+    {
+        return this.errorCodes;
+    }
+
+    public String[] getErrorExceptions()
+    {
+        return this.exceptions;
+    }
+
+    public void setPatterns(final String[] value)
+    {
+        this.patterns = value;
+    }
+
+    public void setErrorCodes(final long[] value)
+    {
+        this.errorCodes = value;
+    }
+
+    public void setErrorExceptions(final String[] value)
+    {
+        this.exceptions = value;
+    }
 }
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/runtime/WhiteboardServiceHelper.java b/http/base/src/test/java/org/apache/felix/http/base/internal/runtime/WhiteboardServiceHelper.java
index 48b8668..f2486f0 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/runtime/WhiteboardServiceHelper.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/runtime/WhiteboardServiceHelper.java
@@ -98,19 +98,19 @@
         return info;
     }
 
-    public static ServletState createTestServletWithServiceId(String identifier,
+    public static ServletHandler createTestServletWithServiceId(String identifier,
             ExtServletContext context,
             long contextServiceId)
     {
         return createTestServlet(identifier, context, ID_COUNTER.incrementAndGet(), contextServiceId);
     }
 
-    public static ServletState createTestServlet(String identifier, ExtServletContext context, long contextServiceId)
+    public static ServletHandler createTestServlet(String identifier, ExtServletContext context, long contextServiceId)
     {
         return createTestServlet(identifier, context, -ID_COUNTER.incrementAndGet(), contextServiceId);
     }
 
-    private static ServletState createTestServlet(String identifier,
+    private static ServletHandler createTestServlet(String identifier,
             ExtServletContext context,
             Long serviceId,
             Long contextServiceId)
@@ -120,33 +120,7 @@
         when(servlet.getServletInfo()).thenReturn("info_" + identifier);
         final ServletHandler h = new HttpServiceServletHandler(contextServiceId, context, servletInfo, servlet);
 
-        return new ServletState() {
-
-            @Override
-            public ServletInfo getServletInfo() {
-                return h.getServletInfo();
-            }
-
-            @Override
-            public Servlet getServlet() {
-                return h.getServlet();
-            }
-
-            @Override
-            public String[] getPatterns() {
-                return h.getServletInfo().getPatterns();
-            }
-
-            @Override
-            public String[] getErrorExceptions() {
-                return null;
-            }
-
-            @Override
-            public long[] getErrorCodes() {
-                return null;
-            }
-        };
+        return h;
     }
 
     private static ServletInfo createServletInfo(String identifier, Long serviceId)
@@ -202,49 +176,20 @@
             Long serviceId,
             long contextServiceId)
     {
-        final ServletState servletHandler = createTestServlet(identifier, context, serviceId, contextServiceId);
+        final ServletHandler servletHandler = createTestServlet(identifier, context, serviceId, contextServiceId);
         final Collection<Long> errorCodes = Arrays.asList(400L, 500L);
         final Collection<String> exceptions = Arrays.asList("Bad request", "Error");
 
-        return new ServletState()
+        final ServletState state = new ServletState(servletHandler);
+        final long[] codes = new long[errorCodes.size()];
+        final Iterator<Long> iter = errorCodes.iterator();
+        for(int i=0; i<codes.length; i++)
         {
-
-            @Override
-            public ServletInfo getServletInfo()
-            {
-                return servletHandler.getServletInfo();
-            }
-
-            @Override
-            public Servlet getServlet()
-            {
-                return servletHandler.getServlet();
-            }
-
-            @Override
-            public String[] getPatterns()
-            {
-                return servletHandler.getPatterns();
-            }
-
-            @Override
-            public String[] getErrorExceptions()
-            {
-                return exceptions.toArray(new String[1]);
-            }
-
-            @Override
-            public long[] getErrorCodes()
-            {
-                final long[] codes = new long[errorCodes.size()];
-                final Iterator<Long> iter = errorCodes.iterator();
-                for(int i=0; i<codes.length; i++)
-                {
-                    codes[i] = iter.next();
-                }
-                return codes;
-            }
-        };
+            codes[i] = iter.next();
+        }
+        state.setErrorCodes(codes);
+        state.setErrorExceptions(exceptions.toArray(new String[exceptions.size()]));
+        return state;
     }
 
     public static ServletContextHelperInfo createContextInfo(int serviceRanking,
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/runtime/dto/RuntimeDTOBuilderTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/runtime/dto/RuntimeDTOBuilderTest.java
index 30320f6..9ec1314 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/runtime/dto/RuntimeDTOBuilderTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/runtime/dto/RuntimeDTOBuilderTest.java
@@ -243,20 +243,20 @@
         ServletContextHelperRuntime contextHelper_A = setupContext(context_A, "A", ID_A);
         ServletContextHelperRuntime contextHelper_B = setupContext(context_B, "B", ID_B);
 
-        List<ServletState> servlets = new ArrayList<ServletState>();
-        List<ServletState> resources = new ArrayList<ServletState>();
+        List<ServletHandler> servlets = new ArrayList<ServletHandler>();
+        List<ServletHandler> resources = new ArrayList<ServletHandler>();
 
         servlets.add(createTestServlet("1", context_0, ID_0));
         resources.add(createTestServlet("1", context_0, ID_0));
         List<FilterState> filters_0 = asList(createTestFilter("1", context_0));
         List<ServletState> errorPages_0 = asList(createErrorPage("E_1", context_0, ID_0));
-        ContextRuntime contextRuntime_0 = new ContextRuntime(filters_0, errorPages_0, null, null, null, null, null, null);
+        ContextRuntime contextRuntime_0 = new ContextRuntime(filters_0, errorPages_0, null, null);
 
         servlets.add(createTestServlet("A_1", context_A, ID_A));
         resources.add(createTestServlet("A_1", context_A, ID_A));
         List<FilterState> filters_A = asList(createTestFilter("A_1", context_A));
         List<ServletState> errorPages_A = asList(createErrorPage("E_A_1", context_A, ID_A));
-        ContextRuntime contextRuntime_A = new ContextRuntime(filters_A, errorPages_A, null, null, null, null, null, null);
+        ContextRuntime contextRuntime_A = new ContextRuntime(filters_A, errorPages_A, null, null);
 
         servlets.addAll(asList(createTestServletWithServiceId("B_1", context_B, ID_B),
                 createTestServletWithServiceId("B_2", context_B, ID_B)));
@@ -266,7 +266,7 @@
                 createTestFilterWithServiceId("B_2", context_B));
         List<ServletState> errorPages_B = asList(createErrorPageWithServiceId("E_B_1", context_B, ID_B),
                 createErrorPageWithServiceId("E_B_2", context_B, ID_B));
-        ContextRuntime contextRuntime_B = new ContextRuntime(filters_B, errorPages_B, null, null, null, null, null, null);
+        ContextRuntime contextRuntime_B = new ContextRuntime(filters_B, errorPages_B, null, null);
 
         Map<Long, Collection<ServiceReference<?>>> listenerRuntimes = setupListeners();
 
@@ -274,7 +274,7 @@
                 asList(contextRuntime_0, contextRuntime_A, contextRuntime_B),
 //                new ServletRegistryRuntime(servlets, resources),
                 listenerRuntimes,
-                FailureRuntime.empty());
+                null);
 
         RuntimeDTO runtimeDTO = new RuntimeDTOBuilder(registry, runtimeReference).build();
 
@@ -617,12 +617,11 @@
 
         ContextRuntime contextRuntime = new ContextRuntime(asList(filterHandler),
                 Collections.<ServletState>emptyList(),
-                null, null,
-                null, null, null, null);
+                null, null);
         setupRegistry(asList(contextHandler), asList(contextRuntime),
 //                new ServletRegistryRuntime(asList(resourceHandler), asList(servletHandler)),
                 Collections.<Long, Collection<ServiceReference<?>>>emptyMap(),
-                FailureRuntime.empty());
+                null);
 
         RuntimeDTO runtimeDTO = new RuntimeDTOBuilder(registry, runtimeReference).build();
 
@@ -646,7 +645,7 @@
         setupRegistry(asList(contextHandler_0, contextHandler_A),
 null, //                asList(ContextRuntime.empty(ID_0), ContextRuntime.empty(ID_A)),
                 Collections.<Long, Collection<ServiceReference<?>>>emptyMap(),
-                FailureRuntime.empty());
+                null);
 
         RuntimeDTO runtimeDTO = new RuntimeDTOBuilder(registry, runtimeReference).build();
 
@@ -678,12 +677,11 @@
 
         ContextRuntime contextRuntime = new ContextRuntime(Collections.<FilterState>emptyList(),
                 Collections.<ServletState>emptyList(),
-                null, null,
-                null, null, null, null);
+                null, null);
         setupRegistry(asList(contextHandler), asList(contextRuntime),
 //                new ServletRegistryRuntime(asList(servletHandler), Collections.<ServletRuntime>emptyList()),
                 Collections.<Long, Collection<ServiceReference<?>>>emptyMap(),
-                FailureRuntime.empty());
+                null);
 
         new RuntimeDTOBuilder(registry, runtimeReference).build();
     }