/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2016 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ package org.pentaho.di.trans.steps.accessoutput; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; import org.apache.commons.vfs2.FileObject; import org.pentaho.di.core.Const; import org.pentaho.di.core.ResultFile; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.exception.KettleValueException; import org.pentaho.di.core.vfs.KettleVFS; import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.trans.Trans; import org.pentaho.di.trans.TransMeta; import org.pentaho.di.trans.step.BaseStep; import org.pentaho.di.trans.step.StepDataInterface; import org.pentaho.di.trans.step.StepInterface; import org.pentaho.di.trans.step.StepMeta; import org.pentaho.di.trans.step.StepMetaInterface; /** * Writes rows to a database table. * * @author Matt * @since 6-apr-2003 */ public class AccessOutput extends BaseStep implements StepInterface { private static Class<?> PKG = AccessOutput.class; // for i18n purposes, needed by Translator2!! public static final int COMMIT_SIZE = 500; private AccessOutputMeta meta; private AccessOutputData data; public AccessOutput( StepMeta stepMeta, StepDataInterface stepDataInterface, int copyNr, TransMeta transMeta, Trans trans ) { super( stepMeta, stepDataInterface, copyNr, transMeta, trans ); } public boolean processRow( StepMetaInterface smi, StepDataInterface sdi ) throws KettleException { meta = (AccessOutputMeta) smi; data = (AccessOutputData) sdi; Object[] r = getRow(); // this also waits for a previous step to be finished. if ( r == null ) { // no more input to be expected... setOutputDone(); return false; } if ( first && meta.isDoNotOpenNewFileInit() ) { try { if ( !openFile() ) { return false; } } catch ( Exception e ) { logError( "An error occurred intialising this step: " + e.getMessage() ); stopAll(); setErrors( 1 ); } } try { writeToTable( r ); putRow( data.outputRowMeta, r ); // in case we want it go further... if ( checkFeedback( getLinesOutput() ) ) { if ( log.isBasic() ) { logBasic( "linenr " + getLinesOutput() ); } } } catch ( KettleException e ) { logError( "Because of an error, this step can't continue: " + e.getMessage() ); setErrors( 1 ); stopAll(); setOutputDone(); // signal end to receiver(s) return false; } return true; } private boolean writeToTable( Object[] rowData ) throws KettleValueException { if ( rowData == null ) { // Stop: last line or error encountered if ( log.isDetailed() ) { logDetailed( "Last line inserted: stop" ); } return false; } if ( first ) { first = false; data.outputRowMeta = getInputRowMeta(); // First open or create the table try { String realTablename = environmentSubstitute( meta.getTablename() ); data.table = data.db.getTable( realTablename ); if ( data.table == null ) { if ( meta.isTableCreated() ) { // Create the table data.createTable( realTablename, data.outputRowMeta ); } else { logError( BaseMessages.getString( PKG, "AccessOutput.Error.TableDoesNotExist", realTablename ) ); setErrors( 1 ); stopAll(); return false; } } else if ( meta.isTableTruncated() ) { data.truncateTable(); } // All OK: we have an open database and a table to write to. // // Apparently it's not yet possible to remove rows from the table // So truncate is out for the moment as well. } catch ( Exception e ) { logError( BaseMessages .getString( PKG, "AccessOutput.Exception.UnexpectedErrorCreatingTable", e.toString() ) ); logError( Const.getStackTracker( e ) ); setErrors( 1 ); stopAll(); return false; } } // Let's write a row to the database. Object[] columnValues = AccessOutputMeta.createObjectsForRow( data.outputRowMeta, rowData ); try { data.rows.add( columnValues ); if ( meta.getCommitSize() > 0 ) { if ( data.rows.size() >= meta.getCommitSize() ) { data.addRowsToTable( data.rows ); data.rows.clear(); } } else { data.addRowToTable( columnValues ); } } catch ( IOException e ) { logError( BaseMessages.getString( PKG, "AccessOutput.Exception.UnexpectedErrorWritingRow", data.outputRowMeta.getString( rowData ) ) ); logError( Const.getStackTracker( e ) ); setErrors( 1 ); stopAll(); return false; } return true; } public boolean init( StepMetaInterface smi, StepDataInterface sdi ) { meta = (AccessOutputMeta) smi; data = (AccessOutputData) sdi; if ( super.init( smi, sdi ) ) { if ( !meta.isDoNotOpenNewFileInit() ) { try { return openFile(); } catch ( Exception e ) { logError( "An error occurred intialising this step: " + e.getMessage() ); stopAll(); setErrors( 1 ); } } else { return true; } } return false; } boolean openFile() throws Exception { data.oneFileOpened = true; String realFilename = environmentSubstitute( meta.getFilename() ); if ( log.isBasic() ) { logBasic( BaseMessages.getString( PKG, "AccessOutput.log.WritingToFile", realFilename ) ); } FileObject fileObject = KettleVFS.getFileObject( realFilename, getTransMeta() ); File file = FileUtils.toFile( fileObject.getURL() ); // First open or create the access file if ( !file.exists() ) { if ( meta.isFileCreated() ) { data.createDatabase( file ); } else { logError( BaseMessages.getString( PKG, "AccessOutput.InitError.FileDoesNotExist", realFilename ) ); return false; } } else { data.openDatabase( file ); } // Add the filename to the result object... // if ( meta.isAddToResultFiles() ) { ResultFile resultFile = new ResultFile( ResultFile.FILE_TYPE_GENERAL, fileObject, getTransMeta().getName(), toString() ); resultFile.setComment( "This file was created with an access output step" ); addResultFile( resultFile ); } return true; } public void dispose( StepMetaInterface smi, StepDataInterface sdi ) { meta = (AccessOutputMeta) smi; data = (AccessOutputData) sdi; if ( data.oneFileOpened ) { try { // Put the last records in the table as well! if ( data.table != null ) { data.addRowsToTable( data.rows ); } // Just for good measure. data.rows.clear(); if ( data.db != null ) { data.closeDatabase(); } } catch ( IOException e ) { logError( "Error closing the database: " + e.toString() ); setErrors( 1 ); stopAll(); } } super.dispose( smi, sdi ); } }