org.apache.camel.converter.jaxp.XMLStreamReaderInputStream Maven / Gradle / Ivy
The newest version!
/*
* 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.camel.converter.jaxp;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
/**
*
*/
class XMLStreamReaderInputStream extends InputStream {
private static final int BUFFER_SIZE = 4096;
private XMLStreamReader reader;
private XMLStreamWriter writer;
private TrimmableByteArrayOutputStream chunk;
private byte[] buffer;
private String charset;
private int bpos;
XMLStreamReaderInputStream(XMLStreamReader reader, String charset, XMLOutputFactory outfactory) {
this.reader = reader;
this.buffer = new byte[BUFFER_SIZE];
this.chunk = new TrimmableByteArrayOutputStream();
this.charset = charset == null ? "utf-8" : charset;
try {
this.writer = outfactory.createXMLStreamWriter(chunk, this.charset);
} catch (XMLStreamException e) {
//ignore
}
}
XMLStreamReaderInputStream(XMLStreamReader reader, XMLOutputFactory outfactory) {
this(reader, "utf-8", outfactory);
}
@Override
public int read() throws IOException {
byte[] ba = new byte[1];
return read(ba, 0, 1) == 1 ? ba[0] : -1;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int tlen = 0;
while (len > 0) {
int n = ensureBuffering(len);
if (n < 0) {
break;
}
int clen = len > n ? n : len;
System.arraycopy(buffer, 0, b, off, clen);
System.arraycopy(buffer, clen, buffer, 0, buffer.length - clen);
bpos -= clen;
len -= clen;
off += clen;
tlen += clen;
}
return tlen > 0 ? tlen : -1;
}
private int ensureBuffering(int size) throws IOException {
if (size < bpos) {
return bpos;
}
// refill the buffer as more buffering is requested than the current buffer status
try {
// very first event
if (XMLStreamConstants.START_DOCUMENT == reader.getEventType()) {
writer.writeStartDocument(charset, "1.0");
}
if (chunk.size() < buffer.length) {
while (reader.hasNext()) {
int code = reader.next();
switch (code) {
case XMLStreamConstants.END_DOCUMENT:
writer.writeEndDocument();
break;
case XMLStreamConstants.START_ELEMENT:
QName qname = reader.getName();
writer.writeStartElement(qname.getPrefix(), qname.getLocalPart(), qname.getNamespaceURI());
for (int i = 0; i < reader.getAttributeCount(); i++) {
String namespaceUri = reader.getAttributeNamespace(i);
writer.writeAttribute(reader.getAttributePrefix(i), namespaceUri == null ? "" : namespaceUri, reader.getAttributeLocalName(i),
reader.getAttributeValue(i));
}
for (int i = 0; i < reader.getNamespaceCount(); i++) {
String namespacePrefix = reader.getNamespacePrefix(i);
String namespaceURI = reader.getNamespaceURI(i);
writer.writeNamespace(namespacePrefix == null ? "" : namespacePrefix, namespaceURI == null ? "" : namespaceURI);
}
break;
case XMLStreamConstants.END_ELEMENT:
writer.writeEndElement();
break;
case XMLStreamConstants.CHARACTERS:
writer.writeCharacters(reader.getText());
break;
case XMLStreamConstants.COMMENT:
writer.writeComment(reader.getText());
break;
case XMLStreamConstants.CDATA:
writer.writeCData(reader.getText());
break;
default:
break;
}
// check if the chunk is full
final int csize = buffer.length - bpos;
if (chunk.size() > csize) {
System.arraycopy(chunk.getByteArray(), 0, buffer, bpos, csize);
bpos = buffer.length;
chunk.trim(csize, 0);
return buffer.length;
}
}
}
final int csize = chunk.size() < buffer.length - bpos ? chunk.size() : buffer.length - bpos;
if (csize > 0) {
System.arraycopy(chunk.getByteArray(), 0, buffer, bpos, csize);
bpos += csize;
chunk.trim(csize, 0);
return bpos;
} else {
return bpos > 0 ? bpos : -1;
}
} catch (XMLStreamException e) {
throw new IOException(e);
}
}
static class TrimmableByteArrayOutputStream extends ByteArrayOutputStream {
public void trim(int head, int tail) {
System.arraycopy(buf, head, buf, 0, count - head - tail);
count -= head + tail;
}
public byte[] toByteArray(int len) {
byte[] b = new byte[len];
System.arraycopy(buf, 0, b, 0, len);
return b;
}
byte[] getByteArray() {
return buf;
}
}
}