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.sftpput; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.net.InetAddress; import org.apache.commons.vfs.FileObject; import org.pentaho.di.core.Const; import org.pentaho.di.core.ResultFile; import org.pentaho.di.core.encryption.Encr; 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.job.entries.sftp.SFTPClient; import org.pentaho.di.job.entries.sftpput.JobEntrySFTPPUT; 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; /** * Send file to SFTP host. * * @author Samatar Hassan * @since 30-April-2012 */ public class SFTPPut extends BaseStep implements StepInterface { private static Class<?> PKG = SFTPPutMeta.class; // for i18n purposes, needed by Translator2!! private SFTPPutMeta meta; private SFTPPutData data; public SFTPPut(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 = (SFTPPutMeta) smi; data = (SFTPPutData) sdi; boolean sendToErrorRow = false; String errorMessage = null; Object[] r = getRow(); // get row, set busy! if (r == null) { // no more input to be expected... setOutputDone(); return false; } if (first) { // Go there only for the first row received first = false; try { // String substitution.. String realServerName = environmentSubstitute(meta.getServerName()); String realServerPort = environmentSubstitute(meta.getServerPort()); String realUsername = environmentSubstitute(meta.getUserName()); String realPassword = Encr .decryptPasswordOptionallyEncrypted(environmentSubstitute(meta.getPassword())); String realKeyFilename = null; String realPassPhrase = null; if (meta.isUseKeyFile()) { // We must have here a private keyfilename realKeyFilename = environmentSubstitute(meta.getKeyFilename()); if (Const.isEmpty(realKeyFilename)) { // Error..Missing keyfile logError(BaseMessages.getString(PKG, "SFTPPut.Error.KeyFileMissing")); return false; } if (!KettleVFS.fileExists(realKeyFilename)) { // Error.. can not reach keyfile logError(BaseMessages.getString(PKG, "SFTPPut.Error.KeyFileNotFound", realKeyFilename)); return false; } realPassPhrase = environmentSubstitute(meta.getKeyPassPhrase()); } // Let's try to establish SFTP connection.... // Create sftp client to host ... data.sftpclient = new SFTPClient(InetAddress.getByName(realServerName), Const.toInt(realServerPort, 22), realUsername, realKeyFilename, realPassPhrase); // connection successfully established if (isDetailed()) { logDetailed(BaseMessages.getString(PKG, "SFTPPUT.Log.OpenedConnection", realServerName, realServerPort, realUsername)); } // Set compression data.sftpclient.setCompression(meta.getCompression()); // Set proxy? String realProxyHost = environmentSubstitute(meta.getProxyHost()); if (!Const.isEmpty(realProxyHost)) { // Set proxy data.sftpclient.setProxy(realProxyHost, environmentSubstitute(meta.getProxyPort()), environmentSubstitute(meta.getProxyUsername()), environmentSubstitute(meta.getProxyPassword()), meta.getProxyType()); } // login to ftp host ... data.sftpclient.login(realPassword); } catch (Exception e) { throw new KettleException(BaseMessages.getString(PKG, "SFTPPUT.Error.Connection"), e); } // Let's perform some checks // Sourcefilename field String sourceFilenameFieldName = environmentSubstitute(meta.getSourceFileFieldName()); if (Const.isEmpty(sourceFilenameFieldName)) { // source filename field is missing throw new KettleStepException( BaseMessages.getString(PKG, "SFTPPut.Error.SourceFileNameFieldMissing")); } data.indexOfSourceFileFieldName = getInputRowMeta().indexOfValue(sourceFilenameFieldName); if (data.indexOfSourceFileFieldName < -1) { // source filename field is missing throw new KettleStepException( BaseMessages.getString(PKG, "SFTPPut.Error.CanNotFindField", sourceFilenameFieldName)); } // Remote folder fieldname String remoteFoldernameFieldName = environmentSubstitute(meta.getRemoteDirectoryFieldName()); if (Const.isEmpty(remoteFoldernameFieldName)) { // remote folder field is missing throw new KettleStepException( BaseMessages.getString(PKG, "SFTPPut.Error.RemoteFolderNameFieldMissing")); } data.indexOfRemoteDirectory = getInputRowMeta().indexOfValue(remoteFoldernameFieldName); if (data.indexOfRemoteDirectory < -1) { // remote foldername field is missing throw new KettleStepException( BaseMessages.getString(PKG, "SFTPPut.Error.CanNotFindField", remoteFoldernameFieldName)); } // Move to folder if (meta.getAfterFTPS() == JobEntrySFTPPUT.AFTER_FTPSPUT_MOVE) { String realDestinationFoldernameFieldName = environmentSubstitute( meta.getDestinationFolderFieldName()); if (Const.isEmpty(realDestinationFoldernameFieldName)) { throw new KettleStepException( BaseMessages.getString(PKG, "SFTPPut.Log.DestinatFolderNameFieldNameMissing")); } data.indexOfMoveToFolderFieldName = getInputRowMeta() .indexOfValue(realDestinationFoldernameFieldName); if (data.indexOfMoveToFolderFieldName < -1) { // move to folder field is missing throw new KettleStepException(BaseMessages.getString(PKG, "SFTPPut.Error.CanNotFindField", realDestinationFoldernameFieldName)); } } } // Read data top upload String sourceData = getInputRowMeta().getString(r, data.indexOfSourceFileFieldName); InputStream inputStream = null; FileObject destinationFolder = null; FileObject file = null; try { if (Const.isEmpty(sourceData)) { // Source data is empty throw new KettleStepException(BaseMessages.getString(PKG, "SFTPPut.Error.SourceDataEmpty")); } if (meta.isInputStream()) { // Source data is a stream inputStream = new ByteArrayInputStream(sourceData.getBytes()); } else { // source data is a file // let's check file file = KettleVFS.getFileObject(sourceData); if (!file.exists()) { // We can not find file throw new KettleStepException( BaseMessages.getString(PKG, "SFTPPut.Error.CanNotFindField", sourceData)); } // get stream from file inputStream = KettleVFS.getInputStream(file); } if (file != null) { if (meta.getAfterFTPS() == JobEntrySFTPPUT.AFTER_FTPSPUT_MOVE) { String realDestationFolder = getInputRowMeta().getString(r, data.indexOfMoveToFolderFieldName); if (Const.isEmpty(realDestationFolder)) { // Move to destination folder is empty throw new KettleStepException( BaseMessages.getString(PKG, "SFTPPut.Error.MoveToDestinationFolderIsEmpty")); } destinationFolder = KettleVFS.getFileObject(realDestationFolder); if (!destinationFolder.exists()) { // We can not find folder throw new KettleStepException( BaseMessages.getString(PKG, "SFTPPut.Error.CanNotFindFolder", realDestationFolder)); } } } // move to spool dir ... setSFTPDirectory(getInputRowMeta().getString(r, data.indexOfRemoteDirectory)); // Destination filename String destinationFilename = file.getName().getBaseName(); // Upload a stream data.sftpclient.put(inputStream, destinationFilename); if (file != null) { // We successfully uploaded the file // what's next ... finishTheJob(file, sourceData, destinationFolder); } putRow(getInputRowMeta(), r); // copy row to possible alternate rowset(s). if (checkFeedback(getLinesRead())) { if (isDetailed()) { logDetailed(BaseMessages.getString(PKG, "SFTPPut.Log.LineNumber") + getLinesRead()); } } } catch (Exception e) { if (getStepMeta().isDoingErrorHandling()) { sendToErrorRow = true; errorMessage = e.toString(); } else { logError(BaseMessages.getString(PKG, "SFTPPut.Log.ErrorInStep"), e); setErrors(1); stopAll(); setOutputDone(); // signal end to receiver(s) return false; } if (sendToErrorRow) { // Simply add this row to the error row putError(getInputRowMeta(), r, 1, errorMessage, null, "SFTPPUT001"); } } finally { try { if (destinationFolder != null) { destinationFolder.close(); } if (file != null) { file.close(); } if (inputStream != null) { inputStream.close(); } } catch (Exception e) { // ignore this } } return true; } protected void finishTheJob(FileObject file, String sourceData, FileObject destinationFolder) throws KettleException { try { switch (meta.getAfterFTPS()) { case JobEntrySFTPPUT.AFTER_FTPSPUT_DELETE: // Delete source file if (!file.exists()) { file.delete(); if (isDetailed()) { logDetailed(BaseMessages.getString(PKG, "SFTPPut.Log.DeletedFile", sourceData)); } } break; case JobEntrySFTPPUT.AFTER_FTPSPUT_MOVE: // Move source file FileObject destination = null; try { destination = KettleVFS.getFileObject(destinationFolder.getName().getBaseName() + Const.FILE_SEPARATOR + file.getName().getBaseName(), this); file.moveTo(destination); if (isDetailed()) { logDetailed(BaseMessages.getString(PKG, "SFTPPut.Log.FileMoved", file, destination)); } } finally { if (destination != null) { destination.close(); } } break; default: if (meta.isAddFilenameResut()) { // Add this to the result file names... ResultFile resultFile = new ResultFile(ResultFile.FILE_TYPE_GENERAL, file, getTransMeta().getName(), getStepname()); resultFile .setComment(BaseMessages.getString(PKG, "SFTPPut.Log.FilenameAddedToResultFilenames")); addResultFile(resultFile); if (isDetailed()) { logDetailed(BaseMessages.getString(PKG, "SFTPPut.Log.FilenameAddedToResultFilenames", sourceData)); } } break; } } catch (Exception e) { throw new KettleException(e); } } protected void setSFTPDirectory(String spoolDirectory) throws KettleException { boolean existfolder = data.sftpclient.folderExists(spoolDirectory); if (!existfolder) { if (!meta.isCreateRemoteFolder()) { throw new KettleException( BaseMessages.getString(PKG, "SFTPPut.Error.CanNotFindRemoteFolder", spoolDirectory)); } if (isDetailed()) { logDetailed(BaseMessages.getString(PKG, "SFTPPut.Error.CanNotFindRemoteFolder", spoolDirectory)); } // Let's create folder data.sftpclient.createFolder(spoolDirectory); if (isDetailed()) { logDetailed(BaseMessages.getString(PKG, "SFTPPut.Log.RemoteFolderCreated", spoolDirectory)); } } data.sftpclient.chdir(spoolDirectory); if (isDetailed()) { logDetailed(BaseMessages.getString(PKG, "SFTPPut.Log.ChangedDirectory", spoolDirectory)); } } public void dispose(StepMetaInterface smi, StepDataInterface sdi) { meta = (SFTPPutMeta) smi; data = (SFTPPutData) sdi; try { // Close SFTP connection if (data.sftpclient != null) { data.sftpclient.disconnect(); } } catch (Exception e) { // Ignore errors } super.dispose(smi, sdi); } }