You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by fo...@apache.org on 2012/03/19 04:09:21 UTC
svn commit: r1302264 - in /mina/vysper/trunk: ./
nbxml/src/main/java/org/apache/vysper/xml/decoder/
nbxml/src/main/java/org/apache/vysper/xml/sax/impl/
nbxml/src/test/java/org/apache/vysper/xml/sax/impl/
nbxml/src/test/java/org/apache/vysper/xml/sax/pe...
Author: foodmike
Date: Mon Mar 19 03:09:21 2012
New Revision: 1302264
URL: http://svn.apache.org/viewvc?rev=1302264&view=rev
Log:
Fix to address VYSPER-18. Modifications to XML parsing/handling in order to recognize and act on stream close events. This fix adds a closed flag to the XMLElementListener that allows the XMPPDecoder to determine when a stream is closed.
Additionally added a check to the XMLTokenizer that allows it to ignore whitespace when it is in the START state. This prevents is from buffering unnecessary whitespace characters.
Modified:
mina/vysper/trunk/ (props changed)
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMLElementListener.java
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPContentHandler.java
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPDecoder.java
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/XMLTokenizer.java
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/XMPPContentHandlerTestCase.java
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/perf/PerfRunner.java
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/mina/XmppIoHandlerAdapter.java
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/parser/XMLParserUtil.java
mina/vysper/trunk/server/extensions/websockets/src/main/java/org/apache/vysper/xmpp/extension/websockets/WebSocketBackedSessionContext.java
Propchange: mina/vysper/trunk/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Mon Mar 19 03:09:21 2012
@@ -2,3 +2,6 @@ target
.settings
.classpath
.project
+lib
+bogus_mina_tls.cert
+spring-config.xml
Modified: mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMLElementListener.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMLElementListener.java?rev=1302264&r1=1302263&r2=1302264&view=diff
==============================================================================
--- mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMLElementListener.java (original)
+++ mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMLElementListener.java Mon Mar 19 03:09:21 2012
@@ -23,4 +23,6 @@ import org.apache.vysper.xml.fragment.XM
public interface XMLElementListener {
void element(XMLElement element);
+ void close();
+ boolean isClosed();
}
\ No newline at end of file
Modified: mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPContentHandler.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPContentHandler.java?rev=1302264&r1=1302263&r2=1302264&view=diff
==============================================================================
--- mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPContentHandler.java (original)
+++ mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPContentHandler.java Mon Mar 19 03:09:21 2012
@@ -83,8 +83,7 @@ public class XMPPContentHandler implemen
// complete stanza, emit
emit();
} else if (depth == 0) {
- // end stream:stream element
- // TODO handle
+ // End of stream. Handled in endDocument().
} else {
builder.endInnerElement();
}
@@ -137,9 +136,10 @@ public class XMPPContentHandler implemen
}
/**
- * {@inheritDoc}
+ * End of the XMPP stream. Tell the XML listener we're done.
*/
- public void endDocument() throws SAXException { /* ignore */
+ public void endDocument() throws SAXException {
+ this.listener.close();
}
/**
Modified: mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPDecoder.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPDecoder.java?rev=1302264&r1=1302263&r2=1302264&view=diff
==============================================================================
--- mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPDecoder.java (original)
+++ mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPDecoder.java Mon Mar 19 03:09:21 2012
@@ -34,7 +34,7 @@ import org.apache.vysper.xml.sax.impl.De
* @author The Apache MINA Project (dev@mina.apache.org)
*/
public class XMPPDecoder extends CumulativeProtocolDecoder {
-
+
private static final String XML_DECL = "<?xml";
private static final String STREAM_STREAM = "<stream:stream";
@@ -53,6 +53,7 @@ public class XMPPDecoder extends Cumulat
public static class MinaStanzaListener implements XMLElementListener {
private ProtocolDecoderOutput protocolDecoder;
+ private boolean closed = false;
public MinaStanzaListener(ProtocolDecoderOutput protocolDecoder) {
this.protocolDecoder = protocolDecoder;
@@ -65,6 +66,14 @@ public class XMPPDecoder extends Cumulat
protocolDecoder.write(element);
}
+
+ public void close() {
+ this.closed = true;
+ }
+
+ public boolean isClosed() {
+ return this.closed;
+ }
}
/**
@@ -90,11 +99,17 @@ public class XMPPDecoder extends Cumulat
}
XMPPContentHandler contentHandler = (XMPPContentHandler) reader.getContentHandler();
- contentHandler.setListener(new MinaStanzaListener(out));
+ XMLElementListener listener = new MinaStanzaListener(out);
+ contentHandler.setListener(listener);
reader.parse(in, CharsetUtil.UTF8_DECODER);
-
- // we have parsed what we got, invoke again when more data is available
- return false;
+
+ if (listener.isClosed()) {
+ session.close(true);
+ return true;
+ } else {
+ // we have parsed what we got, invoke again when more data is available
+ return false;
+ }
}
}
\ No newline at end of file
Modified: mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/XMLTokenizer.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/XMLTokenizer.java?rev=1302264&r1=1302263&r2=1302264&view=diff
==============================================================================
--- mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/XMLTokenizer.java (original)
+++ mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/XMLTokenizer.java Mon Mar 19 03:09:21 2012
@@ -55,7 +55,6 @@ public class XMLTokenizer {
/**
* @param byteBuffer
* @param charsetDecoder
- * @return the new particle or NULL, if the buffer was exhausted before the particle was completed
* @throws Exception
*/
public void parse(IoBuffer byteBuffer, CharsetDecoder decoder) throws SAXException {
@@ -66,6 +65,8 @@ public class XMLTokenizer {
if (c == '<') {
emit(c, byteBuffer);
state = State.IN_TAG;
+ } else if (Character.isWhitespace(c)) {
+ // ignore
} else {
state = State.IN_TEXT;
buffer.put((byte) c);
Modified: mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/XMPPContentHandlerTestCase.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/XMPPContentHandlerTestCase.java?rev=1302264&r1=1302263&r2=1302264&view=diff
==============================================================================
--- mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/XMPPContentHandlerTestCase.java (original)
+++ mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/XMPPContentHandlerTestCase.java Mon Mar 19 03:09:21 2012
@@ -39,10 +39,14 @@ public class XMPPContentHandlerTestCase
private static class TestListener implements XMLElementListener {
public List<XMLElement> elements = new ArrayList<XMLElement>();
+ private boolean closed = false;
public void element(XMLElement element) {
elements.add(element);
}
+
+ public void close() { closed = true; }
+ public boolean isClosed() { return closed; }
}
public void test() throws Exception {
@@ -63,6 +67,7 @@ public class XMPPContentHandlerTestCase
assertEquals("stanza", actual.next().getName());
assertEquals("message", actual.next().getName());
assertEquals("iq", actual.next().getName());
+ assertTrue(listener.isClosed());
}
private void parse(NonBlockingXMLReader reader, String xml) throws Exception {
Modified: mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/perf/PerfRunner.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/perf/PerfRunner.java?rev=1302264&r1=1302263&r2=1302264&view=diff
==============================================================================
--- mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/perf/PerfRunner.java (original)
+++ mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/perf/PerfRunner.java Mon Mar 19 03:09:21 2012
@@ -39,7 +39,9 @@ public class PerfRunner {
public void element(XMLElement element) {
counter++;
}
-
+
+ public void close() {}
+ public boolean isClosed() { return false; }
}
private static final String SINGLE_LEVEL_XML = "<child att='foo' att2='bar'></child>";
Modified: mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/mina/XmppIoHandlerAdapter.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/mina/XmppIoHandlerAdapter.java?rev=1302264&r1=1302263&r2=1302264&view=diff
==============================================================================
--- mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/mina/XmppIoHandlerAdapter.java (original)
+++ mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/mina/XmppIoHandlerAdapter.java Mon Mar 19 03:09:21 2012
@@ -31,6 +31,7 @@ import org.apache.vysper.xmpp.protocol.S
import org.apache.vysper.xmpp.protocol.StreamErrorCondition;
import org.apache.vysper.xmpp.server.ServerRuntimeContext;
import org.apache.vysper.xmpp.server.SessionContext;
+import org.apache.vysper.xmpp.server.SessionContext.SessionTerminationCause;
import org.apache.vysper.xmpp.server.response.ServerErrorResponses;
import org.apache.vysper.xmpp.stanza.Stanza;
import org.slf4j.Logger;
@@ -47,6 +48,8 @@ public class XmppIoHandlerAdapter implem
public static final String ATTRIBUTE_VYSPER_SESSIONSTATEHOLDER = "vysperSessionStateHolder";
+ public static final String ATTRIBUTE_VYSPER_TERMINATE_REASON = "vysperTerminateReason";
+
final Logger logger = LoggerFactory.getLogger(XmppIoHandlerAdapter.class);
private ServerRuntimeContext serverRuntimeContext;
@@ -106,6 +109,7 @@ public class XmppIoHandlerAdapter implem
SessionContext sessionContext = new MinaBackedSessionContext(serverRuntimeContext, stateHolder, ioSession);
ioSession.setAttribute(ATTRIBUTE_VYSPER_SESSION, sessionContext);
ioSession.setAttribute(ATTRIBUTE_VYSPER_SESSIONSTATEHOLDER, stateHolder);
+ ioSession.setAttribute(ATTRIBUTE_VYSPER_TERMINATE_REASON, SessionTerminationCause.CLIENT_BYEBYE);
}
public void sessionOpened(IoSession ioSession) throws Exception {
@@ -114,10 +118,11 @@ public class XmppIoHandlerAdapter implem
public void sessionClosed(IoSession ioSession) throws Exception {
SessionContext sessionContext = extractSession(ioSession);
+ SessionTerminationCause cause = (SessionTerminationCause) ioSession.getAttribute(ATTRIBUTE_VYSPER_TERMINATE_REASON);
String sessionId = "UNKNOWN";
if (sessionContext != null) {
sessionId = sessionContext.getSessionId();
- sessionContext.endSession(SessionContext.SessionTerminationCause.CONNECTION_ABORT);
+ sessionContext.endSession(cause);
}
logger.info("session {} has been closed", sessionId);
}
@@ -129,12 +134,17 @@ public class XmppIoHandlerAdapter implem
public void exceptionCaught(IoSession ioSession, Throwable throwable) throws Exception {
SessionContext sessionContext = extractSession(ioSession);
-
+
+ // Assume that the connection was aborted for now. Might be different depending on
+ // cause of exception determined below.
+ ioSession.setAttribute(ATTRIBUTE_VYSPER_TERMINATE_REASON, SessionTerminationCause.CONNECTION_ABORT);
+
Stanza errorStanza;
if(throwable.getCause() != null && throwable.getCause() instanceof SAXParseException) {
logger.info("Client sent not well-formed XML, closing session", throwable);
errorStanza = ServerErrorResponses.getStreamError(StreamErrorCondition.XML_NOT_WELL_FORMED,
sessionContext.getXMLLang(), "Stanza not well-formed", null);
+ ioSession.setAttribute(ATTRIBUTE_VYSPER_TERMINATE_REASON, SessionTerminationCause.STREAM_ERROR);
} else if(throwable instanceof WriteToClosedSessionException) {
// ignore
return;
@@ -145,8 +155,8 @@ public class XmppIoHandlerAdapter implem
logger.warn("error caught on transportation layer", throwable);
errorStanza = ServerErrorResponses.getStreamError(StreamErrorCondition.UNDEFINED_CONDITION,
sessionContext.getXMLLang(), "Unknown error", null);
+ ioSession.setAttribute(ATTRIBUTE_VYSPER_TERMINATE_REASON, SessionTerminationCause.STREAM_ERROR);
}
sessionContext.getResponseWriter().write(errorStanza);
- sessionContext.endSession(SessionContext.SessionTerminationCause.STREAM_ERROR);
}
}
Modified: mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/parser/XMLParserUtil.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/parser/XMLParserUtil.java?rev=1302264&r1=1302263&r2=1302264&view=diff
==============================================================================
--- mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/parser/XMLParserUtil.java (original)
+++ mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/parser/XMLParserUtil.java Mon Mar 19 03:09:21 2012
@@ -41,7 +41,7 @@ public class XMLParserUtil {
/**
* Parses a complete XML document. If the XML string contains errors, a
- * {@link SAXException} will be trown. If the XML string is not a complete
+ * {@link SAXException} will be thrown. If the XML string is not a complete
* XML document, null will be returned
* @param xml A string with a complete XML document
* @return
@@ -60,6 +60,8 @@ public class XMLParserUtil {
public void element(XMLElement element) {
documents.add(element);
}
+ public void close() {}
+ public boolean isClosed() { return false; }
});
IoBuffer buffer = IoBuffer.wrap(xml.getBytes("UTF-8"));
Modified: mina/vysper/trunk/server/extensions/websockets/src/main/java/org/apache/vysper/xmpp/extension/websockets/WebSocketBackedSessionContext.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/websockets/src/main/java/org/apache/vysper/xmpp/extension/websockets/WebSocketBackedSessionContext.java?rev=1302264&r1=1302263&r2=1302264&view=diff
==============================================================================
--- mina/vysper/trunk/server/extensions/websockets/src/main/java/org/apache/vysper/xmpp/extension/websockets/WebSocketBackedSessionContext.java (original)
+++ mina/vysper/trunk/server/extensions/websockets/src/main/java/org/apache/vysper/xmpp/extension/websockets/WebSocketBackedSessionContext.java Mon Mar 19 03:09:21 2012
@@ -60,6 +60,7 @@ public class WebSocketBackedSessionConte
private Connection outbound;
private NonBlockingXMLReader xmlReader = new DefaultNonBlockingXMLReader();
+ private boolean closed = false;
public WebSocketBackedSessionContext(ServerRuntimeContext serverRuntimeContext) {
super(serverRuntimeContext, new SessionStateHolder());
@@ -174,7 +175,13 @@ public class WebSocketBackedSessionConte
*/
public void close() {
// TODO how to handle?
+ closed = true;
+ }
+
+ /**
+ * Implementation for XMLElementListener.
+ */
+ public boolean isClosed() {
+ return closed;
}
-
-
}
Re: svn commit: r1302264 - in /mina/vysper/trunk: ./
nbxml/src/main/java/org/apache/vysper/xml/decoder/
nbxml/src/main/java/org/apache/vysper/xml/sax/impl/
nbxml/src/test/java/org/apache/vysper/xml/sax/impl/
nbxml/src/test/java/org/apache/vysper/xml/sa...
Posted by Mike Mahoney <mi...@thingworx.com>.
On Mar 21, 2012, at 12:42 PM, Bernd Fondermann wrote:
> But why do notable implementations like MinaStanzaListener and
> WebSocketBackedSessionContext record the 'closed' state, but beyond that
> do not honour it? I suggest they should simply stop whatever they do.
So, basically no protocolDecoder.write(element) call if the state is closed? That makes sense, but since a new MinaStanzaListener is created on every pass through doDecode, does it matter?
> Another way to go (and I'd prefer that ATM) would be to move close(),
> isClosed() down to MinaStanzaListener. It is not needed anywhere else.
This makes sense. I'll move it out of XMLElementListener and only implement it in MinaStanzaListener.
-Mike
Re: svn commit: r1302264 - in /mina/vysper/trunk: ./ nbxml/src/main/java/org/apache/vysper/xml/decoder/
nbxml/src/main/java/org/apache/vysper/xml/sax/impl/ nbxml/src/test/java/org/apache/vysper/xml/sax/impl/
nbxml/src/test/java/org/apache/vysper/xml/sax/pe...
Posted by Bernd Fondermann <bf...@brainlounge.de>.
Some thoughts and questions regarding this change.
Interface XMLElementListener now has a close() method. So far, so good.
But why do notable implementations like MinaStanzaListener and
WebSocketBackedSessionContext record the 'closed' state, but beyond that
do not honour it? I suggest they should simply stop whatever they do.
Another way to go (and I'd prefer that ATM) would be to move close(),
isClosed() down to MinaStanzaListener. It is not needed anywhere else.
Bernd
On 19.03.12 04:09, foodmike@apache.org wrote:
> Author: foodmike
> Date: Mon Mar 19 03:09:21 2012
> New Revision: 1302264
>
> URL: http://svn.apache.org/viewvc?rev=1302264&view=rev
> Log:
> Fix to address VYSPER-18. Modifications to XML parsing/handling in order to recognize and act on stream close events. This fix adds a closed flag to the XMLElementListener that allows the XMPPDecoder to determine when a stream is closed.