/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.script.io; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.SQLXML; import java.sql.Types; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; /** * This object wraps/extends a SQL ResultSet object as Reader object. Once the * ResultSet can read as reader then it can be persisted, printed or compared * easily without lot of code hassle of walking it every time. * * <p>PS: remember this is a Reader not InputStream, so all the fields read * going to be converted to strings before they returned. * * @since 4.3 */ public class ResultSetReader extends StringLineReader { ResultSet source = null; // Number of columns in the result set int columnCount = 0; // delimiter between the fields while reading each row String delimiter = " "; //$NON-NLS-1$ boolean firstTime = true; int[] columnTypes = null; private int rowCount; public ResultSetReader(ResultSet in) { this.source = in; } public ResultSetReader(ResultSet in, String delimiter) { this.source = in; this.delimiter = delimiter; } /** * @see java.io.Reader#close() * @since 4.3 */ public void close() throws IOException { try { source.close(); super.close(); } catch (SQLException e) { throw new IOException(e.getMessage()); } } /** * Get the next line of results from the ResultSet. The first line will be the * metadata of the resultset and then followed by the result rows. Each row will be * returned as one line. * @return next result line from result set. */ protected String nextLine() throws IOException{ try { if (firstTime) { firstTime = false; ResultSetMetaData metadata = source.getMetaData(); columnCount = metadata.getColumnCount(); columnTypes = new int[columnCount]; for (int i = 0; i < columnCount; i++) { columnTypes[i] = metadata.getColumnType(i+1); } return resultSetMetaDataToString(metadata, delimiter); } // if you get here then we are ready to read the results. if (source.next()) { rowCount++; StringBuffer sb = new StringBuffer(); // Walk through column values in this row for (int col = 1; col <= columnCount; col++) { Object anObj = source.getObject(col); if (columnTypes[col-1] == Types.CLOB) { sb.append(anObj != null ? source.getString(col) : "null"); //$NON-NLS-1$ } else if (columnTypes[col-1] == Types.BLOB) { sb.append(anObj != null ? "BLOB" : "null"); //$NON-NLS-1$ //$NON-NLS-2$ } else if (columnTypes[col-1] == Types.SQLXML) { SQLXML xml = (SQLXML)anObj; sb.append(anObj != null ? prettyPrint(xml) : "null"); //$NON-NLS-1$ } else { sb.append(anObj != null ? anObj : "null"); //$NON-NLS-1$ } if (col != columnCount) { sb.append(delimiter); } } sb.append("\n"); //$NON-NLS-1$ return sb.toString(); } } catch (SQLException e) { throw new IOException(e.getMessage()); } return null; } public int getRowCount() { return rowCount; } /** * Get the first line from the result set. This is the resultset metadata line where * we gather the column names and their types. * @return * @throws SQLException */ public static String resultSetMetaDataToString(ResultSetMetaData metadata, String delimiter) throws SQLException{ StringBuffer sb = new StringBuffer(); int columnCount = metadata.getColumnCount(); for (int col = 1; col <= columnCount; col++) { sb.append(metadata.getColumnName(col)) .append("[") //$NON-NLS-1$ .append(metadata.getColumnTypeName(col)) .append("]"); //$NON-NLS-1$ if (col != columnCount) { sb.append(delimiter); } } sb.append("\n"); //$NON-NLS-1$ return sb.toString(); } public static String prettyPrint(SQLXML xml) throws SQLException { try { TransformerFactory transFactory = TransformerFactory.newInstance(); transFactory.setAttribute("indent-number", new Integer(2)); //$NON-NLS-1$ Transformer tf = transFactory.newTransformer(); tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); //$NON-NLS-1$ tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");//$NON-NLS-1$ tf.setOutputProperty(OutputKeys.INDENT, "yes");//$NON-NLS-1$ tf.setOutputProperty(OutputKeys.METHOD, "xml");//$NON-NLS-1$ tf.setOutputProperty(OutputKeys.STANDALONE, "yes");//$NON-NLS-1$ tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); //$NON-NLS-1$ //$NON-NLS-2$ ByteArrayOutputStream out = new ByteArrayOutputStream(); StreamResult xmlOut = new StreamResult(new BufferedOutputStream(out)); tf.transform(xml.getSource(StreamSource.class), xmlOut); return out.toString(); } catch (Exception e) { return xml.getString(); } } }