package com.ximple.eofms.jobs; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.ArrayList; import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.vividsolutions.jts.util.Assert; import oracle.sql.BLOB; import com.ximple.eofms.util.PrintfFormat; import com.ximple.io.dgn7.ArcElement; import com.ximple.io.dgn7.ComplexChainElement; import com.ximple.io.dgn7.ComplexShapeElement; import com.ximple.io.dgn7.Element; import com.ximple.io.dgn7.EllipseElement; import com.ximple.io.dgn7.LineElement; import com.ximple.io.dgn7.LineStringElement; import com.ximple.io.dgn7.ShapeElement; import com.ximple.io.dgn7.TextElement; import com.ximple.io.dgn7.TextNodeElement; import com.ximple.io.dgn7.IElementHandler; import com.ximple.io.dgn7.Dgn7fileException; public class OracleElementLogger { static Log logger = LogFactory.getLog(OracleElementLogger.class); private static final String DEFAULT_ELMOUTPATH = "elmout"; private static final String TAB_IGDSSEED = "SD$IGDSSET_SEED"; private Connection connection; private String dataOut = null; private String dataPath; private String currentSchema; private boolean schemaChanged; private FileOutputStream fos = null; private FileChannel fch = null; private int logCount = 0; private ArrayList dgnFileHeader = null; private String elmOutPath; public OracleElementLogger(Connection connection) { this.connection = connection; elmOutPath = DEFAULT_ELMOUTPATH; } public OracleElementLogger(Connection connection, String elmOutPath) { this.connection = connection; this.elmOutPath = elmOutPath; } public String getDataOutPath() { if (dataOut == null) { File outPath = new File(getDataPath(), elmOutPath); if (!outPath.exists()) { outPath.mkdir(); } else if (!outPath.isDirectory()) { outPath.mkdir(); } dataOut = outPath.toString(); } return dataOut; } public String getDataPath() { return dataPath; } public void setDataPath(String dataPath) { this.dataPath = dataPath; } public void logElement(Element element, String currentSchema) { if ((this.currentSchema == null) || (!this.currentSchema.equalsIgnoreCase(currentSchema))) { schemaChanged = true; this.currentSchema = currentSchema; try { createNewStream(); } catch (IOException e) { logger.warn(e.getMessage(), e); return; } catch (SQLException e) { logger.warn(e.getMessage(), e); return; } } else { if (fch == null) { try { createNewStream(); } catch (IOException e) { logger.warn(e.getMessage(), e); return; } catch (SQLException e) { logger.warn(e.getMessage(), e); return; } } } ArrayList subBuffers = new ArrayList(); if (fch != null) { ByteBuffer buf = null; if (element instanceof LineElement) { int size = LineElement.ElementHandler.getInstance().getLength(element); buf = ByteBuffer.allocate(size * 2); LineElement.ElementHandler.getInstance().write(buf, element); } else if (element instanceof ShapeElement) { int size = ShapeElement.ElementHandler.getInstance().getLength(element); buf = ByteBuffer.allocate(size * 2); ShapeElement.ElementHandler.getInstance().write(buf, element); } else if (element instanceof LineStringElement) { int size = LineStringElement.ElementHandler.getInstance().getLength(element); buf = ByteBuffer.allocate(size * 2); LineStringElement.ElementHandler.getInstance().write(buf, element); } else if (element instanceof ComplexChainElement) { int size = ComplexChainElement.ElementHandler.getInstance().getLength(element); buf = ByteBuffer.allocate(size * 2); ComplexChainElement.ElementHandler.getInstance().write(buf, element); ComplexChainElement complexElement = (ComplexChainElement) element; ListIterator it = complexElement.listIterator(); while (it.hasNext()) { Element subElm = (Element) it.next(); try { IElementHandler handler = subElm.getElementType().getElementHandler(); size = handler.getLength(subElm); ByteBuffer subBuf = ByteBuffer.allocate(size * 2); handler.write(subBuf, subElm); subBuffers.add(subBuf); } catch (Dgn7fileException e) { logger.warn(e.getMessage(), e); } } } else if (element instanceof ComplexShapeElement) { int size = ComplexShapeElement.ElementHandler.getInstance().getLength(element); buf = ByteBuffer.allocate(size * 2); ComplexShapeElement.ElementHandler.getInstance().write(buf, element); ComplexShapeElement complexElement = (ComplexShapeElement) element; ListIterator it = complexElement.listIterator(); while (it.hasNext()) { Element subElm = (Element) it.next(); try { IElementHandler handler = subElm.getElementType().getElementHandler(); size = handler.getLength(subElm); ByteBuffer subBuf = ByteBuffer.allocate(size * 2); handler.write(subBuf, subElm); subBuffers.add(subBuf); } catch (Dgn7fileException e) { logger.warn(e.getMessage(), e); } } } else if (element instanceof ArcElement) { int size = ArcElement.ElementHandler.getInstance().getLength(element); buf = ByteBuffer.allocate(size * 2); ArcElement.ElementHandler.getInstance().write(buf, element); } else if (element instanceof EllipseElement) { int size = EllipseElement.ElementHandler.getInstance().getLength(element); buf = ByteBuffer.allocate(size * 2); EllipseElement.ElementHandler.getInstance().write(buf, element); } else if (element instanceof TextElement) { int size = TextElement.ElementHandler.getInstance().getLength(element); buf = ByteBuffer.allocate(size * 2); TextElement.ElementHandler.getInstance().write(buf, element); } else if (element instanceof TextNodeElement) { int size = TextNodeElement.ElementHandler.getInstance().getLength(element); buf = ByteBuffer.allocate(size * 2); TextNodeElement.ElementHandler.getInstance().write(buf, element); TextNodeElement nodeElement = (TextNodeElement) element; ListIterator it = nodeElement.listIterator(); while (it.hasNext()) { Element subElm = (Element) it.next(); try { IElementHandler handler = subElm.getElementType().getElementHandler(); size = handler.getLength(subElm); ByteBuffer subBuf = ByteBuffer.allocate(size * 2); handler.write(subBuf, subElm); subBuffers.add(subBuf); } catch (Dgn7fileException e) { logger.warn(e.getMessage(), e); } } } if ((buf != null) && (fch != null)) { try { buf.position(0); int size = fch.write(buf); if (size != buf.limit()) { long position = fch.position(); logger.info("Pos:" + position); } } catch (IOException e) { logger.warn(e.getMessage(), e); } } } if ((subBuffers.size() != 0) && (fch != null)) { for (ByteBuffer buf : subBuffers) { try { buf.position(0); int size = fch.write(buf); if (size != buf.limit()) { long position = fch.position(); logger.info("Pos:" + position); } } catch (IOException e) { logger.warn(e.getMessage(), e); } } } } private void createNewStream() throws IOException, SQLException { if (fos != null) { putEndOfFileElement(); fos.close(); fos = null; fch = null; } File logFile = new File(getDataOutPath(), this.currentSchema + ".dgn"); while (logFile.exists()) { logFile = new File(getDataOutPath(), this.currentSchema + "-" + (++logCount) + ".dgn"); } logger.warn("Create Dgn Logging File:" + logFile.toString()); fos = new FileOutputStream(logFile); fch = fos.getChannel(); prepareOutputElementStream(); schemaChanged = false; } private void putEndOfFileElement() throws IOException { if (fch == null) return; ByteBuffer bf = ByteBuffer.allocate(4); bf.putInt(-1); fch.write(bf); } private void prepareOutputElementStream() throws SQLException, IOException { if (connection == null) { logger.warn("connection is null"); return; } if (dgnFileHeader != null) { for (byte[] raw : dgnFileHeader) { putElementIntoStream(raw); } return; } dgnFileHeader = new ArrayList(); String fetchSrcStmtFmt = "SELECT IGDSELM FROM \"%s\".\"%s\" ORDER BY ROWID"; PrintfFormat spf = new PrintfFormat(fetchSrcStmtFmt); String fetchSrcStmt = spf.sprintf(new Object[]{currentSchema, TAB_IGDSSEED}); Statement stmtSrc = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); ResultSet rsSrc = stmtSrc.executeQuery(fetchSrcStmt); int igdsMetaType = rsSrc.getMetaData().getColumnType(1); while (rsSrc.next()) { byte[] raw; if (igdsMetaType == Types.BLOB) { BLOB blob = (BLOB) rsSrc.getBlob(1); raw = getBytesFromBLOB(blob); blob.close(); } else { raw = rsSrc.getBytes(1); } if (raw != null) { dgnFileHeader.add(raw); putElementIntoStream(raw); } } rsSrc.close(); stmtSrc.close(); } private void putElementIntoStream(byte[] raw) throws IOException { if (fch != null) fch.write(ByteBuffer.wrap(raw)); } protected static byte[] getBytesFromBLOB(BLOB blob) throws SQLException { byte[] raw = null; int optimalSize = blob.getChunkSize(); byte[] chunk = new byte[optimalSize]; InputStream is = blob.getBinaryStream(0); ByteBuffer buffer = null; // ByteBuffer.allocate(optimalSize); int len; 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(); assert buffer != null; buffer.position(0); raw = buffer.array(); } catch (IOException e) { logger.warn(e.getMessage(), e); Assert.shouldNeverReachHere(); } return raw; } public void flashLogging() { if (fos != null) { try { fos.close(); } catch (IOException e) { logger.warn(e.getMessage(), e); } fos = null; fch = null; } } public boolean isSchemaChanged() { return schemaChanged; } }