package com.ximple.io.dgn7; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Iterator; import org.apache.log4j.Logger; import oracle.jdbc.OracleConnection; import oracle.sql.BLOB; /** * Dgn7OracleReader * User: Ulysses * Date: 2007/10/24 * Time: 下午 01:01:08 */ public class Dgn7OracleReader implements Iterator { private final static Logger logger = Logger.getLogger(Dgn7OracleReader.class); private String _sql; private String _fieldName; private Connection _connection; private ResultSet _resultSet; private static final int FETCHSIZE = 20; private Element _element; public Dgn7OracleReader(String sql, String fieldName, OracleConnection connection) { this._sql = sql; this._fieldName = fieldName; this._connection = connection; } public String getSql() { return _sql; } public void setSql(String sql) { this._sql = sql; } public String getFieldName() { return _fieldName; } public void setFieldName(String fieldName) { this._fieldName = fieldName; } public boolean hasNext() { if (_resultSet == null) { try { initializeReader(); } catch (SQLException e) { throw new RuntimeException("initialize oralce error.", e); } catch (Dgn7fileException e) { throw new RuntimeException("initialize oralce error.", e); } } if (_element == null) { return false; } return true; } public Element next() { Element result = _element; try { fetchElement(); } catch (SQLException e) { throw new RuntimeException("Error:" + e.getMessage(), e); } catch (Dgn7fileException e) { throw new RuntimeException("Error:" + e.getMessage(), e); } return result; } public void remove() { throw new RuntimeException("Not Support this method."); } private boolean initializeReader() throws SQLException, Dgn7fileException { if (_resultSet != null) return true; Statement stmtSrc = _connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); stmtSrc.setFetchSize(FETCHSIZE); _resultSet = stmtSrc.executeQuery(_sql); fetchElement(); return true; } private boolean fetchElement() throws SQLException, Dgn7fileException { if (_resultSet.next()) { byte[] raw = null; Object value = _resultSet.getObject(this._fieldName); if (value instanceof BLOB) { BLOB blob = (BLOB) value; try { raw = getBytesFromBLOB(blob); } catch (IOException e) { throw new SQLException("IOError", e); } blob.close(); } else if (value instanceof byte[]) { raw = (byte[]) value; } if (raw == null) { _element = null; return false; } ByteBuffer buffer = ByteBuffer.wrap(raw); buffer.order(ByteOrder.LITTLE_ENDIAN); short signature = buffer.getShort(); // byte type = (byte) (buffer.get() & 0x7f); byte type = (byte) ((signature >>> 8) & 0x007f); // silly Bentley say contentLength is in 2-byte words // and ByteByffer uses bytes. // track the record location int elementLength = (buffer.getShort() * 2) + 4; ElementType recordType = ElementType.forID(type); IElementHandler handler = recordType.getElementHandler(); _element = (Element) handler.read(buffer, signature, elementLength); if (recordType.isComplexElement() && (elementLength < raw.length)) { int offset = elementLength; while (offset < (raw.length - 4)) { buffer.position(offset); signature = buffer.getShort(); type = (byte) ((signature >>> 8) & 0x007f); elementLength = (buffer.getShort() * 2) + 4; if (raw.length < (offset + elementLength)) { System.out.println("Length not match:" + offset +":"+ buffer.position() +":"+buffer.limit()); break; } recordType = ElementType.forID(type); handler = recordType.getElementHandler(); if (handler != null) { Element subElement = (Element) handler.read(buffer, signature, elementLength); ((ComplexElement) _element).add(subElement); offset += elementLength; } else { byte[] remain = new byte[buffer.remaining()]; System.arraycopy(raw, offset, remain, 0, buffer.remaining()); for (int i = 0; i < remain.length; i++) { if (remain[i] != 0) { logger.info("fetch element has some error. index=" + (offset + i) + ":value=" + remain[i]); System.out.println("fetch element has some error. index=" + (offset + i) + ":value=" + remain[i]); } } break; } } } } else { _element = null; return false; } return true; } protected static byte[] getBytesFromBLOB(BLOB blob) throws SQLException, IOException { byte[] raw = null; // BLOB blob = (BLOB) rs.getBlob(1); int optimalSize = blob.getChunkSize(); byte[] chunk = new byte[optimalSize]; InputStream is = blob.getBinaryStream(0); ByteBuffer buffer = null; // ByteBuffer.allocate(optimalSize); int len = 0; try { while ((len = (is.read(chunk))) != -1) { if (buffer != null) { buffer.limit(buffer.limit() + len); } else { buffer = ByteBuffer.allocate(len); } buffer.put(chunk); } is.close(); buffer.position(0); raw = buffer.array(); } catch (IOException e) { e.printStackTrace(); throw e; } return raw; } }