Coverage Report - org.mule.transport.sftp.SftpUtil
 
Classes in this File Line Coverage Branch Coverage Complexity
SftpUtil
0%
0/134
0%
0/66
4.211
 
 1  
 /*
 2  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 3  
  * The software in this package is published under the terms of the CPAL v1.0
 4  
  * license, a copy of which has been included with this distribution in the
 5  
  * LICENSE.txt file.
 6  
  */
 7  
 package org.mule.transport.sftp;
 8  
 
 9  
 import org.mule.api.endpoint.ImmutableEndpoint;
 10  
 
 11  
 import java.io.File;
 12  
 import java.io.FileOutputStream;
 13  
 import java.io.IOException;
 14  
 import java.io.InputStream;
 15  
 import java.text.SimpleDateFormat;
 16  
 import java.util.Date;
 17  
 
 18  
 import org.apache.commons.io.IOUtils;
 19  
 import org.apache.log4j.Logger;
 20  
 
 21  
 /**
 22  
  * Contains reusable methods not directly related to usage of the jsch sftp library
 23  
  * (they can be found in the class SftpClient).
 24  
  *
 25  
  * @author Magnus Larsson
 26  
  */
 27  
 public class SftpUtil
 28  
 {
 29  
     /** Logger */
 30  0
     private static final Logger logger = Logger.getLogger(SftpUtil.class);
 31  
 
 32  
     private SftpConnector connector;
 33  
     private ImmutableEndpoint endpoint;
 34  
 
 35  
     private static final String DUPLICATE_HANDLING_DEFAULT = SftpConnector.PROPERTY_DUPLICATE_HANDLING_THROW_EXCEPTION;
 36  
     private static final boolean KEEP_FILE_ON_ERROR_DEFAULT = true;
 37  
     private static final boolean USE_TEMP_FILE_TIMESTAMP_SUFFIX_DEFAULT = false;
 38  
     private static final long SIZE_CHECK_WAIT_TIME_DEFAULT = -1;
 39  
 
 40  0
     private final static Object lock = new Object();
 41  
 
 42  
     public SftpUtil(ImmutableEndpoint endpoint)
 43  0
     {
 44  0
         this.endpoint = endpoint;
 45  0
         this.connector = (SftpConnector) endpoint.getConnector();
 46  0
     }
 47  
 
 48  
     public String createUniqueSuffix(String filename)
 49  
     {
 50  0
         SimpleDateFormat timestampFormatter = new SimpleDateFormat("yyyyMMddHHmmssSSS");
 51  0
         String timstampStr = '_' + timestampFormatter.format(new Date());
 52  
 
 53  0
         int fileTypeIdx = filename.lastIndexOf('.');
 54  0
         if (fileTypeIdx != -1)
 55  
         {
 56  0
             String fileType = filename.substring(fileTypeIdx);
 57  0
             filename = filename.substring(0, fileTypeIdx);
 58  0
             return filename + timstampStr + fileType;
 59  
         }
 60  
         else
 61  
         {
 62  0
             return filename + timstampStr;
 63  
         }
 64  
     }
 65  
 
 66  
     public String getTempDirInbound()
 67  
     {
 68  0
         String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_TEMP_DIR);
 69  0
         if (endpointValue != null)
 70  
         {
 71  0
             return endpointValue;
 72  
         }
 73  
 
 74  0
         String connectorValue = connector.getTempDirInbound();
 75  0
         if (connectorValue != null)
 76  
         {
 77  0
             return connectorValue;
 78  
         }
 79  
 
 80  0
         return null;
 81  
     }
 82  
 
 83  
     public boolean isUseTempDirInbound()
 84  
     {
 85  0
         return getTempDirInbound() != null;
 86  
     }
 87  
 
 88  
     public String getTempDirOutbound()
 89  
     {
 90  0
         String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_TEMP_DIR);
 91  0
         if (endpointValue != null)
 92  
         {
 93  0
             return endpointValue;
 94  
         }
 95  
 
 96  0
         String connectorValue = connector.getTempDirOutbound();
 97  0
         if (connectorValue != null)
 98  
         {
 99  0
             return connectorValue;
 100  
         }
 101  
 
 102  0
         return null;
 103  
     }
 104  
 
 105  
     public boolean isUseTempDirOutbound()
 106  
     {
 107  0
         return getTempDirOutbound() != null;
 108  
     }
 109  
 
 110  
     public void cleanupTempDir(SftpClient sftpClient, String transferFileName, String tempDir)
 111  
     {
 112  0
         String tempDirAbs = sftpClient.getAbsolutePath(endpoint.getEndpointURI().getPath() + "/" + tempDir);
 113  
         try
 114  
         {
 115  0
             sftpClient.changeWorkingDirectory(tempDirAbs);
 116  0
             sftpClient.deleteFile(transferFileName);
 117  
         }
 118  0
         catch (Exception e)
 119  
         {
 120  0
             logger.error("Could not delete the file '" + transferFileName + "' from the temp directory '"
 121  
                          + tempDirAbs + "'", e);
 122  0
         }
 123  0
     }
 124  
 
 125  
     public long getSizeCheckWaitTime()
 126  
     {
 127  0
         Object endpointValue = endpoint.getProperty(SftpConnector.PROPERTY_SIZE_CHECK_WAIT_TIME);
 128  0
         if (endpointValue != null)
 129  
         {
 130  0
             return Long.valueOf((String) endpointValue);
 131  
         }
 132  
 
 133  0
         Long connectorValue = connector.getSizeCheckWaitTime();
 134  0
         if (connectorValue != null)
 135  
         {
 136  0
             return connectorValue;
 137  
         }
 138  
 
 139  0
         return SIZE_CHECK_WAIT_TIME_DEFAULT;
 140  
     }
 141  
 
 142  
     public String getArchiveDir()
 143  
     {
 144  0
         String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_ARCHIVE_DIR);
 145  0
         if (endpointValue != null)
 146  
         {
 147  0
             return endpointValue;
 148  
         }
 149  
 
 150  0
         String connectorValue = connector.getArchiveDir();
 151  0
         if (connectorValue != null)
 152  
         {
 153  0
             return connectorValue;
 154  
         }
 155  
 
 156  0
         return null;
 157  
     }
 158  
 
 159  
     public String getArchiveTempReceivingDir()
 160  
     {
 161  0
         String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_ARCHIVE_TEMP_RECEIVING_DIR);
 162  0
         if (endpointValue != null)
 163  
         {
 164  0
             return endpointValue;
 165  
         }
 166  
 
 167  0
         String connectorValue = connector.getArchiveTempReceivingDir();
 168  0
         if (connectorValue != null)
 169  
         {
 170  0
             return connectorValue;
 171  
         }
 172  
 
 173  0
         return null;
 174  
     }
 175  
 
 176  
     public String getArchiveTempSendingDir()
 177  
     {
 178  0
         String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_ARCHIVE_TEMP_SENDING_DIR);
 179  0
         if (endpointValue != null)
 180  
         {
 181  0
             return endpointValue;
 182  
         }
 183  
 
 184  0
         String connectorValue = connector.getArchiveTempSendingDir();
 185  0
         if (connectorValue != null)
 186  
         {
 187  0
             return connectorValue;
 188  
         }
 189  
 
 190  0
         return null;
 191  
     }
 192  
 
 193  
     public boolean isUseTempFileTimestampSuffix()
 194  
     {
 195  0
         Object endpointValue = endpoint.getProperty(SftpConnector.PROPERTY_USE_TEMP_FILE_TIMESTAMP_SUFFIX);
 196  0
         if (endpointValue != null)
 197  
         {
 198  0
             return Boolean.valueOf((String) endpointValue);
 199  
         }
 200  
 
 201  0
         Boolean connectorValue = connector.isUseTempFileTimestampSuffix();
 202  0
         if (connectorValue != null)
 203  
         {
 204  0
             return connectorValue;
 205  
         }
 206  
 
 207  0
         return USE_TEMP_FILE_TIMESTAMP_SUFFIX_DEFAULT;
 208  
     }
 209  
 
 210  
     public String getDuplicateHandling()
 211  
     {
 212  0
         String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_DUPLICATE_HANDLING);
 213  0
         if (endpointValue != null)
 214  
         {
 215  0
             return endpointValue;
 216  
         }
 217  
 
 218  0
         String connectorValue = connector.getDuplicateHandling();
 219  0
         if (connectorValue != null)
 220  
         {
 221  0
             return connectorValue;
 222  
         }
 223  
 
 224  0
         return DUPLICATE_HANDLING_DEFAULT;
 225  
     }
 226  
 
 227  
     public String getIdentityFile()
 228  
     {
 229  0
         String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_IDENTITY_FILE);
 230  0
         if (endpointValue != null)
 231  
         {
 232  0
             return endpointValue;
 233  
         }
 234  
 
 235  0
         String connectorValue = connector.getIdentityFile();
 236  0
         if (connectorValue != null)
 237  
         {
 238  0
             return connectorValue;
 239  
         }
 240  
 
 241  0
         return null;
 242  
     }
 243  
 
 244  
     public String getPassphrase()
 245  
     {
 246  0
         String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_PASS_PHRASE);
 247  0
         if (endpointValue != null)
 248  
         {
 249  0
             return endpointValue;
 250  
         }
 251  
 
 252  0
         String connectorValue = connector.getPassphrase();
 253  0
         if (connectorValue != null)
 254  
         {
 255  0
             return connectorValue;
 256  
         }
 257  
 
 258  0
         return null;
 259  
     }
 260  
 
 261  
     /**
 262  
      * Changes the directory to the temp-dir on the <b>outbound</b> endpoint. Will
 263  
      * create the directory if it not already exists.
 264  
      * <p/>
 265  
      * Note, this method is synchronized because it in rare cases can be called from
 266  
      * two threads at the same time and thus cause an error.
 267  
      * 
 268  
      * @param sftpClient
 269  
      * @param endpointDir
 270  
      * @throws IOException
 271  
      */
 272  
     public void cwdToTempDirOnOutbound(SftpClient sftpClient, String endpointDir) throws IOException
 273  
     {
 274  0
         String tempDir = getTempDirOutbound();
 275  0
         String tempDirAbs = sftpClient.getAbsolutePath(endpointDir + "/" + tempDir);
 276  
 
 277  
         // We need to have a synchronized block if two++ threads tries to
 278  
         // create the same directory at the same time
 279  0
         synchronized (lock)
 280  
         {
 281  
             // Try to change directory to the temp dir, if it fails - create it
 282  
             try
 283  
             {
 284  
                 // This method will throw an exception if the directory does not
 285  
                 // exist.
 286  0
                 sftpClient.changeWorkingDirectory(tempDirAbs);
 287  
             }
 288  0
             catch (IOException e)
 289  
             {
 290  0
                 logger.info("Got an exception when trying to change the working directory to the temp dir. "
 291  
                             + "Will try to create the directory " + tempDirAbs);
 292  0
                 sftpClient.changeWorkingDirectory(endpointDir);
 293  0
                 sftpClient.mkdir(tempDir);
 294  
                 // Now it should exist!
 295  0
                 sftpClient.changeWorkingDirectory(tempDirAbs);
 296  0
             }
 297  0
         }
 298  0
     }
 299  
 
 300  
     public boolean isKeepFileOnError()
 301  
     {
 302  0
         Object endpointValue = endpoint.getProperty(SftpConnector.PROPERTY_KEEP_FILE_ON_ERROR);
 303  0
         if (endpointValue != null)
 304  
         {
 305  0
             return Boolean.valueOf((String) endpointValue);
 306  
         }
 307  
 
 308  0
         Boolean connectorValue = connector.isKeepFileOnError();
 309  0
         if (connectorValue != null)
 310  
         {
 311  0
             return connectorValue;
 312  
         }
 313  
 
 314  0
         return KEEP_FILE_ON_ERROR_DEFAULT;
 315  
     }
 316  
 
 317  
     /**
 318  
      * Should be moved to a util class that is not based on an endpoint... TODO: why
 319  
      * is this method synchronized?
 320  
      * 
 321  
      * @param input
 322  
      * @param destination
 323  
      * @throws IOException
 324  
      */
 325  
     public synchronized void copyStreamToFile(InputStream input, File destination) throws IOException
 326  
     {
 327  
         try
 328  
         {
 329  0
             File folder = destination.getParentFile();
 330  0
             if (!folder.exists())
 331  
             {
 332  0
                 throw new IOException("Destination folder does not exist: " + folder);
 333  
             }
 334  
 
 335  0
             if (!folder.canWrite())
 336  
             {
 337  0
                 throw new IOException("Destination folder is not writeable: " + folder);
 338  
             }
 339  
 
 340  0
             FileOutputStream output = new FileOutputStream(destination);
 341  
             try
 342  
             {
 343  0
                 IOUtils.copy(input, output);
 344  
             }
 345  
             finally
 346  
             {
 347  0
                 if (output != null) output.close();
 348  
             }
 349  
         }
 350  0
         catch (IOException ex)
 351  
         {
 352  0
             setErrorOccurredOnInputStream(input);
 353  0
             throw ex;
 354  
         }
 355  0
         catch (RuntimeException ex)
 356  
         {
 357  0
             setErrorOccurredOnInputStream(input);
 358  0
             throw ex;
 359  
         }
 360  
         finally
 361  
         {
 362  0
             if (input != null) input.close();
 363  
         }
 364  0
     }
 365  
 
 366  
     public void setErrorOccurredOnInputStream(InputStream inputStream)
 367  
     {
 368  
 
 369  0
         if (isKeepFileOnError())
 370  
         {
 371  
             // If an exception occurs and the keepFileOnError property is
 372  
             // true, keep the file on the originating endpoint
 373  
             // Note: this is only supported when using the sftp transport on
 374  
             // both inbound & outbound
 375  0
             if (inputStream != null)
 376  
             {
 377  0
                 if (inputStream instanceof ErrorOccurredDecorator)
 378  
                 {
 379  
                     // Ensure that the SftpInputStream or
 380  
                     // SftpFileArchiveInputStream knows about the error and
 381  
                     // dont delete the file
 382  0
                     ((ErrorOccurredDecorator) inputStream).setErrorOccurred();
 383  
 
 384  
                 }
 385  
                 else
 386  
                 {
 387  0
                     logger.warn("Class "
 388  
                                 + inputStream.getClass().getName()
 389  
                                 + " did not implement the 'ErrorOccurred' decorator, errorOccured=true could not be set.");
 390  
                 }
 391  
             }
 392  
         }
 393  0
     }
 394  
 }