/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program 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. * * Copyright (c) 2002-2016 Pentaho Corporation.. All rights reserved. */ package org.pentaho.di.trans.steps.gpload; import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.Date; import org.pentaho.di.core.Const; import org.pentaho.di.core.util.Utils; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.logging.LogChannel; import org.pentaho.di.core.logging.LogChannelInterface; import org.pentaho.di.core.logging.LogLevel; import org.pentaho.di.core.row.RowMetaInterface; import org.pentaho.di.core.row.ValueMetaInterface; import org.pentaho.di.core.variables.VariableSpace; import org.pentaho.di.i18n.BaseMessages; /** * Does the opening of the output "stream". It's either a file or inter process communication which is transparent to * users of this class. * * Copied from Sven Boden's Oracle version * * @author Luke Lonergan * @since 28-mar-2008 */ public class GPLoadDataOutput { private static Class<?> PKG = GPLoadDataOutput.class; // for i18n purposes, needed by Translator2!! protected LogChannelInterface log; private GPLoad gpLoad = null; private GPLoadMeta meta; private PrintWriter output = null; private boolean first = true; private int[] fieldNumbers = null; private String enclosure = null; private String delimiter = null; private SimpleDateFormat sdfDate = null; private SimpleDateFormat sdfDateTime = null; public GPLoadDataOutput( GPLoad gpLoad, GPLoadMeta meta ) { this.meta = meta; this.gpLoad = gpLoad; } public GPLoadDataOutput( GPLoad gpLoad, GPLoadMeta meta, LogLevel logLevel ) { this( gpLoad, meta ); log = new LogChannel( this ); log.setLogLevel( logLevel ); } public void open( VariableSpace space, Process sqlldrProcess ) throws KettleException { // String loadMethod = meta.getLoadMethod(); try { OutputStream os = null; // if ( GPLoadMeta.METHOD_AUTO_CONCURRENT.equals(loadMethod)) { // String dataFile = meta.getControlFile(); // dataFile = StringUtil.environmentSubstitute(dataFile); // os = new FileOutputStream(dataFile, true); // } else { // Else open the data file filled in. String dataFile = meta.getDataFile(); if ( Utils.isEmpty( dataFile ) ) { throw new KettleException( BaseMessages.getString( PKG, "GPload.Exception.DataFileMissing" ) ); } dataFile = space.environmentSubstitute( dataFile ); if ( Utils.isEmpty( dataFile ) ) { throw new KettleException( BaseMessages.getString( PKG, "GPload.Exception.DataFileMissing" ) ); } log.logDetailed( "Creating temporary load file " + dataFile ); os = new FileOutputStream( dataFile, false ); // String encoding = meta.getEncoding(); if ( Utils.isEmpty( encoding ) ) { // Use the default encoding. output = new PrintWriter( new BufferedWriter( new OutputStreamWriter( os ) ) ); } else { // Use the specified encoding output = new PrintWriter( new BufferedWriter( new OutputStreamWriter( os, encoding ) ) ); } } catch ( IOException e ) { throw new KettleException( "GPLoadDataOutput.Exception" + e.getMessage(), e ); } } public void close() throws IOException { if ( output != null ) { output.close(); } } PrintWriter getOutput() { return output; } protected void setOutput( PrintWriter output ) { this.output = output; } private String createEscapedString( String orig, String enclosure ) { StringBuffer buf = new StringBuffer( orig ); Const.repl( buf, enclosure, enclosure + enclosure ); return buf.toString(); } public void writeLine( RowMetaInterface mi, Object[] row ) throws KettleException { if ( first ) { first = false; enclosure = meta.getEnclosure(); if ( enclosure == null ) { enclosure = ""; } else { enclosure = gpLoad.environmentSubstitute( enclosure ); } delimiter = meta.getDelimiter(); if ( delimiter == null ) { throw new KettleException( BaseMessages.getString( PKG, "GPload.Exception.DelimiterMissing" ) ); } else { delimiter = gpLoad.environmentSubstitute( delimiter ); if ( Utils.isEmpty( delimiter ) ) { throw new KettleException( BaseMessages.getString( PKG, "GPload.Exception.DelimiterMissing" ) ); } } // Setup up the fields we need to take for each of the rows // as this speeds up processing. fieldNumbers = new int[meta.getFieldStream().length]; for ( int i = 0; i < fieldNumbers.length; i++ ) { fieldNumbers[i] = mi.indexOfValue( meta.getFieldStream()[i] ); if ( fieldNumbers[i] < 0 ) { throw new KettleException( BaseMessages.getString( PKG, "GPLoadDataOutput.Exception.FieldNotFound", meta .getFieldStream()[i] ) ); } } sdfDate = new SimpleDateFormat( "yyyy-MM-dd" ); sdfDateTime = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.SSS" ); } // Write the data to the output ValueMetaInterface v = null; int number = 0; for ( int i = 0; i < fieldNumbers.length; i++ ) { // TODO: variable substitution if ( i != 0 ) { output.print( delimiter ); } number = fieldNumbers[i]; v = mi.getValueMeta( number ); if ( row[number] == null ) { // TODO (SB): special check for null in case of Strings. output.print( enclosure ); output.print( enclosure ); } else { switch ( v.getType() ) { case ValueMetaInterface.TYPE_STRING: String s = mi.getString( row, number ); if ( s.indexOf( enclosure ) >= 0 ) { s = createEscapedString( s, enclosure ); } output.print( enclosure ); output.print( s ); output.print( enclosure ); break; case ValueMetaInterface.TYPE_INTEGER: Long l = mi.getInteger( row, number ); if ( meta.getEncloseNumbers() ) { output.print( enclosure ); output.print( l ); output.print( enclosure ); } else { output.print( l ); } break; case ValueMetaInterface.TYPE_NUMBER: Double d = mi.getNumber( row, number ); if ( meta.getEncloseNumbers() ) { output.print( enclosure ); output.print( d ); output.print( enclosure ); } else { output.print( d ); } break; case ValueMetaInterface.TYPE_BIGNUMBER: BigDecimal bd = mi.getBigNumber( row, number ); if ( meta.getEncloseNumbers() ) { output.print( enclosure ); output.print( bd ); output.print( enclosure ); } else { output.print( bd ); } break; case ValueMetaInterface.TYPE_DATE: Date dt = mi.getDate( row, number ); output.print( enclosure ); output.print( sdfDate.format( dt ) ); output.print( enclosure ); break; case ValueMetaInterface.TYPE_BOOLEAN: Boolean b = mi.getBoolean( row, number ); output.print( enclosure ); if ( b.booleanValue() ) { output.print( "Y" ); } else { output.print( "N" ); } output.print( enclosure ); break; case ValueMetaInterface.TYPE_BINARY: byte[] byt = mi.getBinary( row, number ); output.print( "<startlob>" ); output.print( byt ); output.print( "<endlob>" ); break; case ValueMetaInterface.TYPE_TIMESTAMP: Date time = mi.getDate( row, number ); output.print( enclosure ); output.print( sdfDateTime.format( time ) ); output.print( enclosure ); break; default: throw new KettleException( BaseMessages.getString( PKG, "GPLoadDataOutput.Exception.TypeNotSupported", v .getType() ) ); } } } output.print( Const.CR ); } }