You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by be...@apache.org on 2012/06/11 22:32:55 UTC

svn commit: r1348996 - in /mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src: main/java/org/apache/vysper/xmpp/extension/xep0124/ test/java/org/apache/vysper/xmpp/extension/xep0124/

Author: berndf
Date: Mon Jun 11 20:32:55 2012
New Revision: 1348996

URL: http://svn.apache.org/viewvc?rev=1348996&view=rev
Log:
VYSPER-320: 
add flag to BoshBackedSessionContext indicating the request to store it in HttpSession
make BoshHandler subclasses capable to override behavior
subclasses of BoshServlet might replace default BoshHandler

Modified:
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java
    mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContextTest.java

Modified: mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java?rev=1348996&r1=1348995&r2=1348996&view=diff
==============================================================================
--- mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java (original)
+++ mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java Mon Jun 11 20:32:55 2012
@@ -53,7 +53,7 @@ public class BoshBackedSessionContext ex
 
     private final static Logger LOGGER = LoggerFactory.getLogger(BoshBackedSessionContext.class);
 
-    private final BoshHandler boshHandler;
+    public final static String HTTP_SESSION_ATTRIBUTE = "org.apache.vysper.xmpp.extension.xep0124.BoshBackedSessionContext"; 
     
     private final int maxpause = 120;
 
@@ -138,21 +138,20 @@ public class BoshBackedSessionContext ex
     private Long lastInactivityExpireTime;
     
     private boolean isWatchedByInactivityChecker;
+    
+    private boolean propagateSessionContextToHTTPSession = false;
 
     /**
      * Creates a new context for a session
-     * @param boshHandler
      * @param serverRuntimeContext
      * @param inactivityChecker
      */
-    public BoshBackedSessionContext(BoshHandler boshHandler, ServerRuntimeContext serverRuntimeContext, InactivityChecker inactivityChecker) {
+    public BoshBackedSessionContext(ServerRuntimeContext serverRuntimeContext, InactivityChecker inactivityChecker) {
         super(serverRuntimeContext, new SessionStateHolder());
 
         // in BOSH we jump directly to the encrypted state
         sessionStateHolder.setState(SessionState.ENCRYPTED);
 
-        this.boshHandler = boshHandler;
-
         this.inactivityChecker = inactivityChecker;
         updateInactivityChecker();
     }
@@ -197,9 +196,17 @@ public class BoshBackedSessionContext ex
         // and this is done in BoshHandler when the client requests it
     }
 
-    /*
-     * This method is synchronized on the session object to prevent concurrent writes to the same BOSH client
+    /**
+     * true, iff this session context will be stored to the related BOSH HTTP session.
+     * @return
      */
+    public boolean propagateSessionContext() {
+        return propagateSessionContextToHTTPSession;
+    }
+
+    /*
+    * This method is synchronized on the session object to prevent concurrent writes to the same BOSH client
+    */
     synchronized public void write(Stanza stanza) {
         if (stanza == null) throw new IllegalArgumentException("stanza must not be null.");
         LOGGER.debug("adding server stanza for writing to BOSH client");
@@ -207,8 +214,9 @@ public class BoshBackedSessionContext ex
     }
 
     /**
-     * Writes a BOSH response (that is wrapped in a <body/> element) if there are available HTTP requests
-     * to respond to, otherwise the response is queued to be sent later (when a HTTP request will be available).
+     * Writes a server-to-client XMPP stanza as a BOSH response (wrapped in a <body/> element) if there are 
+     * available HTTP requests to respond to, otherwise the response is queued to be sent later 
+     * (when a HTTP request becomes available).
      * <p>
      * (package access)
      * 

Modified: mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java?rev=1348996&r1=1348995&r2=1348996&view=diff
==============================================================================
--- mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java (original)
+++ mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java Mon Jun 11 20:32:55 2012
@@ -19,14 +19,6 @@
  */
 package org.apache.vysper.xmpp.extension.xep0124;
 
-import java.io.IOException;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import javax.servlet.AsyncContext;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.vysper.xml.fragment.Attribute;
 import org.apache.vysper.xml.fragment.XMLElement;
 import org.apache.vysper.xmpp.protocol.NamespaceURIs;
 import org.apache.vysper.xmpp.server.ServerRuntimeContext;
@@ -37,6 +29,13 @@ import org.apache.vysper.xmpp.stanza.Sta
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.servlet.AsyncContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
 /**
  * Processes the BOSH requests from the clients
  * <p>
@@ -72,6 +71,10 @@ public class BoshHandler {
         return serverRuntimeContext;
     }
 
+    protected InactivityChecker getInactivityChecker() {
+        return inactivityChecker;
+    }
+
     /**
      * Setter for the {@link ServerRuntimeContext}
      * @param serverRuntimeContext
@@ -80,8 +83,12 @@ public class BoshHandler {
         this.serverRuntimeContext = serverRuntimeContext;
     }
 
+    protected BoshBackedSessionContext createSessionContext() {
+        return new BoshBackedSessionContext(serverRuntimeContext, inactivityChecker);
+    }
+
     /**
-     * Processes BOSH requests
+     * Processes incoming BOSH requests
      * @param httpRequest the HTTP request
      * @param body the decoded BOSH request
      */
@@ -117,42 +124,46 @@ public class BoshHandler {
             // continue anyway, this is not a problem with this implementation
         }
         BoshRequest br = new BoshRequest(httpRequest, body, rid);
+
+        // session creation request (first request). does not have a "sid" attribute
         if (body.getAttribute("sid") == null) {
-            // the session creation request (first request) does not have a "sid" attribute
             try {
                 createSession(br);
             } catch (IOException e) {
                 LOGGER.error("Exception thrown while processing the session creation request", e);
-                return;
-            }
-        } else {
-            final String sid = body.getAttributeValue("sid");
-            BoshBackedSessionContext session = null;
-            if (sid != null) session = sessions.get(sid);
-            if (session == null) {
-                LOGGER.warn("Received an invalid sid = '{}', terminating connection", sid);
-                final AsyncContext context = br.getHttpServletRequest().startAsync();
-                // create temporary session to be able to reuse the code
-                new BoshBackedSessionContext(this, serverRuntimeContext, inactivityChecker).error(br, "invalid session id");
-                return;
             }
-            synchronized (session) {
-                session.insertRequest(br);
-                for (;;) {
-                    // When a request from the user comes in, it is possible that the request fills a gap
-                    // created by previous lost request, and it could be possible to process more than the current request
-                    // continuing with all the adjacent requests.
-                    br = session.getNextRequest();
-                    if (br == null) {
-                        break;
-                    }
-                    processSession(session, br);
+            return;
+        } 
+
+        // in-session request, now find the server-side session
+        final String sid = body.getAttributeValue("sid");
+        BoshBackedSessionContext session = null;
+        if (sid != null) session = sessions.get(sid);
+        if (session == null) {
+            LOGGER.warn("Received an invalid sid = '{}', terminating connection", sid);
+            final AsyncContext context = br.getHttpServletRequest().startAsync();
+            // create temporary session to be able to reuse the code
+            createSessionContext().error(br, "invalid session id");
+            return;
+        }
+        
+        // process request for the session
+        synchronized (session) {
+            session.insertRequest(br);
+            for (;;) {
+                // When a request from the user comes in, it is possible that the request fills a gap
+                // created by previous lost request, and it could be possible to process more than the current request
+                // continuing with all the adjacent requests.
+                br = session.getNextRequest();
+                if (br == null) {
+                    break;
                 }
+                processSession(session, br);
             }
         }
     }
     
-    private void processSession(BoshBackedSessionContext session, BoshRequest br) {
+    protected void processSession(BoshBackedSessionContext session, BoshRequest br) {
         final Stanza stanza = br.getBody();
         if (session.getState() == SessionState.ENCRYPTED) {
             if (stanza.getInnerElements().isEmpty()) {
@@ -184,13 +195,13 @@ public class BoshHandler {
         }
     }
 
-    private void terminateSession(BoshBackedSessionContext session) {
+    protected void terminateSession(BoshBackedSessionContext session) {
         sessions.remove(session.getSessionId());
         session.writeBoshResponse(BoshStanzaUtils.TERMINATE_BOSH_RESPONSE);
         session.close();
     }
 
-    private void processStanza(BoshBackedSessionContext session, XMLElement element) {
+    protected void processStanza(BoshBackedSessionContext session, XMLElement element) {
         Stanza stanza;
         if (element instanceof Stanza) {
             stanza = (Stanza) element;
@@ -202,10 +213,14 @@ public class BoshHandler {
                 session.getStateHolder());
     }
 
-    private void createSession(BoshRequest br) throws IOException {
+    protected void createSession(BoshRequest br) throws IOException {
         final Stanza stanza = br.getBody();
 
-        BoshBackedSessionContext session = new BoshBackedSessionContext(this, serverRuntimeContext, inactivityChecker);
+        BoshBackedSessionContext session = createSessionContext();
+        if (session.propagateSessionContext() && br.getHttpServletRequest() != null) {
+            final HttpSession httpSession = br.getHttpServletRequest().getSession(true);
+            httpSession.setAttribute(BoshBackedSessionContext.HTTP_SESSION_ATTRIBUTE, session);
+        }
         
         final String contentAttribute = stanza.getAttributeValue("content");
         if (contentAttribute != null) session.setContentType(contentAttribute);
@@ -250,7 +265,7 @@ public class BoshHandler {
         session.writeBoshResponse(getSessionCreationResponse(session));
     }
 
-    private Stanza getSessionCreationResponse(BoshBackedSessionContext session) {
+    protected Stanza getSessionCreationResponse(BoshBackedSessionContext session) {
         StanzaBuilder body = BoshStanzaUtils.createBoshStanzaBuilder();
         body.addAttribute("wait", Integer.toString(session.getWait()));
         body.addAttribute("inactivity", Integer.toString(session.getInactivity()));
@@ -273,16 +288,4 @@ public class BoshHandler {
         return body.build();
 
     }
-
-    public Stanza addAttribute(Stanza stanza, String attributeName, String attributeValue) {
-        StanzaBuilder stanzaBuilder = BoshStanzaUtils.createBoshStanzaBuilder();
-        for (Attribute attr : stanza.getAttributes()) {
-            stanzaBuilder.addAttribute(attr);
-        }
-        stanzaBuilder.addAttribute(attributeName, attributeValue);
-        for (XMLElement element : stanza.getInnerElements()) {
-            stanzaBuilder.addPreparedElement(element);
-        }
-        return stanzaBuilder.build();
-    }
 }

Modified: mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java?rev=1348996&r1=1348995&r2=1348996&view=diff
==============================================================================
--- mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java (original)
+++ mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java Mon Jun 11 20:32:55 2012
@@ -56,7 +56,7 @@ public class BoshServlet extends HttpSer
 
     protected static final String SERVER_IDENTIFICATION = "Vysper/0.8";
 
-    protected final BoshHandler boshHandler = new BoshHandler();
+    protected BoshHandler boshHandler;
 
     protected List<String> accessControlAllowOrigin;
 
@@ -64,6 +64,14 @@ public class BoshServlet extends HttpSer
 
     protected String accessControlAllowMethods = "GET, POST, OPTIONS";
 
+    public BoshServlet() {
+        initBoshHandler();
+    }
+
+    protected void initBoshHandler() {
+        boshHandler = new BoshHandler();
+    }
+
     /**
      * Setter for the {@link ServerRuntimeContext}
      * @param serverRuntimeContext

Modified: mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContextTest.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContextTest.java?rev=1348996&r1=1348995&r2=1348996&view=diff
==============================================================================
--- mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContextTest.java (original)
+++ mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContextTest.java Mon Jun 11 20:32:55 2012
@@ -87,7 +87,7 @@ public class BoshBackedSessionContextTes
         httpServletRequest.setAttribute(eq("response"), EasyMock.<BoshResponse> capture(captured));
         mocksControl.replay();
 
-        BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(boshHandler, serverRuntimeContext, inactivityChecker);
+        BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(serverRuntimeContext, inactivityChecker);
         Stanza body = BoshStanzaUtils.EMPTY_BOSH_RESPONSE;
         boshBackedSessionContext.insertRequest(new BoshRequest(httpServletRequest, body, 1L));
         boshBackedSessionContext.writeBoshResponse(body);
@@ -101,7 +101,7 @@ public class BoshBackedSessionContextTes
     @Test
     public void testSetBoshVersion1() {
         mocksControl.replay();
-        BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(boshHandler, serverRuntimeContext, inactivityChecker);
+        BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(serverRuntimeContext, inactivityChecker);
         boshBackedSessionContext.setBoshVersion("1.8");
         assertEquals("1.8", boshBackedSessionContext.getBoshVersion());
         mocksControl.verify();
@@ -110,7 +110,7 @@ public class BoshBackedSessionContextTes
     @Test
     public void testSetBoshVersion2() {
         mocksControl.replay();
-        BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(boshHandler, serverRuntimeContext, inactivityChecker);
+        BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(serverRuntimeContext, inactivityChecker);
         boshBackedSessionContext.setBoshVersion("2.0");
         assertEquals("1.9", boshBackedSessionContext.getBoshVersion());
         mocksControl.verify();
@@ -146,7 +146,7 @@ public class BoshBackedSessionContextTes
 
         // write0
         mocksControl.replay();
-        BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(boshHandler, serverRuntimeContext, inactivityChecker);
+        BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(serverRuntimeContext, inactivityChecker);
         
         boshBackedSessionContext.insertRequest(br);
         listenerCaptured.getValue().onTimeout(asyncEvent);
@@ -192,7 +192,7 @@ public class BoshBackedSessionContextTes
         httpServletRequest1.setAttribute(eq("response"), EasyMock.<BoshResponse> capture(captured));
 
         mocksControl.replay();
-        BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(boshHandler, serverRuntimeContext, inactivityChecker);
+        BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(serverRuntimeContext, inactivityChecker);
 
         boshBackedSessionContext.setHold(2);
         // consecutive writes with RID 1 and 2
@@ -232,7 +232,7 @@ public class BoshBackedSessionContextTes
 
         mocksControl.replay();
 
-        BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(boshHandler,
+        BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(
                 serverRuntimeContext, inactivityChecker);
         boshBackedSessionContext.writeBoshResponse(body); // queued for merging
         boshBackedSessionContext.writeBoshResponse(body); // queued for merging