Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * $Id: SftpReceiverRequesterUtil.java 21125 2011-01-26 21:21:10Z dzapata $
   * --------------------------------------------------------------------------------------
   * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
   *
   * The software in this package is published under the terms of the CPAL v1.0
   * license, a copy of which has been included with this distribution in the
   * LICENSE.txt file.
   */
 
 package org.mule.transport.sftp;
 
 
 import java.io.File;
 import java.util.List;

Contains reusable methods not directly related to usage of the jsch sftp library (they can be found in the class SftpClient).

Author(s):
Magnus Larsson
 
 {
     private transient Log logger = LogFactory.getLog(getClass());
 
     private final SftpConnector connector;
     private final ImmutableEndpoint endpoint;
     private final FilenameFilter filenameFilter;
     private final SftpUtil sftpUtil;
 
     public SftpReceiverRequesterUtil(ImmutableEndpoint endpoint)
     {
         this. = endpoint;
         this. = (SftpConnectorendpoint.getConnector();
 
          = new SftpUtil(endpoint);
 
         if (endpoint.getFilter() instanceof FilenameFilter)
         {
             this. = (FilenameFilterendpoint.getFilter();
         }
         else
         {
             this. = null;
         }
 
     }
 
     // Get files in directory configured on the endpoint
     public String[] getAvailableFiles(boolean onlyGetTheFirstOnethrows Exception
     {
         // This sftp client instance is only for checking available files. This
         // instance cannot be shared
         // with clients that retrieve files because of thread safety
 
         if (.isDebugEnabled())
         {
             .debug("Checking files at endpoint " + .getEndpointURI());
         }
 
         SftpClient client = null;
 
         try
         {
             client = .createSftpClient();
 
             long fileAge = .getFileAge();
             boolean checkFileAge = .getCheckFileAge();
 
             // Override the value from the Endpoint?
             if (.getProperty(.) != null)
             {
                 checkFileAge = true;
                 fileAge = Long.valueOf((String.getProperty(.));
             }
 
             .debug("fileAge : " + fileAge);
 
             // Get size check parameter
             long sizeCheckDelayMs = .getSizeCheckWaitTime();
 
             String[] files = client.listFiles();
 
             // Only return files that have completely been written and match
             // fileExtension
             List<StringcompletedFiles = new ArrayList<String>(files.length);
 
             for (String file : files)
             {
                // Skip if no match.
                // Note, Mule also uses this filter. We use the filter here because
                // we don't want to
                // run the below tests (checkFileAge, sizeCheckDelayMs etc) for files
                // that Mule
                // later should have ignored. Thus this is an "early" filter so that
                // improves performance.
                if ( != null && !.accept(nullfile))
                {
                    continue;
                }
                if (checkFileAge || sizeCheckDelayMs >= 0)
                {
                    // See if the file is still growing (either by age or size),
                    // leave it alone if it is
                    if (!hasChanged(fileclientfileAgesizeCheckDelayMs))
                    {
                        // logger.debug("marking file [" + files[i] +
                        // "] as in transit.");
                        // client.rename(files[i], files[i] + ".transtit");
                        // completedFiles.add( files[i] + ".transtit" );
                        completedFiles.add(file);
                        if (onlyGetTheFirstOne)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    completedFiles.add(file);
                    if (onlyGetTheFirstOne)
                    {
                        break;
                    }
                }
            }
            return completedFiles.toArray(new String[completedFiles.size()]);
        }
        finally
        {
            if (client != null)
            {
                .releaseClient(client);
            }
        }
    }
    public InputStream retrieveFile(String fileNameSftpNotifier notifierthrows Exception
    {
        // Getting a new SFTP client dedicated to the SftpInputStream below
        SftpClient client = .createSftpClient(notifier);
        // Check usage of tmpSendingDir
        String tmpSendingDir = .getTempDirInbound();
        if (tmpSendingDir != null)
        {
            // Check usage of unique names of files during transfer
            boolean addUniqueSuffix = .isUseTempFileTimestampSuffix();
            // TODO: is it possibly to move this to some kind of init method?
            client.createSftpDirIfNotExists(tmpSendingDir);
            String tmpSendingFileName = tmpSendingDir + "/" + fileName;
            if (addUniqueSuffix)
            {
                tmpSendingFileName = .createUniqueSuffix(tmpSendingFileName);
            }
            String fullTmpSendingPath = .getEndpointURI().getPath() + "/" + tmpSendingFileName;
            if (.isDebugEnabled())
            {
                .debug("Move " + fileName + " to " + fullTmpSendingPath);
            }
            client.rename(fileNamefullTmpSendingPath);
            fileName = tmpSendingFileName;
            if (.isDebugEnabled())
            {
                .debug("Move done");
            }
        }
        // Archive functionality...
        String archive = .getArchiveDir();
        // Retrieve the file stream
        InputStream fileInputStream = client.retrieveFile(fileName);
        if (!"".equals(archive))
        {
            String archiveTmpReceivingDir = .getArchiveTempReceivingDir();
            String archiveTmpSendingDir = .getArchiveTempSendingDir();
            InputStream is = new SftpInputStream(clientfileInputStreamfileName.isAutoDelete(),
                );
            // TODO ML FIX. Refactor to util-class...
            int idx = fileName.lastIndexOf('/');
            String fileNamePart = fileName.substring(idx + 1);
            // don't use new File() directly, see MULE-1112
            File archiveFile = FileUtils.newFile(archivefileNamePart);
            // Should temp dirs be used when handling the archive file?
            if ("".equals(archiveTmpReceivingDir) || "".equals(archiveTmpSendingDir))
            {
                return archiveFile(isarchiveFile);
            }
            else
            {
                return archiveFileUsingTempDirs(archivearchiveTmpReceivingDirarchiveTmpSendingDiris,
                    fileNamePartarchiveFile);
            }
        }
        // This special InputStream closes the SftpClient when the stream is closed.
        // The stream will be materialized in a Message Dispatcher or Service
        // Component
        return new SftpInputStream(clientfileInputStreamfileName.isAutoDelete(), );
    }
    private InputStream archiveFileUsingTempDirs(String archive,
                                                 String archiveTmpReceivingDir,
                                                 String archiveTmpSendingDir,
                                                 InputStream is,
                                                 String fileNamePart,
                                                 File archiveFilethrows IOException
    {
        File archiveTmpReceivingFolder = FileUtils.newFile(archive + '/' + archiveTmpReceivingDir);
        File archiveTmpReceivingFile = FileUtils.newFile(archive + '/' + archiveTmpReceivingDirfileNamePart);
        if (!archiveTmpReceivingFolder.exists())
        {
            if (.isInfoEnabled())
            {
                .info("Creates " + archiveTmpReceivingFolder.getAbsolutePath());
            }
            if (!archiveTmpReceivingFolder.mkdirs())
                throw new IOException("Failed to create archive-tmp-receiving-folder: "
                                      + archiveTmpReceivingFolder);
        }
        File archiveTmpSendingFolder = FileUtils.newFile(archive + '/' + archiveTmpSendingDir);
        File archiveTmpSendingFile = FileUtils.newFile(archive + '/' + archiveTmpSendingDirfileNamePart);
        if (!archiveTmpSendingFolder.exists())
        {
            if (.isInfoEnabled())
            {
                .info("Creates " + archiveTmpSendingFolder.getAbsolutePath());
            }
            if (!archiveTmpSendingFolder.mkdirs())
                throw new IOException("Failed to create archive-tmp-sending-folder: "
                                      + archiveTmpSendingFolder);
        }
        if (.isInfoEnabled())
        {
            .info("Copy SftpInputStream to archiveTmpReceivingFile... "
                        + archiveTmpReceivingFile.getAbsolutePath());
        }
        .copyStreamToFile(isarchiveTmpReceivingFile);
        // TODO. ML FIX. Should be performed before the sftp:delete - operation, i.e.
        // in the SftpInputStream in the operation above...
        if (.isInfoEnabled())
        {
            .info("Move archiveTmpReceivingFile (" + archiveTmpReceivingFile
                        + ") to archiveTmpSendingFile (" + archiveTmpSendingFile + ")...");
        }
        FileUtils.moveFile(archiveTmpReceivingFilearchiveTmpSendingFile);
        if (.isDebugEnabled())
        {
            .debug("Return SftpFileArchiveInputStream for archiveTmpSendingFile ("
                         + archiveTmpSendingFile + ")...");
        }
        return new SftpFileArchiveInputStream(archiveTmpSendingFilearchiveFile);
    }
    private InputStream archiveFile(InputStream isFile archiveFilethrows IOException
    {
        File archiveFolder = FileUtils.newFile(archiveFile.getParentFile().getPath());
        if (!archiveFolder.exists())
        {
            if (.isInfoEnabled())
            {
                .info("Creates " + archiveFolder.getAbsolutePath());
            }
            if (!archiveFolder.mkdirs())
                throw new IOException("Failed to create archive-folder: " + archiveFolder);
        }
        if (.isInfoEnabled())
        {
            .info("Copy SftpInputStream to archiveFile... " + archiveFile.getAbsolutePath());
        }
        .copyStreamToFile(isarchiveFile);
        if (.isDebugEnabled())
        {
            .debug("*** Return SftpFileArchiveInputStream for archiveFile...");
        }
        return new SftpFileArchiveInputStream(archiveFile);
    }

    
Checks if the file has been changed.

Note! This assumes that the time on both servers are synchronized!

Parameters:
fileName The file to check
client instance of StftClient
fileAge How old the file should be to be considered "old" and not changed
sizeCheckDelayMs Wait time (in ms) between size-checks to determine if a file is ready to be processed.
Returns:
true if the file has changed
Throws:
java.lang.Exception Error
    private boolean hasChanged(String fileNameSftpClient clientlong fileAgelong sizeCheckDelayMs)
        throws Exception
    {
        // Perform fileAge test if configured
        // Note that for this to work it is required that the system clock on the
        // mule server
        // is synchronized with the system clock on the sftp server
        if (fileAge > 0)
        {
            long lastModifiedTime = client.getLastModifiedTime(fileName);
            // TODO Can we get the current time from the other server?
            long now = System.currentTimeMillis();
            long diff = now - lastModifiedTime;
            // If the diff is negative it's a sign that the time on the test server
            // and the ftps-server is not synchronized
            if (diff < fileAge)
            {
                if (.isDebugEnabled())
                {
                    .debug("The file has not aged enough yet, will return nothing for: " + fileName
                                 + ". The file must be " + (fileAge - diff) + "ms older, was " + diff);
                }
                return true;
            }
            if (.isDebugEnabled())
            {
                .debug("The file " + fileName + " has aged enough. Was " + diff);
            }
        }
        // Perform a size check with a short configurable latencey between the
        // size-calls
        // Take consecutive file size snapshots to determine if file is still being
        // written
        if (sizeCheckDelayMs > 0)
        {
            .info("Perform size check with a delay of: " + sizeCheckDelayMs + " ms.");
            long fileSize1 = client.getSize(fileName);
            Thread.sleep(sizeCheckDelayMs);
            long fileSize2 = client.getSize(fileName);
            if (fileSize1 == fileSize2)
            {
                .info("File is stable (not growing), ready for retrieval: " + fileName);
            }
            else
            {
                .info("File is growing, deferring retrieval: " + fileName);
                return true;
            }
        }
        // None of file-change tests faile so we can retrieve this file
        return false;
    }
New to GrepCode? Check out our FAQ X