WebSessions: backported latests changes from 1.6.

Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/b07d5c1f
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/b07d5c1f
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/b07d5c1f

Branch: refs/heads/ignite-3163
Commit: b07d5c1f3f8f4136bd829360ed78623f298669d2
Parents: 2d2e935
Author: vozerov-gridgain <[email protected]>
Authored: Wed May 18 11:06:42 2016 +0300
Committer: vozerov-gridgain <[email protected]>
Committed: Wed May 18 11:06:42 2016 +0300

----------------------------------------------------------------------
 .../WebSessionAttributeProcessor.java           |   5 +-
 .../ignite/cache/websession/WebSession.java     |  74 +++++++-
 .../cache/websession/WebSessionFilter.java      | 177 ++++++++++++++-----
 .../ignite/cache/websession/WebSessionV2.java   |  74 ++++----
 4 files changed, 250 insertions(+), 80 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/b07d5c1f/modules/core/src/main/java/org/apache/ignite/internal/websession/WebSessionAttributeProcessor.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/websession/WebSessionAttributeProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/websession/WebSessionAttributeProcessor.java
index 35b4d90..bef42e4 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/websession/WebSessionAttributeProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/websession/WebSessionAttributeProcessor.java
@@ -67,9 +67,8 @@ public class WebSessionAttributeProcessor implements 
EntryProcessor<String, WebS
      * @param maxInactiveInterval Max inactive interval.
      * @param maxIntervalChanged {@code True} if max inactive interval should 
be updated.
      */
-    public WebSessionAttributeProcessor(
-        final Map<String, byte[]> updatesMap, final long accessTime, final int 
maxInactiveInterval,
-        final boolean maxIntervalChanged) {
+    public WebSessionAttributeProcessor(final Map<String, byte[]> updatesMap, 
final long accessTime,
+        final int maxInactiveInterval, final boolean maxIntervalChanged) {
         this.updatesMap = updatesMap;
         this.accessTime = accessTime;
         this.maxInactiveInterval = maxInactiveInterval;

http://git-wip-us.apache.org/repos/asf/ignite/blob/b07d5c1f/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSession.java
----------------------------------------------------------------------
diff --git 
a/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSession.java 
b/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSession.java
index 5734b64..2e43f2f 100644
--- 
a/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSession.java
+++ 
b/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSession.java
@@ -45,6 +45,9 @@ class WebSession implements HttpSession, Externalizable {
     /** */
     private static final long serialVersionUID = 0L;
 
+    /** Flag indicating if the session is valid. */
+    private volatile transient boolean isValid = true;
+
     /** Empty session context. */
     private static final HttpSessionContext EMPTY_SES_CTX = new 
HttpSessionContext() {
         @Nullable @Override public HttpSession getSession(String id) {
@@ -76,6 +79,7 @@ class WebSession implements HttpSession, Externalizable {
     @GridToStringExclude
     private transient ServletContext ctx;
 
+    /** Web session filter. */
     @GridToStringExclude
     private transient WebSessionFilter filter;
 
@@ -85,6 +89,9 @@ class WebSession implements HttpSession, Externalizable {
     /** Updates list. */
     private transient Collection<T2<String, Object>> updates;
 
+    /** Genuine http session. */
+    private transient HttpSession genSes;
+
     /**
      * Required by {@link Externalizable}.
      */
@@ -130,6 +137,15 @@ class WebSession implements HttpSession, Externalizable {
     }
 
     /**
+     * Sets the genuine http session.
+     *
+     * @param genSes Genuine http session.
+     */
+    protected void genSes(HttpSession genSes) {
+        this.genSes = genSes;
+    }
+
+    /**
      * @param ctx Servlet context.
      */
     public void servletContext(ServletContext ctx) {
@@ -148,6 +164,15 @@ class WebSession implements HttpSession, Externalizable {
     }
 
     /**
+     * Checks if the session is valid.
+     *
+     * @return True is valid, otherwise false.
+     */
+    protected boolean isValid() {
+        return this.isValid;
+    }
+
+    /**
      * Resets updates list.
      */
     public void resetUpdates() {
@@ -170,6 +195,15 @@ class WebSession implements HttpSession, Externalizable {
         return id;
     }
 
+    /**
+     * Sets a session id.
+     *
+     * @param id Session id.
+     */
+    protected void setId(String id) {
+        this.id = id;
+    }
+
     /** {@inheritDoc} */
     @Override public ServletContext getServletContext() {
         return ctx;
@@ -177,11 +211,17 @@ class WebSession implements HttpSession, Externalizable {
 
     /** {@inheritDoc} */
     @Override public long getCreationTime() {
+        if (!isValid)
+            throw new IllegalStateException("Call on invalidated session!");
+
         return createTime;
     }
 
     /** {@inheritDoc} */
     @Override public long getLastAccessedTime() {
+        if (!isValid)
+            throw new IllegalStateException("Call on invalidated session!");
+
         return accessTime;
     }
 
@@ -197,26 +237,43 @@ class WebSession implements HttpSession, Externalizable {
 
     /** {@inheritDoc} */
     @Override public Object getAttribute(String name) {
-        return attrs.get(name);
+        if (!isValid)
+            throw new IllegalStateException("Call on invalidated session!");
+
+        Object val = attrs.get(name);
+
+        if (val != null && updates != null)
+            updates.add(new T2<>(name, val));
+
+        return val;
     }
 
     /** {@inheritDoc} */
     @Override public Object getValue(String name) {
-        return attrs.get(name);
+        return getAttribute(name);
     }
 
     /** {@inheritDoc} */
     @Override public Enumeration<String> getAttributeNames() {
+        if (!isValid)
+            throw new IllegalStateException("Call on invalidated session!");
+
         return Collections.enumeration(attrs.keySet());
     }
 
     /** {@inheritDoc} */
     @Override public String[] getValueNames() {
+        if (!isValid)
+            throw new IllegalStateException("Call on invalidated session!");
+
         return attrs.keySet().toArray(new String[attrs.size()]);
     }
 
     /** {@inheritDoc} */
     @Override public void setAttribute(String name, Object val) {
+        if (!isValid)
+            throw new IllegalStateException("Call on invalidated session!");
+
         attrs.put(name, val);
 
         if (updates != null)
@@ -230,6 +287,9 @@ class WebSession implements HttpSession, Externalizable {
 
     /** {@inheritDoc} */
     @Override public void removeAttribute(String name) {
+        if (!isValid)
+            throw new IllegalStateException("Call on invalidated session!");
+
         attrs.remove(name);
 
         if (updates != null)
@@ -243,15 +303,25 @@ class WebSession implements HttpSession, Externalizable {
 
     /** {@inheritDoc} */
     @Override public void invalidate() {
+        if (!isValid)
+            throw new IllegalStateException("Call on invalidated session!");
+
         attrs.clear();
 
         updates = null;
 
         filter.destroySession(id);
+
+        genSes.invalidate();
+
+        isValid = false;
     }
 
     /** {@inheritDoc} */
     @Override public boolean isNew() {
+        if (!isValid)
+            throw new IllegalStateException("Call on invalidated session!");
+
         return isNew;
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/b07d5c1f/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionFilter.java
----------------------------------------------------------------------
diff --git 
a/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionFilter.java
 
b/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionFilter.java
index c0f62bf..2b7442f 100644
--- 
a/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionFilter.java
+++ 
b/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionFilter.java
@@ -196,8 +196,7 @@ public class WebSessionFilter implements Filter {
     /** Default retry on fail timeout flag value. */
     public static final int DFLT_RETRIES_ON_FAIL_TIMEOUT = 10000;
 
-    // TOOD: Minimal JavaDoc.
-    /** */
+    /** Default keep binary flag. */
     public static final boolean DFLT_KEEP_BINARY_FLAG = true;
 
     /** Cache. */
@@ -416,7 +415,7 @@ public class WebSessionFilter implements Filter {
      * @param chain Filter chain.
      * @return Session ID.
      * @throws IOException In case of I/O error.
-     * @throws ServletException In case oif servlet error.
+     * @throws ServletException In case of servlet error.
      * @throws CacheException In case of other error.
      */
     private String doFilterV1(HttpServletRequest httpReq, ServletResponse res, 
FilterChain chain) throws IOException,
@@ -464,26 +463,30 @@ public class WebSessionFilter implements Filter {
                 cached = createSession(httpReq);
             }
         }
-        else {
+        else
             cached = createSession(httpReq);
 
-            sesId = cached.getId();
-        }
-
         assert cached != null;
 
+        sesId = cached.getId();
+
         cached.servletContext(ctx);
         cached.filter(this);
         cached.resetUpdates();
+        cached.genSes(httpReq.getSession(false));
 
         httpReq = new RequestWrapper(httpReq, cached);
 
         chain.doFilter(httpReq, res);
 
-        final Collection<T2<String, Object>> updates = cached.updates();
+        HttpSession ses = httpReq.getSession(false);
+
+        if (ses != null && ses instanceof WebSession) {
+            Collection<T2<String, Object>> updates = ((WebSession) 
ses).updates();
 
-        if (updates != null)
-            updateAttributes(transformSessionId(sesId), updates, 
cached.getMaxInactiveInterval());
+            if (updates != null)
+                updateAttributes(transformSessionId(sesId), updates, 
ses.getMaxInactiveInterval());
+        }
 
         return sesId;
     }
@@ -511,11 +514,10 @@ public class WebSessionFilter implements Filter {
                 try {
                     final WebSessionEntity entity = binaryCache.get(sesId);
 
-                    if (entity != null) {
-                        cached = new WebSessionV2(sesId, null, false, ctx, 
entity, marshaller);
+                    if (entity != null)
+                        cached = new WebSessionV2(sesId, 
httpReq.getSession(false), false, ctx, entity, marshaller);
 
-                        break;
-                    }
+                    break;
                 }
                 catch (CacheException | IgniteException | 
IllegalStateException e) {
                     handleLoadSessionException(sesId, i, e);
@@ -548,23 +550,29 @@ public class WebSessionFilter implements Filter {
             }
         }
         // No session was requested by the client, create new one and put in 
the request.
-        else {
+        else
             cached = createSessionV2(httpReq);
 
-            sesId = cached.getId();
-        }
-
         assert cached != null;
 
+        sesId = cached.getId();
+
         httpReq = new RequestWrapperV2(httpReq, cached);
 
         chain.doFilter(httpReq, res);
 
-        // Update session
-        if (cached.isValid())
-            updateAttributesV2(sesId, cached);
+        if (!cached.isValid())
+            binaryCache.remove(cached.id());
+        // Changed session ID.
+        else if (!cached.getId().equals(sesId)) {
+            final String oldId = cached.getId();
+
+            cached.invalidate();
+
+            binaryCache.remove(oldId);
+        }
         else
-            binaryCache.remove(sesId);
+            updateAttributesV2(cached.getId(), cached);
 
         return sesId;
     }
@@ -604,8 +612,10 @@ public class WebSessionFilter implements Filter {
     }
 
     /**
-     * @param httpReq HTTP request.
-     * @return Cached session.
+     * Creates a new session from http request.
+     *
+     * @param httpReq Request.
+     * @return New session.
      */
     @SuppressWarnings("unchecked")
     private WebSession createSession(HttpServletRequest httpReq) {
@@ -613,11 +623,25 @@ public class WebSessionFilter implements Filter {
 
         String sesId = transformSessionId(ses.getId());
 
-        if (log.isDebugEnabled())
-            log.debug("Session created: " + sesId);
+        return createSession(ses, sesId);
+    }
 
+    /**
+     * Creates a new web session with the specified id.
+     *
+     * @param ses Base session.
+     * @param sesId Session id.
+     * @return New session.
+     */
+    @SuppressWarnings("unchecked")
+    private WebSession createSession(HttpSession ses, String sesId) {
         WebSession cached = new WebSession(sesId, ses, true);
 
+        cached.genSes(ses);
+
+        if (log.isDebugEnabled())
+            log.debug("Session created: " + sesId);
+
         for (int i = 0; i < retries; i++) {
             try {
                 final IgniteCache<String, WebSession> cache0 =
@@ -664,14 +688,13 @@ public class WebSessionFilter implements Filter {
     }
 
     /**
-     * @param httpReq HTTP request.
-     * @return Cached session.
+     * Creates a new web session with the specified id.
+     *
+     * @param ses Base session.
+     * @param sesId Session id.
+     * @return New session.
      */
-    private WebSessionV2 createSessionV2(HttpServletRequest httpReq) throws 
IOException {
-        final HttpSession ses = httpReq.getSession(true);
-
-        final String sesId = transformSessionId(ses.getId());
-
+    private WebSessionV2 createSessionV2(final HttpSession ses, final String 
sesId) throws IOException {
         if (log.isDebugEnabled())
             log.debug("Session created: " + sesId);
 
@@ -687,9 +710,9 @@ public class WebSessionFilter implements Filter {
                 final WebSessionEntity old = cache0.getAndPutIfAbsent(sesId, 
marshaledEntity);
 
                 if (old != null)
-                    cached = new WebSessionV2(sesId, null, false, ctx, old, 
marshaller);
+                    cached = new WebSessionV2(sesId, ses, false, ctx, old, 
marshaller);
                 else
-                    cached = new WebSessionV2(sesId, null, false, ctx, 
marshaledEntity, marshaller);
+                    cached = new WebSessionV2(sesId, ses, false, ctx, 
marshaledEntity, marshaller);
 
                 break;
             }
@@ -702,6 +725,18 @@ public class WebSessionFilter implements Filter {
     }
 
     /**
+     * @param httpReq HTTP request.
+     * @return Cached session.
+     */
+    private WebSessionV2 createSessionV2(HttpServletRequest httpReq) throws 
IOException {
+        final HttpSession ses = httpReq.getSession(true);
+
+        final String sesId = transformSessionId(ses.getId());
+
+        return createSessionV2(ses, sesId);
+    }
+
+    /**
      * @param maxInactiveInteval Interval to use in expiry policy.
      * @param cache Cache.
      * @param <T> Cached object type.
@@ -876,9 +911,9 @@ public class WebSessionFilter implements Filter {
     /**
      * Request wrapper.
      */
-    private static class RequestWrapper extends HttpServletRequestWrapper {
+    private class RequestWrapper extends HttpServletRequestWrapper {
         /** Session. */
-        private final WebSession ses;
+        private volatile WebSession ses;
 
         /**
          * @param req Request.
@@ -894,21 +929,48 @@ public class WebSessionFilter implements Filter {
 
         /** {@inheritDoc} */
         @Override public HttpSession getSession(boolean create) {
+            if (!ses.isValid()) {
+                if (create) {
+                    this.ses = createSession((HttpServletRequest)getRequest());
+                    this.ses.servletContext(ctx);
+                    this.ses.filter(WebSessionFilter.this);
+                    this.ses.resetUpdates();
+                }
+                else
+                    return null;
+            }
+
             return ses;
         }
 
         /** {@inheritDoc} */
         @Override public HttpSession getSession() {
-            return ses;
+            return getSession(true);
+        }
+
+        /** {@inheritDoc} */
+        @Override public String changeSessionId() {
+            HttpServletRequest req = (HttpServletRequest)getRequest();
+
+            String newId = req.changeSessionId();
+
+            this.ses.setId(newId);
+
+            this.ses = createSession(ses, newId);
+            this.ses.servletContext(ctx);
+            this.ses.filter(WebSessionFilter.this);
+            this.ses.resetUpdates();
+
+            return newId;
         }
     }
 
     /**
      * Request wrapper V2.
      */
-    private static class RequestWrapperV2 extends HttpServletRequestWrapper {
+    private class RequestWrapperV2 extends HttpServletRequestWrapper {
         /** Session. */
-        private final WebSessionV2 ses;
+        private WebSessionV2 ses;
 
         /**
          * @param req Request.
@@ -924,12 +986,45 @@ public class WebSessionFilter implements Filter {
 
         /** {@inheritDoc} */
         @Override public HttpSession getSession(boolean create) {
+            if (!ses.isValid()) {
+                binaryCache.remove(ses.id());
+
+                if (create) {
+                    try {
+                        ses = createSessionV2((HttpServletRequest) 
getRequest());
+                    }
+                    catch (IOException e) {
+                        throw new IgniteException(e);
+                    }
+                }
+                else
+                    return null;
+            }
+
             return ses;
         }
 
         /** {@inheritDoc} */
         @Override public HttpSession getSession() {
-            return ses;
+            return getSession(true);
+        }
+
+        /** {@inheritDoc} */
+        @Override public String changeSessionId() {
+            final HttpServletRequest req = (HttpServletRequest) getRequest();
+
+            final String newId = req.changeSessionId();
+
+            if (!F.eq(newId, ses.getId())) {
+                try {
+                    ses = createSessionV2(ses, newId);
+                }
+                catch (IOException e) {
+                    throw new IgniteException(e);
+                }
+            }
+
+            return newId;
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b07d5c1f/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionV2.java
----------------------------------------------------------------------
diff --git 
a/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionV2.java
 
b/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionV2.java
index 9f2e24a..b6540b2 100644
--- 
a/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionV2.java
+++ 
b/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionV2.java
@@ -66,9 +66,6 @@ class WebSessionV2 implements HttpSession {
     /** Attributes. */
     protected Map<String, Object> attrs;
 
-    /** Attributes waiting for update in cache. */
-    private Map<String, Object> updatesMap;
-
     /** Timestamp that shows when this object was created. (Last access time 
from user request) */
     private final long accessTime;
 
@@ -87,6 +84,9 @@ class WebSessionV2 implements HttpSession {
     /** Grid marshaller. */
     private final Marshaller marshaller;
 
+    /** Original session to delegate invalidation. */
+    private final HttpSession genuineSes;
+
     /**
      * @param id Session ID.
      * @param ses Session.
@@ -102,6 +102,7 @@ class WebSessionV2 implements HttpSession {
         this.marshaller = marshaller;
         this.ctx = ctx;
         this.isNew = isNew;
+        this.genuineSes = ses;
 
         accessTime = System.currentTimeMillis();
 
@@ -134,8 +135,13 @@ class WebSessionV2 implements HttpSession {
 
     /** {@inheritDoc} */
     @Override public String getId() {
-        assertValid();
+        return entity.id();
+    }
 
+    /**
+     * @return Session ID without throwing exception.
+     */
+    public String id() {
         return entity.id();
     }
 
@@ -185,21 +191,20 @@ class WebSessionV2 implements HttpSession {
         if (attr == REMOVED_ATTR)
             return null;
 
-        if (attr != null)
-            return attr;
+        if (attr == null) {
+            final byte[] bytes = entity.attributes().get(name);
 
-        final byte[] bytes = entity.attributes().get(name);
+            if (bytes != null) {
+                // deserialize
+                try {
+                    attr = unmarshal(bytes);
+                }
+                catch (IOException e) {
+                    throw new IgniteException(e);
+                }
 
-        if (bytes != null) {
-            // deserialize
-            try {
-                attr = unmarshal(bytes);
-            }
-            catch (IOException e) {
-                throw new IgniteException(e);
+                attributes().put(name, attr);
             }
-
-            attributes().put(name, attr);
         }
 
         return attr;
@@ -214,9 +219,10 @@ class WebSessionV2 implements HttpSession {
     @Override public void setAttribute(final String name, final Object val) {
         assertValid();
 
-        attributes().put(name, val);
-
-        updatesMap().put(name, val);
+        if (val == null)
+            removeAttribute(name);
+        else
+            attributes().put(name, val);
     }
 
     /** {@inheritDoc} */
@@ -265,8 +271,6 @@ class WebSessionV2 implements HttpSession {
         assertValid();
 
         attributes().put(name, REMOVED_ATTR);
-
-        updatesMap().put(name, null);
     }
 
     /** {@inheritDoc} */
@@ -278,6 +282,15 @@ class WebSessionV2 implements HttpSession {
     @Override public void invalidate() {
         assertValid();
 
+        if (genuineSes != null) {
+            try {
+                genuineSes.invalidate();
+            }
+            catch (IllegalStateException e) {
+                // Already invalidated, keep going.
+            }
+        }
+
         invalidated = true;
     }
 
@@ -293,15 +306,18 @@ class WebSessionV2 implements HttpSession {
      * @throws IOException
      */
     public Map<String, byte[]> binaryUpdatesMap() throws IOException {
-        final Map<String, Object> map = updatesMap;
+        final Map<String, Object> map = attributes();
 
         if (F.isEmpty(map))
             return Collections.emptyMap();
 
         final Map<String, byte[]> res = new HashMap<>(map.size());
 
-        for (final Map.Entry<String, Object> entry : map.entrySet())
-            res.put(entry.getKey(), marshal(entry.getValue()));
+        for (final Map.Entry<String, Object> entry : map.entrySet()) {
+            Object val = entry.getValue() == REMOVED_ATTR ? null : 
entry.getValue();
+
+            res.put(entry.getKey(), marshal(val));
+        }
 
         return res;
     }
@@ -371,16 +387,6 @@ class WebSessionV2 implements HttpSession {
     }
 
     /**
-     * @return Updates map.
-     */
-    private Map<String, Object> updatesMap() {
-        if (updatesMap == null)
-            updatesMap = new HashMap<>();
-
-        return updatesMap;
-    }
-
-    /**
      * @return {@code True} if session wasn't invalidated.
      */
     public boolean isValid() {

Reply via email to