uk.org.retep.util.nio.StAXSocketProcessorHandler Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2009, Peter T Mount
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the retep.org.uk nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package uk.org.retep.util.nio;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.annotation.concurrent.ThreadSafe;
import org.w3c.dom.Document;
import uk.org.retep.util.xml.XMLStreamParser;
/**
* Base class for SocketProcessorHandler's that require StAX support
*
* @param Type of the containing DelegatingSocketProcessor
* @author peter
* @since 9.4
*/
@ThreadSafe
public abstract class StAXSocketProcessorHandler
extends SocketProcessorHandler
implements XMLStreamParser.Listener
{
private XMLStreamParser parser;
private ByteBufferInputStream inputStream;
private XMLStreamReader xmlStreamReader;
/**
*
* @param processor The DelegatingSocketProcessor that owns this handler
* @param channel SocketChannel for this instance, ignored if this is
* shared by the DelegatingSocketProcessor implementation
* @throws ParserConfigurationException if the Document could not be created
* @throws XMLStreamException
*/
@SuppressWarnings( "unchecked" )
public StAXSocketProcessorHandler( final P processor,
final SocketChannel channel )
throws ParserConfigurationException,
XMLStreamException
{
super( processor, channel );
parser = new XMLStreamParser( createDocument() );
parser.addListener( this );
}
/**
* Create the Document to parse into. The default implementation creates a
* namespaceAware document.
*
* @return Document
* @throws javax.xml.parsers.ParserConfigurationException
*/
protected abstract Document createDocument()
throws ParserConfigurationException;
/**
* Create an XMLStreamReader to read from the given InputStream
* @param inputStream InputStream
* @return XMLStreamReader
* @throws javax.xml.stream.XMLStreamException
*/
protected abstract XMLStreamReader createXMLStreamReader(
final InputStream inputStream )
throws XMLStreamException;
protected final XMLStreamReader getXMLStreamReader( final ByteBuffer buffer )
throws XMLStreamException
{
// Remove the InputStream if it's not for this buffer
// if( inputStream != null && inputStream.getBuffer() != buffer )
// {
// inputStream = null;
// }
if( inputStream == null )
{
inputStream = new ByteBufferInputStream( buffer );
// if( xmlStreamReader != null )
// {
// try
// {
// xmlStreamReader.close();
// }
// finally
// {
// xmlStreamReader = null;
// }
// }
}
if( xmlStreamReader == null )
{
xmlStreamReader = createXMLStreamReader( inputStream );
}
return xmlStreamReader;
}
@Override
public void read( final SocketChannel channel, final ByteBuffer buffer )
throws IOException
{
try
{
getLog().info( "A %d %d", buffer.position(), buffer.limit() );
getXMLStreamReader( buffer );
getLog().info( "B %d %d", buffer.position(), buffer.limit() );
do
{
while( xmlStreamReader.hasNext() )
{
getLog().info( "C %d %d", buffer.position(), buffer.limit() );
parser.processEvents( xmlStreamReader );
}
getLog().info( "D %d %d", buffer.position(), buffer.limit() );
} while( inputStream.available() > 0 );
getLog().info( "E %d %d", buffer.position(), buffer.limit() );
}
catch( XMLStreamException ex )
{
parser.notifyStreamError( ex );
throw new IOException( ex );
}
}
@Override
public void closing( final SocketChannel channel )
{
if( parser != null )
{
parser.notifyStreamClosed();
parser.removeListener( this );
parser = null;
}
if( xmlStreamReader != null )
{
try
{
xmlStreamReader.close();
}
catch( XMLStreamException ex )
{
getLog().info( "Exception closing XMLStreamParser", ex );
}
xmlStreamReader = null;
}
super.closing( channel );
}
@Override
public void STaXThreadClosed( XMLStreamParser t )
{
}
@Override
public void STaXThreadError( XMLStreamParser t, Exception e )
{
}
}