Update to latest http whiteboard api

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1659007 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java
index 8ca2193..cc265f5 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java
@@ -439,15 +439,20 @@
         }
 
         @Override
+        public HttpSession getSession() {
+            return this.getSession(true);
+        }
+
+        @Override
         public HttpSession getSession(boolean create)
         {
             // FELIX-2797: wrap the original HttpSession to provide access to the correct ServletContext...
-            HttpSession session = super.getSession(create);
+            final HttpSession session = super.getSession(create);
             if (session == null)
             {
                 return null;
             }
-            return new HttpSessionWrapper(session, this.servletContext);
+            return new HttpSessionWrapper(this.contextId, session, this.servletContext);
         }
 
         @Override
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpSessionWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpSessionWrapper.java
index 602a106..2573cca 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpSessionWrapper.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpSessionWrapper.java
@@ -19,7 +19,12 @@
 
 package org.apache.felix.http.base.internal.handler;
 
+import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
 
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpSession;
@@ -31,100 +36,218 @@
 @SuppressWarnings("deprecation")
 public class HttpSessionWrapper implements HttpSession
 {
+    private static final String PREFIX = "org.apache.felix.http.session.context.";
+
+    private static final String SESSION_MAP = "org.apache.felix.http.session.context.map";
+
     private final HttpSession delegate;
     private final ServletContext context;
 
+    private final String keyPrefix;
+
+    private volatile boolean isInvalid = false;
+
+    private final long created;
+
+    private final long contextId;
+
     /**
      * Creates a new {@link HttpSessionWrapper} instance.
      */
-    public HttpSessionWrapper(HttpSession session, ServletContext context)
+    public HttpSessionWrapper(final Long contextId, final HttpSession session,
+            final ServletContext context)
     {
         this.delegate = session;
         this.context = context;
+        this.contextId = (contextId == null ? 0 : contextId);
+        this.keyPrefix = this.contextId == 0 ? null : PREFIX + String.valueOf(contextId) + ".";
+        synchronized ( this.getClass() )
+        {
+            @SuppressWarnings("unchecked")
+            Map<Long, Long> sessionMap = (Map<Long, Long>)session.getAttribute(SESSION_MAP);
+            if ( sessionMap == null )
+            {
+                sessionMap = new HashMap<Long, Long>();
+            }
+            if ( !sessionMap.containsKey(contextId) )
+            {
+                sessionMap.put(contextId, System.currentTimeMillis());
+                session.setAttribute(SESSION_MAP, sessionMap);
+            }
+            this.created = sessionMap.get(contextId);
+        }
     }
 
-    public Object getAttribute(String name)
+    private String getKey(final String name)
     {
-        return this.delegate.getAttribute(name);
+        return this.keyPrefix == null ? name : this.keyPrefix.concat(name);
     }
 
+    private void checkInvalid()
+    {
+        if ( this.isInvalid )
+        {
+            throw new IllegalStateException("Session is invalid.");
+        }
+    }
+
+    @Override
+    public Object getAttribute(final String name)
+    {
+        this.checkInvalid();
+        return this.delegate.getAttribute(this.getKey(name));
+    }
+
+    @Override
     public Enumeration<String> getAttributeNames()
     {
-        return this.delegate.getAttributeNames();
+        this.checkInvalid();
+        final Enumeration<String> e = this.delegate.getAttributeNames();
+        return new Enumeration<String>() {
+
+            String next = peek();
+
+            private String peek()
+            {
+                while ( e.hasMoreElements() )
+                {
+                    final String name = e.nextElement();
+                    if ( keyPrefix == null )
+                    {
+                        return name;
+                    }
+                    if ( name.startsWith(keyPrefix))
+                    {
+                        return name.substring(keyPrefix.length());
+                    }
+                }
+                return null;
+            }
+
+            @Override
+            public boolean hasMoreElements() {
+                return next != null;
+            }
+
+            @Override
+            public String nextElement() {
+                if ( next == null )
+                {
+                    throw new NoSuchElementException();
+                }
+                final String result = next;
+                next = this.peek();
+                return result;
+            }
+        };
+
     }
 
+    @Override
     public long getCreationTime()
     {
-        return this.delegate.getCreationTime();
+        this.checkInvalid();
+        return this.created;
     }
 
+    @Override
     public String getId()
     {
-        return this.delegate.getId();
+        this.checkInvalid();
+        return this.delegate.getId() + "-" + String.valueOf(this.contextId);
     }
 
+    @Override
     public long getLastAccessedTime()
     {
+        this.checkInvalid();
+        // TODO
         return this.delegate.getLastAccessedTime();
     }
 
+    @Override
     public int getMaxInactiveInterval()
     {
+        // TODO
         return this.delegate.getMaxInactiveInterval();
     }
 
+    @Override
     public ServletContext getServletContext()
     {
         return this.context;
     }
 
+    @Override
     public HttpSessionContext getSessionContext()
     {
         return this.delegate.getSessionContext();
     }
 
+    @Override
     public Object getValue(String name)
     {
-        return this.delegate.getValue(name);
+        return this.getAttribute(name);
     }
 
+    @Override
     public String[] getValueNames()
     {
-        return this.delegate.getValueNames();
+        final List<String> names = new ArrayList<String>();
+        final Enumeration<String> e = this.getAttributeNames();
+        while ( e.hasMoreElements() )
+        {
+            names.add(e.nextElement());
+        }
+        return names.toArray(new String[names.size()]);
     }
 
+    @Override
     public void invalidate()
     {
+        this.checkInvalid();
+        this.isInvalid = true;
+        // TODO
         this.delegate.invalidate();
     }
 
+    @Override
     public boolean isNew()
     {
+        this.checkInvalid();
         return this.delegate.isNew();
     }
 
-    public void putValue(String name, Object value)
+    @Override
+    public void putValue(final String name, final Object value)
     {
-        this.delegate.putValue(name, value);
+        this.setAttribute(name, value);
     }
 
-    public void removeAttribute(String name)
+    @Override
+    public void removeAttribute(final String name)
     {
+        this.checkInvalid();
         this.delegate.removeAttribute(name);
     }
 
-    public void removeValue(String name)
+    @Override
+    public void removeValue(final String name)
     {
-        this.delegate.removeValue(name);
+        this.removeAttribute(this.getKey(name));
     }
 
-    public void setAttribute(String name, Object value)
+    @Override
+    public void setAttribute(final String name, final Object value)
     {
-        this.delegate.setAttribute(name, value);
+        this.checkInvalid();
+        this.delegate.setAttribute(this.getKey(name), value);
     }
 
+    @Override
     public void setMaxInactiveInterval(int interval)
     {
+        // TODO
         this.delegate.setMaxInactiveInterval(interval);
     }
 }
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 3d072ce..d66c5c5 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
@@ -29,7 +29,9 @@
     private final ServletContext context;
     private final Map<String, String> initParams;
 
-    public ServletConfigImpl(final String name, final ServletContext context, final Map<String, String> initParams)
+    public ServletConfigImpl(final String name,
+            final ServletContext context,
+            final Map<String, String> initParams)
     {
         this.name = name;
         this.context = context;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextAttributeListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextAttributeListenerInfo.java
index 27fd5da..a55147c 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextAttributeListenerInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextAttributeListenerInfo.java
@@ -21,6 +21,7 @@
 import javax.servlet.ServletContextAttributeListener;
 
 import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
 /**
  * Info object for registered servlet context attribute listeners
@@ -29,8 +30,18 @@
  */
 public final class ServletContextAttributeListenerInfo extends WhiteboardServiceInfo<ServletContextAttributeListener>
 {
+
+    private final String enabled;
+
     public ServletContextAttributeListenerInfo(final ServiceReference<ServletContextAttributeListener> ref)
     {
         super(ref);
+        this.enabled = this.getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER);
+    }
+
+    @Override
+    public boolean isValid()
+    {
+        return super.isValid() && "true".equalsIgnoreCase(this.enabled);
     }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java
index fe73d8e..1440f67 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java
@@ -21,6 +21,7 @@
 import javax.servlet.ServletContextListener;
 
 import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
 /**
  * Info object for registered servlet context listeners
@@ -29,8 +30,17 @@
  */
 public final class ServletContextListenerInfo extends WhiteboardServiceInfo<ServletContextListener>
 {
+    private final String enabled;
+
     public ServletContextListenerInfo(final ServiceReference<ServletContextListener> ref)
     {
         super(ref);
+        this.enabled = this.getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER);
+    }
+
+    @Override
+    public boolean isValid()
+    {
+        return super.isValid() && "true".equalsIgnoreCase(this.enabled);
     }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextAttributeListenerTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextAttributeListenerTracker.java
index eb82557..2ed295d 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextAttributeListenerTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextAttributeListenerTracker.java
@@ -24,20 +24,19 @@
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
 public final class ServletContextAttributeListenerTracker extends AbstractReferenceTracker<ServletContextAttributeListener>
 {
 
-    /** TODO Currently under discussion. */
-    private static final String OPT_IN_PROP = "osgi.http.whiteboard.listener";
-
     private static org.osgi.framework.Filter createFilter(final BundleContext btx)
     {
         try
         {
-            return btx.createFilter(String.format("(&(objectClass=%s)(%s=*))",
+            return btx.createFilter(String.format("(&(objectClass=%s)(%s=*)(!(%s~=false)))",
                     ServletContextAttributeListener.class.getName(),
-                    OPT_IN_PROP));
+                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER,
+                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER));
         }
         catch ( final InvalidSyntaxException ise)
         {
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
index fe0028c..b2af061 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
@@ -24,20 +24,19 @@
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
 public final class ServletContextListenerTracker extends AbstractReferenceTracker<ServletContextListener>
 {
 
-    /** TODO Currently under discussion. */
-    private static final String OPT_IN_PROP = "osgi.http.whiteboard.listener";
-
     private static org.osgi.framework.Filter createFilter(final BundleContext btx)
     {
         try
         {
-            return btx.createFilter(String.format("(&(objectClass=%s)(%s=*))",
+            return btx.createFilter(String.format("(&(objectClass=%s)(%s=*)(!(%s~=false)))",
                     ServletContextListener.class.getName(),
-                    OPT_IN_PROP));
+                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER,
+                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER));
         }
         catch ( final InvalidSyntaxException ise)
         {