1
2
3
4
5
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
23
24
25
26
27 public class SftpUtil
28 {
29
30 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 private final static Object lock = new Object();
41
42 public SftpUtil(ImmutableEndpoint endpoint)
43 {
44 this.endpoint = endpoint;
45 this.connector = (SftpConnector) endpoint.getConnector();
46 }
47
48 public String createUniqueSuffix(String filename)
49 {
50 SimpleDateFormat timestampFormatter = new SimpleDateFormat("yyyyMMddHHmmssSSS");
51 String timstampStr = '_' + timestampFormatter.format(new Date());
52
53 int fileTypeIdx = filename.lastIndexOf('.');
54 if (fileTypeIdx != -1)
55 {
56 String fileType = filename.substring(fileTypeIdx);
57 filename = filename.substring(0, fileTypeIdx);
58 return filename + timstampStr + fileType;
59 }
60 else
61 {
62 return filename + timstampStr;
63 }
64 }
65
66 public String getTempDirInbound()
67 {
68 String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_TEMP_DIR);
69 if (endpointValue != null)
70 {
71 return endpointValue;
72 }
73
74 String connectorValue = connector.getTempDirInbound();
75 if (connectorValue != null)
76 {
77 return connectorValue;
78 }
79
80 return null;
81 }
82
83 public boolean isUseTempDirInbound()
84 {
85 return getTempDirInbound() != null;
86 }
87
88 public String getTempDirOutbound()
89 {
90 String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_TEMP_DIR);
91 if (endpointValue != null)
92 {
93 return endpointValue;
94 }
95
96 String connectorValue = connector.getTempDirOutbound();
97 if (connectorValue != null)
98 {
99 return connectorValue;
100 }
101
102 return null;
103 }
104
105 public boolean isUseTempDirOutbound()
106 {
107 return getTempDirOutbound() != null;
108 }
109
110 public void cleanupTempDir(SftpClient sftpClient, String transferFileName, String tempDir)
111 {
112 String tempDirAbs = sftpClient.getAbsolutePath(endpoint.getEndpointURI().getPath() + "/" + tempDir);
113 try
114 {
115 sftpClient.changeWorkingDirectory(tempDirAbs);
116 sftpClient.deleteFile(transferFileName);
117 }
118 catch (Exception e)
119 {
120 logger.error("Could not delete the file '" + transferFileName + "' from the temp directory '"
121 + tempDirAbs + "'", e);
122 }
123 }
124
125 public long getSizeCheckWaitTime()
126 {
127 Object endpointValue = endpoint.getProperty(SftpConnector.PROPERTY_SIZE_CHECK_WAIT_TIME);
128 if (endpointValue != null)
129 {
130 return Long.valueOf((String) endpointValue);
131 }
132
133 Long connectorValue = connector.getSizeCheckWaitTime();
134 if (connectorValue != null)
135 {
136 return connectorValue;
137 }
138
139 return SIZE_CHECK_WAIT_TIME_DEFAULT;
140 }
141
142 public String getArchiveDir()
143 {
144 String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_ARCHIVE_DIR);
145 if (endpointValue != null)
146 {
147 return endpointValue;
148 }
149
150 String connectorValue = connector.getArchiveDir();
151 if (connectorValue != null)
152 {
153 return connectorValue;
154 }
155
156 return null;
157 }
158
159 public String getArchiveTempReceivingDir()
160 {
161 String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_ARCHIVE_TEMP_RECEIVING_DIR);
162 if (endpointValue != null)
163 {
164 return endpointValue;
165 }
166
167 String connectorValue = connector.getArchiveTempReceivingDir();
168 if (connectorValue != null)
169 {
170 return connectorValue;
171 }
172
173 return null;
174 }
175
176 public String getArchiveTempSendingDir()
177 {
178 String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_ARCHIVE_TEMP_SENDING_DIR);
179 if (endpointValue != null)
180 {
181 return endpointValue;
182 }
183
184 String connectorValue = connector.getArchiveTempSendingDir();
185 if (connectorValue != null)
186 {
187 return connectorValue;
188 }
189
190 return null;
191 }
192
193 public boolean isUseTempFileTimestampSuffix()
194 {
195 Object endpointValue = endpoint.getProperty(SftpConnector.PROPERTY_USE_TEMP_FILE_TIMESTAMP_SUFFIX);
196 if (endpointValue != null)
197 {
198 return Boolean.valueOf((String) endpointValue);
199 }
200
201 Boolean connectorValue = connector.isUseTempFileTimestampSuffix();
202 if (connectorValue != null)
203 {
204 return connectorValue;
205 }
206
207 return USE_TEMP_FILE_TIMESTAMP_SUFFIX_DEFAULT;
208 }
209
210 public String getDuplicateHandling()
211 {
212 String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_DUPLICATE_HANDLING);
213 if (endpointValue != null)
214 {
215 return endpointValue;
216 }
217
218 String connectorValue = connector.getDuplicateHandling();
219 if (connectorValue != null)
220 {
221 return connectorValue;
222 }
223
224 return DUPLICATE_HANDLING_DEFAULT;
225 }
226
227 public String getIdentityFile()
228 {
229 String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_IDENTITY_FILE);
230 if (endpointValue != null)
231 {
232 return endpointValue;
233 }
234
235 String connectorValue = connector.getIdentityFile();
236 if (connectorValue != null)
237 {
238 return connectorValue;
239 }
240
241 return null;
242 }
243
244 public String getPassphrase()
245 {
246 String endpointValue = (String) endpoint.getProperty(SftpConnector.PROPERTY_PASS_PHRASE);
247 if (endpointValue != null)
248 {
249 return endpointValue;
250 }
251
252 String connectorValue = connector.getPassphrase();
253 if (connectorValue != null)
254 {
255 return connectorValue;
256 }
257
258 return null;
259 }
260
261
262
263
264
265
266
267
268
269
270
271
272 public void cwdToTempDirOnOutbound(SftpClient sftpClient, String endpointDir) throws IOException
273 {
274 String tempDir = getTempDirOutbound();
275 String tempDirAbs = sftpClient.getAbsolutePath(endpointDir + "/" + tempDir);
276
277
278
279 synchronized (lock)
280 {
281
282 try
283 {
284
285
286 sftpClient.changeWorkingDirectory(tempDirAbs);
287 }
288 catch (IOException e)
289 {
290 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 sftpClient.changeWorkingDirectory(endpointDir);
293 sftpClient.mkdir(tempDir);
294
295 sftpClient.changeWorkingDirectory(tempDirAbs);
296 }
297 }
298 }
299
300 public boolean isKeepFileOnError()
301 {
302 Object endpointValue = endpoint.getProperty(SftpConnector.PROPERTY_KEEP_FILE_ON_ERROR);
303 if (endpointValue != null)
304 {
305 return Boolean.valueOf((String) endpointValue);
306 }
307
308 Boolean connectorValue = connector.isKeepFileOnError();
309 if (connectorValue != null)
310 {
311 return connectorValue;
312 }
313
314 return KEEP_FILE_ON_ERROR_DEFAULT;
315 }
316
317
318
319
320
321
322
323
324
325 public synchronized void copyStreamToFile(InputStream input, File destination) throws IOException
326 {
327 try
328 {
329 File folder = destination.getParentFile();
330 if (!folder.exists())
331 {
332 throw new IOException("Destination folder does not exist: " + folder);
333 }
334
335 if (!folder.canWrite())
336 {
337 throw new IOException("Destination folder is not writeable: " + folder);
338 }
339
340 FileOutputStream output = new FileOutputStream(destination);
341 try
342 {
343 IOUtils.copy(input, output);
344 }
345 finally
346 {
347 if (output != null) output.close();
348 }
349 }
350 catch (IOException ex)
351 {
352 setErrorOccurredOnInputStream(input);
353 throw ex;
354 }
355 catch (RuntimeException ex)
356 {
357 setErrorOccurredOnInputStream(input);
358 throw ex;
359 }
360 finally
361 {
362 if (input != null) input.close();
363 }
364 }
365
366 public void setErrorOccurredOnInputStream(InputStream inputStream)
367 {
368
369 if (isKeepFileOnError())
370 {
371
372
373
374
375 if (inputStream != null)
376 {
377 if (inputStream instanceof ErrorOccurredDecorator)
378 {
379
380
381
382 ((ErrorOccurredDecorator) inputStream).setErrorOccurred();
383
384 }
385 else
386 {
387 logger.warn("Class "
388 + inputStream.getClass().getName()
389 + " did not implement the 'ErrorOccurred' decorator, errorOccured=true could not be set.");
390 }
391 }
392 }
393 }
394 }