org.postgresql.jdbc.PgSQLXML Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mogdb-jdbc Show documentation
Show all versions of mogdb-jdbc Show documentation
Java JDBC driver for MogDB
/*
* Copyright (c) 2004, PostgreSQL Global Development Group
* See the LICENSE file in the project root for more information.
*/
package io.mogdb.jdbc;
import io.mogdb.core.BaseConnection;
import io.mogdb.util.GT;
import io.mogdb.util.PSQLException;
import io.mogdb.util.PSQLState;
import io.mogdb.xml.DefaultPGXmlFactoryFactory;
import io.mogdb.xml.PGXmlFactoryFactory;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.sql.SQLException;
import java.sql.SQLXML;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stax.StAXResult;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
public class PgSQLXML implements SQLXML {
private final BaseConnection _conn;
private String _data; // The actual data contained.
private boolean _initialized; // Has someone assigned the data for this object?
private boolean _active; // Is anyone in the process of loading data into us?
private boolean _freed;
private ByteArrayOutputStream _byteArrayOutputStream;
private StringWriter _stringWriter;
private DOMResult _domResult;
public PgSQLXML(BaseConnection conn) {
this(conn, null, false);
}
public PgSQLXML(BaseConnection conn, String data) {
this(conn, data, true);
}
private PgSQLXML(BaseConnection conn, String data, boolean initialized) {
_conn = conn;
_data = data;
_initialized = initialized;
_active = false;
_freed = false;
}
private PGXmlFactoryFactory getXmlFactoryFactory() throws SQLException {
if (_conn != null) {
return _conn.getXmlFactoryFactory();
}
return DefaultPGXmlFactoryFactory.INSTANCE;
}
public synchronized void free() {
_freed = true;
_data = null;
}
public synchronized InputStream getBinaryStream() throws SQLException {
checkFreed();
ensureInitialized();
if (_data == null) {
return null;
}
try {
return new ByteArrayInputStream(_conn.getEncoding().encode(_data));
} catch (IOException ioe) {
// This should be a can't happen exception. We just
// decoded this data, so it would be surprising that
// we couldn't encode it.
// For this reason don't make it translatable.
throw new PSQLException("Failed to re-encode xml data.", PSQLState.DATA_ERROR, ioe);
}
}
public synchronized Reader getCharacterStream() throws SQLException {
checkFreed();
ensureInitialized();
if (_data == null) {
return null;
}
return new StringReader(_data);
}
// We must implement this unsafely because that's what the
// interface requires. Because it says we're returning T
// which is unknown, none of the return values can satisfy it
// as Java isn't going to understand the if statements that
// ensure they are the same.
//
public synchronized T getSource(Class sourceClass) throws SQLException {
checkFreed();
ensureInitialized();
if (_data == null) {
return null;
}
try {
if (sourceClass == null || DOMSource.class.equals(sourceClass)) {
DocumentBuilder builder = getXmlFactoryFactory().newDocumentBuilder();
InputSource input = new InputSource(new StringReader(_data));
return (T) new DOMSource(builder.parse(input));
} else if (SAXSource.class.equals(sourceClass)) {
XMLReader reader = getXmlFactoryFactory().createXMLReader();
InputSource is = new InputSource(new StringReader(_data));
return (T) new SAXSource(reader, is);
} else if (StreamSource.class.equals(sourceClass)) {
return (T) new StreamSource(new StringReader(_data));
} else if (StAXSource.class.equals(sourceClass)) {
XMLInputFactory xif = getXmlFactoryFactory().newXMLInputFactory();
XMLStreamReader xsr = xif.createXMLStreamReader(new StringReader(_data));
return (T) new StAXSource(xsr);
}
} catch (Exception e) {
throw new PSQLException(GT.tr("Unable to decode xml data."), PSQLState.DATA_ERROR, e);
}
throw new PSQLException(GT.tr("Unknown XML Source class: {0}", sourceClass),
PSQLState.INVALID_PARAMETER_TYPE);
}
public synchronized String getString() throws SQLException {
checkFreed();
ensureInitialized();
return _data;
}
public synchronized OutputStream setBinaryStream() throws SQLException {
checkFreed();
initialize();
_active = true;
_byteArrayOutputStream = new ByteArrayOutputStream();
return _byteArrayOutputStream;
}
public synchronized Writer setCharacterStream() throws SQLException {
checkFreed();
initialize();
_stringWriter = new StringWriter();
return _stringWriter;
}
public synchronized T setResult(Class resultClass) throws SQLException {
checkFreed();
initialize();
if (resultClass == null || DOMResult.class.equals(resultClass)) {
_domResult = new DOMResult();
_active = true;
return (T) _domResult;
} else if (SAXResult.class.equals(resultClass)) {
try {
SAXTransformerFactory transformerFactory = getXmlFactoryFactory().newSAXTransformerFactory();
TransformerHandler transformerHandler = transformerFactory.newTransformerHandler();
_stringWriter = new StringWriter();
transformerHandler.setResult(new StreamResult(_stringWriter));
_active = true;
return (T) new SAXResult(transformerHandler);
} catch (TransformerException te) {
throw new PSQLException(GT.tr("Unable to create SAXResult for SQLXML."),
PSQLState.UNEXPECTED_ERROR, te);
}
} else if (StreamResult.class.equals(resultClass)) {
_stringWriter = new StringWriter();
_active = true;
return (T) new StreamResult(_stringWriter);
} else if (StAXResult.class.equals(resultClass)) {
_stringWriter = new StringWriter();
try {
XMLOutputFactory xof = getXmlFactoryFactory().newXMLOutputFactory();
XMLStreamWriter xsw = xof.createXMLStreamWriter(_stringWriter);
_active = true;
return (T) new StAXResult(xsw);
} catch (XMLStreamException xse) {
throw new PSQLException(GT.tr("Unable to create StAXResult for SQLXML"),
PSQLState.UNEXPECTED_ERROR, xse);
}
}
throw new PSQLException(GT.tr("Unknown XML Result class: {0}", resultClass),
PSQLState.INVALID_PARAMETER_TYPE);
}
public synchronized void setString(String value) throws SQLException {
checkFreed();
initialize();
_data = value;
}
private void checkFreed() throws SQLException {
if (_freed) {
throw new PSQLException(GT.tr("This SQLXML object has already been freed."),
PSQLState.OBJECT_NOT_IN_STATE);
}
}
private void ensureInitialized() throws SQLException {
if (!_initialized) {
throw new PSQLException(
GT.tr(
"This SQLXML object has not been initialized, so you cannot retrieve data from it."),
PSQLState.OBJECT_NOT_IN_STATE);
}
// Is anyone loading data into us at the moment?
if (!_active) {
return;
}
if (_byteArrayOutputStream != null) {
try {
_data = _conn.getEncoding().decode(_byteArrayOutputStream.toByteArray());
} catch (IOException ioe) {
throw new PSQLException(GT.tr("Failed to convert binary xml data to encoding: {0}.",
_conn.getEncoding().name()), PSQLState.DATA_ERROR, ioe);
} finally {
_byteArrayOutputStream = null;
_active = false;
}
} else if (_stringWriter != null) {
// This is also handling the work for Stream, SAX, and StAX Results
// as they will use the same underlying stringwriter variable.
//
_data = _stringWriter.toString();
_stringWriter = null;
_active = false;
} else if (_domResult != null) {
// Copy the content from the result to a source
// and use the identify transform to get it into a
// friendlier result format.
try {
TransformerFactory factory = getXmlFactoryFactory().newTransformerFactory();
Transformer transformer = factory.newTransformer();
DOMSource domSource = new DOMSource(_domResult.getNode());
StringWriter stringWriter = new StringWriter();
StreamResult streamResult = new StreamResult(stringWriter);
transformer.transform(domSource, streamResult);
_data = stringWriter.toString();
} catch (TransformerException te) {
throw new PSQLException(GT.tr("Unable to convert DOMResult SQLXML data to a string."),
PSQLState.DATA_ERROR, te);
} finally {
_domResult = null;
_active = false;
}
}
}
private void initialize() throws SQLException {
if (_initialized) {
throw new PSQLException(
GT.tr(
"This SQLXML object has already been initialized, so you cannot manipulate it further."),
PSQLState.OBJECT_NOT_IN_STATE);
}
_initialized = true;
}
}