Author: ngn
Date: Sat Jun 12 20:53:38 2010
New Revision: 954138
URL: http://svn.apache.org/viewvc?rev=954138&view=rev
Log:
Adding XML parsing to the BOSH implementation (by Bogdan Pistol) (VYSPER-207)
Added:
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshDecoder.java
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java
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/BoshServlet.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=954138&r1=954137&r2=954138&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
Sat Jun 12 20:53:38 2010
@@ -19,11 +19,9 @@
*/
package org.apache.vysper.xmpp.extension.xep0124;
-import org.apache.mina.core.future.CloseFuture;
-import org.apache.mina.core.future.IoFuture;
-import org.apache.mina.core.future.IoFutureListener;
-import org.apache.mina.core.session.IoSession;
-import org.apache.vysper.mina.codec.StanzaWriteInfo;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
import org.apache.vysper.xmpp.protocol.SessionStateHolder;
import org.apache.vysper.xmpp.server.AbstractSessionContext;
import org.apache.vysper.xmpp.server.ServerRuntimeContext;
@@ -34,29 +32,32 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * connects MINA 2 frontend to the vysper backend through the Bosh protocol
+ * Keeps the session state
*
* @author The Apache MINA Project ([email protected])
*/
public class BoshBackedSessionContext extends AbstractSessionContext implements
- StanzaWriter, IoFutureListener {
+ StanzaWriter {
- final Logger logger = LoggerFactory
+ private final Logger logger = LoggerFactory
.getLogger(BoshBackedSessionContext.class);
- private IoSession minaSession;
+ private final BoshDecoder boshDecoder;
- private boolean openingStanzaWritten = false;
+ private HttpServletRequest httpRequest;
- protected CloseFuture closeFuture;
+ private HttpServletResponse httpRespone;
+ /**
+ * Creates a new context for a session
+ * @param serverRuntimeContext
+ * @param boshHandler
+ */
public BoshBackedSessionContext(ServerRuntimeContext serverRuntimeContext,
- SessionStateHolder sessionStateHolder, IoSession minaSession) {
- super(serverRuntimeContext, sessionStateHolder);
- this.minaSession = minaSession;
- closeFuture = minaSession.getCloseFuture();
- closeFuture.addListener(this);
- sessionStateHolder.setState(SessionState.INITIATED); // connection
established
+ BoshHandler boshHandler) {
+ super(serverRuntimeContext, new SessionStateHolder());
+ sessionStateHolder.setState(SessionState.INITIATED);
+ boshDecoder = new BoshDecoder(boshHandler, this);
}
public StanzaWriter getResponseWriter() {
@@ -64,27 +65,54 @@ public class BoshBackedSessionContext ex
}
public void setIsReopeningXMLStream() {
- openingStanzaWritten = false;
}
public void write(Stanza stanza) {
- minaSession.write(new StanzaWriteInfo(stanza, !openingStanzaWritten));
- openingStanzaWritten = true;
+ // minaSession.write(new StanzaWriteInfo(stanza,
!openingStanzaWritten));
}
public void close() {
logger.info("session will be closed now");
- closeFuture.setClosed();
- minaSession.close(true);
}
- public void operationComplete(IoFuture ioFuture) {
- // close future notification
- logger.info("close future called");
+ public void switchToTLS() {
+ // BOSH cannot switch dynamically,
+ // SSL can be enabled/disabled in BoshEndpoint#setSSLEnabled()
}
- public void switchToTLS() {
- // Bosh cannot switch dynamically
- // SSL can be enabled/disabled in BoshEndpoint#setSslEnabled()
+ /**
+ * Updates the context with the session's {...@link HttpServletRequest}
and {...@link HttpServletResponse}
+ * <p>
+ * The HTTP context is updated every time a new HTTP request is received.
+ * @param req
+ * @param resp
+ */
+ public void setHttpContext(HttpServletRequest req, HttpServletResponse
resp) {
+ httpRequest = req;
+ httpRespone = resp;
+ }
+
+ /**
+ * Getter for the HTTP request
+ * @return
+ */
+ public HttpServletRequest getHttpRequest() {
+ return httpRequest;
+ }
+
+ /**
+ * Getter for the HTTP response
+ * @return
+ */
+ public HttpServletResponse getHttpResponse() {
+ return httpRespone;
+ }
+
+ /**
+ * Getter for the decoder
+ * @return
+ */
+ public BoshDecoder getDecoder() {
+ return boshDecoder;
}
}
Added:
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshDecoder.java
URL:
http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshDecoder.java?rev=954138&view=auto
==============================================================================
---
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshDecoder.java
(added)
+++
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshDecoder.java
Sat Jun 12 20:53:38 2010
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.vysper.xmpp.extension.xep0124;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.mina.core.buffer.IoBuffer;
+import org.apache.vysper.charset.CharsetUtil;
+import org.apache.vysper.mina.codec.StanzaBuilderFactory;
+import org.apache.vysper.xml.decoder.XMPPContentHandler;
+import org.apache.vysper.xml.decoder.XMPPContentHandler.StanzaListener;
+import org.apache.vysper.xml.fragment.XMLElement;
+import org.apache.vysper.xml.sax.NonBlockingXMLReader;
+import org.apache.vysper.xml.sax.impl.DefaultNonBlockingXMLReader;
+import org.apache.vysper.xmpp.server.SessionContext;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.xml.sax.SAXException;
+
+/**
+ * Decodes bytes into BOSH stanzas
+ * <p>
+ * Uses nbxml for XML processing.
+ * Every HTTP session has its own instance of BoshDecoder
+ * (because decoding state is associated with the decoder, and to ensure that
+ * the decoding errors of a session do not affect another session).
+ *
+ * @author The Apache MINA Project ([email protected])
+ */
+public class BoshDecoder implements StanzaListener {
+
+ private final BoshHandler boshHandler;
+
+ private final NonBlockingXMLReader reader;
+
+ private final BoshBackedSessionContext sessionContext;
+
+ /**
+ * Creates a new decoder associated with a {...@link SessionContext}
+ * @param boshHandler
+ * @param sessionContext
+ */
+ public BoshDecoder(BoshHandler boshHandler,
+ BoshBackedSessionContext sessionContext) {
+ this.boshHandler = boshHandler;
+ this.sessionContext = sessionContext;
+ reader = new DefaultNonBlockingXMLReader();
+ XMPPContentHandler contentHandler = new XMPPContentHandler(
+ new StanzaBuilderFactory());
+ contentHandler.setListener(this);
+ reader.setContentHandler(contentHandler);
+ }
+
+ /**
+ * Decodes the bytes from the {...@link InputStream} provided by the
current {...@link HttpServletRequest} of
+ * the session context into BOSH stanzas.
+ * @throws IOException
+ * @throws SAXException
+ */
+ public void decode() throws IOException, SAXException {
+ IoBuffer ioBuf = IoBuffer.allocate(1024);
+ ioBuf.setAutoExpand(true);
+ byte[] buf = new byte[1024];
+ InputStream in = sessionContext.getHttpRequest().getInputStream();
+
+ for (;;) {
+ int i = in.read(buf);
+ if (i == -1) {
+ break;
+ }
+ ioBuf.put(buf, 0, i);
+ }
+ ioBuf.flip();
+ reader.parse(ioBuf, CharsetUtil.UTF8_DECODER);
+ }
+
+ public void stanza(XMLElement element) {
+ boshHandler.processStanza(sessionContext, (Stanza) element);
+ }
+
+}
\ No newline at end of file
Added:
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=954138&view=auto
==============================================================================
---
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java
(added)
+++
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java
Sat Jun 12 20:53:38 2010
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.vysper.xmpp.extension.xep0124;
+
+import java.io.IOException;
+import java.util.Random;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.vysper.xmpp.stanza.Stanza;
+
+/**
+ * Processes the BOSH requests from the clients and then responds back
+ *
+ * @author The Apache MINA Project ([email protected])
+ */
+public class BoshHandler {
+
+ /**
+ * Handles the BOSH stanzas received from the decoder
+ * @param sessionContext
+ * @param stanza
+ */
+ public void processStanza(BoshBackedSessionContext sessionContext,
+ Stanza stanza) {
+
+ // TODO
+ HttpServletResponse resp = sessionContext.getHttpResponse();
+ String sid = Long.toString(new Random().nextLong(), 16);
+ resp.setContentType("text/xml; charset=UTF-8");
+ try {
+ resp.getWriter().print("<body
xmlns='http://jabber.org/protocol/httpbind' wait='60' inactivity='60'
polling='5' requests='2' hold='1' maxpause='120' sid='");
+ resp.getWriter().print(sid);
+ resp.getWriter().print("' ver='1.6' from='vysper.org'/>");
+ resp.flushBuffer();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+}
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=954138&r1=954137&r2=954138&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
Sat Jun 12 20:53:38 2010
@@ -20,20 +20,20 @@
package org.apache.vysper.xmpp.extension.xep0124;
import java.io.BufferedInputStream;
-import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
-import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
import org.apache.vysper.xmpp.server.ServerRuntimeContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
/**
* Handles BOSH requests from HTTP clients.
@@ -51,8 +51,12 @@ public class BoshServlet extends HttpSer
private static final String XML_CONTENT_TYPE = "text/xml; charset=UTF-8";
private static final String INFO_GET = "This is an XMPP BOSH connection
manager, you need to use a compatible BOSH client to use its services!";
+
+ private static final String SESSION_CONTEXT_ATTRIBUTE =
"SESSION_CONTEXT_ATTRIBUTE";
private final Logger logger = LoggerFactory.getLogger(BoshServlet.class);
+
+ private final BoshHandler boshHandler = new BoshHandler();
private ServerRuntimeContext serverRuntimeContext;
@@ -103,39 +107,26 @@ public class BoshServlet extends HttpSer
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
- BufferedReader reader = req.getReader();
-
- char[] buf = new char[1024];
- StringBuilder sb = new StringBuilder();
-
- for (;;) {
- int n = reader.read(buf);
- if (n == -1) {
- break;
- }
- sb.append(buf, 0, n);
+ HttpSession httpSession = req.getSession(true);
+ BoshBackedSessionContext sessionContext = (BoshBackedSessionContext)
httpSession.getAttribute(SESSION_CONTEXT_ATTRIBUTE);
+ if (sessionContext == null) {
+ sessionContext = new
BoshBackedSessionContext(serverRuntimeContext, boshHandler);
+ httpSession.setAttribute(SESSION_CONTEXT_ATTRIBUTE,
sessionContext);
}
-
- String body = sb.toString();
- logger.debug("BOSH CM received : {}", body);
-
- // test if this is the first request (kind of a hack - should be
parsing XML)
- if (body.indexOf("sid=") == -1) {
- // initial request
- String sid = Long.toString(new Random().nextLong(), 16);
- resp.setContentType(XML_CONTENT_TYPE);
- resp.getWriter()
- .print("<body xmlns='http://jabber.org/protocol/httpbind'
wait='60' inactivity='60' polling='5' requests='2' hold='1' maxpause='120'
sid='");
- resp.getWriter().print(sid);
- resp.getWriter().print("' ver='1.6' from='vysper.org'/>");
- resp.flushBuffer();
- return;
+
+ /*
+ * The following block is synchronized on the session context to
prevent simultaneous
+ * access from a session (simultaneous access is possible in certain
cases because of the
+ * nature of HTTP sessions tracking mechanism - cookies, URL rewrites,
etc).
+ */
+ synchronized (sessionContext) {
+ sessionContext.setHttpContext(req, resp);
+ try {
+ sessionContext.getDecoder().decode();
+ } catch (SAXException e) {
+ logger.error("Exception thrown while decoding XML", e);
+ }
}
-
- // session exists
- // not handled yet, TODO
- resp.setContentType(XML_CONTENT_TYPE);
- resp.flushBuffer();
}
}