Java tutorial
/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2013 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.propertyoutput; import java.io.OutputStream; import java.util.Properties; import org.apache.commons.vfs.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.KettleStepException; 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; /** * Output rows to Properties file and create a file. * * @author Samatar * @since 13-Apr-2008 */ public class PropertyOutput extends BaseStep implements StepInterface { private static Class<?> PKG = PropertyOutputMeta.class; // for i18n purposes, needed by Translator2!! private PropertyOutputMeta meta; private PropertyOutputData data; public PropertyOutput(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 = (PropertyOutputMeta) smi; data = (PropertyOutputData) 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) { first = false; data.inputRowMeta = getInputRowMeta(); data.outputRowMeta = data.inputRowMeta.clone(); meta.getFields(data.outputRowMeta, getStepname(), null, null, this, repository, metaStore); // Let's take the index of Key field ... data.indexOfKeyField = data.inputRowMeta.indexOfValue(meta.getKeyField()); if (data.indexOfKeyField < 0) { // The field is unreachable ! logError(BaseMessages.getString(PKG, "PropertyOutput.Log.ErrorFindingField", meta.getKeyField())); throw new KettleException( BaseMessages.getString(PKG, "PropertyOutput.Log.ErrorFindingField", meta.getKeyField())); } // Let's take the index of Key field ... data.indexOfValueField = data.inputRowMeta.indexOfValue(meta.getValueField()); if (data.indexOfValueField < 0) { // The field is unreachable ! logError(BaseMessages.getString(PKG, "PropertyOutput.Log.ErrorFindingField", meta.getValueField())); throw new KettleException( BaseMessages.getString(PKG, "PropertyOutput.Log.ErrorFindingField", meta.getValueField())); } if (meta.isFileNameInField()) { String realFieldName = environmentSubstitute(meta.getFileNameField()); if (Const.isEmpty(realFieldName)) { logError(BaseMessages.getString(PKG, "PropertyOutput.Log.FilenameInFieldEmpty")); throw new KettleException( BaseMessages.getString(PKG, "PropertyOutput.Log.FilenameInFieldEmpty")); } data.indexOfFieldfilename = data.inputRowMeta.indexOfValue(realFieldName); if (data.indexOfFieldfilename < 0) { // The field is unreachable ! logError(BaseMessages.getString(PKG, "PropertyOutput.Log.ErrorFindingField", meta.getValueField())); throw new KettleException(BaseMessages.getString(PKG, "PropertyOutput.Log.ErrorFindingField", meta.getValueField())); } } else { // Let's check for filename... data.filename = buildFilename(); // Check if filename is empty.. if (Const.isEmpty(data.filename)) { logError(BaseMessages.getString(PKG, "PropertyOutput.Log.FilenameEmpty")); throw new KettleException(BaseMessages.getString(PKG, "PropertyOutput.Log.FilenameEmpty")); } openNewFile(); } } // end first // Get value field String propkey = data.inputRowMeta.getString(r, data.indexOfKeyField); String propvalue = data.inputRowMeta.getString(r, data.indexOfValueField); try { if (meta.isFileNameInField()) { data.filename = data.inputRowMeta.getString(r, data.indexOfFieldfilename); if (Const.isEmpty(data.filename)) { throw new KettleException(BaseMessages.getString(PKG, "PropertyOutputMeta.Log.FileNameEmty")); } if (!checkSameFile()) { // close previous file closeFile(); // Open new file openNewFile(); } } if (!data.KeySet.contains(propkey)) { if (log.isDetailed()) { logDetailed(BaseMessages.getString(PKG, "PropertyOutput.Log.Key", propkey)); logDetailed(BaseMessages.getString(PKG, "PropertyOutput.Log.Value", propvalue)); } // Update property data.pro.setProperty(propkey, propvalue); putRow(data.outputRowMeta, r); // in case we want it to go further... incrementLinesOutput(); if (checkFeedback(getLinesRead())) { if (log.isBasic()) { logBasic("linenr " + getLinesRead()); } } data.KeySet.add(propkey); } } catch (KettleStepException e) { boolean sendToErrorRow = false; String errorMessage = null; if (getStepMeta().isDoingErrorHandling()) { sendToErrorRow = true; errorMessage = e.toString(); } else { logError(BaseMessages.getString(PKG, "PropertyOutputMeta.Log.ErrorInStep") + e.getMessage()); setErrors(1); stopAll(); setOutputDone(); // signal end to receiver(s) return false; } if (sendToErrorRow) { putError(data.outputRowMeta, r, 1L, errorMessage, null, "PROPSOUTPUTO001"); } } return true; } public boolean checkSameFile() throws KettleException { return data.previousFileName.equals(data.filename); } private void saveProcessingFile() { data.previousFileName = data.filename; } private void openNewFile() throws KettleException { try { data.pro = new Properties(); data.KeySet.clear(); data.file = KettleVFS.getFileObject(data.filename, getTransMeta()); if (meta.isAppend() && data.file.exists()) { data.pro.load(KettleVFS.getInputStream(data.file)); } // Create parent folder if needed... createParentFolder(); saveProcessingFile(); } catch (Exception e) { throw new KettleException("Error opening file [" + data.filename + "]!", e); } } private void createParentFolder() throws KettleException { if (meta.isCreateParentFolder()) { FileObject parentfolder = null; try { // Do we need to create parent folder ? // Check for parent folder // Get parent folder parentfolder = data.file.getParent(); if (!parentfolder.exists()) { if (log.isDetailed()) { logDetailed(BaseMessages.getString(PKG, "PropertyOutput.Log.ParentFolderExists", parentfolder.getName().toString())); } parentfolder.createFolder(); if (log.isDetailed()) { logDetailed(BaseMessages.getString(PKG, "PropertyOutput.Log.CanNotCreateParentFolder", parentfolder.getName().toString())); } } } catch (Exception e) { logError(BaseMessages.getString(PKG, "PropertyOutput.Log.CanNotCreateParentFolder", parentfolder.getName().toString())); throw new KettleException(BaseMessages.getString(PKG, "PropertyOutput.Log.CanNotCreateParentFolder", parentfolder.getName().toString())); } finally { if (parentfolder != null) { try { parentfolder.close(); } catch (Exception ex) { /* Ignore */ } } } } } private boolean closeFile() { if (data.file == null) { return true; } boolean retval = false; OutputStream propsFile = null; try { propsFile = KettleVFS.getOutputStream(data.file, false); data.pro.store(propsFile, environmentSubstitute(meta.getComment())); if (meta.addToResult()) { // Add this to the result file names... ResultFile resultFile = new ResultFile(ResultFile.FILE_TYPE_GENERAL, data.file, getTransMeta().getName(), getStepname()); resultFile.setComment(BaseMessages.getString(PKG, "PropertyOutput.Log.FileAddedResult")); addResultFile(resultFile); } data.KeySet.clear(); retval = true; } catch (Exception e) { logError("Exception trying to close file [" + data.file.getName() + "]! :" + e.toString()); setErrors(1); } finally { if (propsFile != null) { try { propsFile.close(); propsFile = null; } catch (Exception e) { /* Ignore */ } } if (data.file != null) { try { data.file.close(); data.file = null; } catch (Exception e) { /* Ignore */ } } if (data.pro != null) { data.pro = null; } } return retval; } public String buildFilename() { return meta.buildFilename(this, getCopy()); } public boolean init(StepMetaInterface smi, StepDataInterface sdi) { meta = (PropertyOutputMeta) smi; data = (PropertyOutputData) sdi; if (super.init(smi, sdi)) { return true; } return false; } public void dispose(StepMetaInterface smi, StepDataInterface sdi) { meta = (PropertyOutputMeta) smi; data = (PropertyOutputData) sdi; closeFile(); setOutputDone(); super.dispose(smi, sdi); } }