View Javadoc

1   /*
2    * $Id: SftpInputStream.java 21125 2011-01-26 21:21:10Z dzapata $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.transport.sftp;
12  
13  import org.apache.commons.logging.Log;
14  import org.apache.commons.logging.LogFactory;
15  import org.mule.api.endpoint.ImmutableEndpoint;
16  
17  import java.io.BufferedInputStream;
18  import java.io.IOException;
19  import java.io.InputStream;
20  
21  /**
22   * <code>SftpInputStream</code> wraps an sftp InputStream.
23   */
24  
25  public class SftpInputStream extends BufferedInputStream implements ErrorOccurredDecorator
26  {
27      private final Log logger = LogFactory.getLog(getClass());
28  
29      private SftpClient client;
30      private boolean autoDelete = true;
31      private String fileName;
32  
33      public String getFileName()
34      {
35          return fileName;
36      }
37  
38      public void setFileName(String fileName)
39      {
40          this.fileName = fileName;
41      }
42  
43      private boolean errorOccured = false;
44      private ImmutableEndpoint endpoint;
45  
46      // Log every 10 000 000 bytes read at debug-level
47      // Good if really large files are transferred and you tend to get nervous by not
48      // seeing any progress in the logfile...
49      private static final int LOG_BYTE_INTERVAL = 10000000;
50      private long bytesRead = 0;
51      private long nextLevelToLogBytesRead = LOG_BYTE_INTERVAL;
52  
53      /**
54       * A special sftp InputStream. The constructor creates the InputStream by calling
55       * <code>SftpClient.retrieveFile(fileName)</code>. The client passed in is
56       * destroyed when the stream is closed.
57       * 
58       * @param client The SftpClient instance. Will be destroyed when stream closed.
59       * @param is The stream that should be used
60       * @param fileName name of the file to be retrieved
61       * @param autoDelete whether the file specified by fileName should be deleted
62       * @param endpoint the endpoint associated to a specific client (connector) pool.
63       * @throws Exception if failing to retrieve internal input stream.
64       */
65      public SftpInputStream(SftpClient client,
66                             InputStream is,
67                             String fileName,
68                             boolean autoDelete,
69                             ImmutableEndpoint endpoint) throws Exception
70      {
71          super(is);
72  
73          this.client = client;
74          this.fileName = fileName;
75          this.autoDelete = autoDelete;
76          this.endpoint = endpoint;
77      }
78  
79      @Override
80      public synchronized int read() throws IOException
81      {
82          logReadBytes(1);
83          return super.read();
84      }
85  
86      @Override
87      public synchronized int read(byte[] b, int off, int len) throws IOException
88      {
89          logReadBytes(len);
90          return super.read(b, off, len);
91      }
92  
93      @Override
94      public int read(byte[] b) throws IOException
95      {
96          logReadBytes(b.length);
97          return super.read(b);
98      }
99  
100     public void close() throws IOException
101     {
102         if (logger.isDebugEnabled())
103         {
104             logger.debug("Closing the stream for the file " + fileName);
105         }
106         try
107         {
108             super.close();
109 
110             if (autoDelete && !errorOccured)
111             {
112                 client.deleteFile(fileName);
113             }
114         }
115         catch (IOException e)
116         {
117             logger.error("Error occured while closing file " + fileName, e);
118             throw e;
119         }
120         finally
121         {
122             // We should release the connection from the pool even if some error
123             // occurs here
124             try
125             {
126                 ((SftpConnector) endpoint.getConnector()).releaseClient(endpoint, client);
127             }
128             catch (Exception e)
129             {
130                 logger.error(e.getMessage(), e);
131             }
132         }
133     }
134 
135     public void setErrorOccurred()
136     {
137         if (logger.isDebugEnabled()) logger.debug("setErrorOccurred() called");
138         this.errorOccured = true;
139     }
140 
141     @Override
142     public String toString()
143     {
144         return "SftpInputStream{" + "fileName='" + fileName + '\'' + " from endpoint="
145                + endpoint.getEndpointURI() + '}';
146     }
147 
148     private void logReadBytes(int newBytesRead)
149     {
150         if (!logger.isDebugEnabled()) return;
151 
152         this.bytesRead += newBytesRead;
153         if (this.bytesRead >= nextLevelToLogBytesRead)
154         {
155             logger.debug("Read " + this.bytesRead + " bytes and couting...");
156             nextLevelToLogBytesRead += LOG_BYTE_INTERVAL;
157         }
158     }
159 
160 }