View Javadoc
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.MuleEvent;
10  import org.mule.api.MuleMessage;
11  import org.mule.api.endpoint.OutboundEndpoint;
12  import org.mule.transport.AbstractMessageDispatcher;
13  import org.mule.transport.sftp.notification.SftpNotifier;
14  
15  import java.io.ByteArrayInputStream;
16  import java.io.InputStream;
17  
18  /**
19   * <code>SftpMessageDispatcher</code> dispatches files via sftp to a remote sftp
20   * service. This dispatcher reads an InputStream, byte[], or String payload, which is
21   * then streamed to the SFTP endpoint.
22   */
23  
24  public class SftpMessageDispatcher extends AbstractMessageDispatcher
25  {
26  
27      private SftpConnector connector;
28      private SftpUtil sftpUtil = null;
29  
30      public SftpMessageDispatcher(OutboundEndpoint endpoint)
31      {
32          super(endpoint);
33          connector = (SftpConnector) endpoint.getConnector();
34          sftpUtil = new SftpUtil(endpoint);
35      }
36  
37      // protected void doConnect() throws Exception
38      // {
39      // super.doConnect();
40      //
41      // SftpClient client = null;
42      // if (sftpUtil.isUseTempDir()) {
43      // if (logger.isDebugEnabled()) {
44      // logger.debug("Initializing temp directory for endpoint " +
45      // super.getEndpoint().getEndpointURI());
46      // }
47      //
48      // try {
49      // client = connector.createSftpClient(endpoint, null);
50      //
51      // sftpUtil.createSftpDirIfNotExists(client,
52      // endpoint.getEndpointURI().getPath());
53      // } finally {
54      // if (client != null) {
55      // // If the connection fails, the client will be null, otherwise disconnect.
56      // connector.releaseClient(endpoint, client);
57      // }
58      // }
59      // }
60      // }
61  
62      protected void doDisconnect() throws Exception
63      {
64          // no op
65      }
66  
67      // protected MuleMessage doReceive(long l)
68      // {
69      // throw new UnsupportedOperationException("doReceive");
70      // }
71  
72      protected void doDispose()
73      {
74          // no op
75      }
76  
77      protected void doDispatch(MuleEvent event) throws Exception
78      {
79          Object data = event.getMessage().getPayload();
80          // this is outbound because the props are copied into the outbound scope
81          // during processing
82          String filename = (String) event.getMessage().findPropertyInAnyScope(SftpConnector.PROPERTY_FILENAME,
83              null);
84          // If no name specified, set filename according to output pattern specified
85          // on
86          // endpoint or connector
87  
88          if (filename == null)
89          {
90              MuleMessage message = event.getMessage();
91  
92              String outPattern = (String) endpoint.getProperty(SftpConnector.PROPERTY_OUTPUT_PATTERN);
93              if (outPattern == null)
94              {
95                  outPattern = (String) message.getProperty(SftpConnector.PROPERTY_OUTPUT_PATTERN,
96                      connector.getOutputPattern());
97              }
98              filename = generateFilename(message, outPattern);
99          }
100 
101         // byte[], String, or InputStream payloads supported.
102 
103         byte[] buf;
104         InputStream inputStream;
105 
106         if (data instanceof byte[])
107         {
108             buf = (byte[]) data;
109             inputStream = new ByteArrayInputStream(buf);
110         }
111         else if (data instanceof InputStream)
112         {
113             inputStream = (InputStream) data;
114         }
115         else if (data instanceof String)
116         {
117             inputStream = new ByteArrayInputStream(((String) data).getBytes());
118 
119         }
120         else
121         {
122             throw new IllegalArgumentException(
123                 "Unexpected message type: java.io.InputStream, byte[], or String expected. Got "
124                                 + data.getClass().getName());
125         }
126 
127         if (logger.isDebugEnabled())
128         {
129             logger.debug("Writing file to: " + endpoint.getEndpointURI() + " [" + filename + "]");
130 
131         }
132 
133         SftpClient client = null;
134         boolean useTempDir = false;
135         String transferFilename = null;
136 
137         try
138         {
139             String serviceName = (event.getFlowConstruct() == null)
140                                                                    ? "UNKNOWN SERVICE"
141                                                                    : event.getFlowConstruct().getName();
142             SftpNotifier notifier = new SftpNotifier(connector, event.getMessage(), endpoint, serviceName);
143             client = connector.createSftpClient(endpoint, notifier);
144             String destDir = endpoint.getEndpointURI().getPath();
145 
146             if (logger.isDebugEnabled())
147             {
148                 logger.debug("Connection setup successful, writing file.");
149             }
150 
151             // Duplicate Handling
152             filename = client.duplicateHandling(destDir, filename, sftpUtil.getDuplicateHandling());
153             transferFilename = filename;
154 
155             useTempDir = sftpUtil.isUseTempDirOutbound();
156             if (useTempDir)
157             {
158                 // TODO move to a init-method like doConnect?
159                 // cd to tempDir and create it if it doesn't already exist
160                 sftpUtil.cwdToTempDirOnOutbound(client, destDir);
161 
162                 // Add unique file-name (if configured) for use during transfer to
163                 // temp-dir
164                 boolean addUniqueSuffix = sftpUtil.isUseTempFileTimestampSuffix();
165                 if (addUniqueSuffix)
166                 {
167                     transferFilename = sftpUtil.createUniqueSuffix(transferFilename);
168                 }
169             }
170 
171             // send file over sftp
172             client.storeFile(transferFilename, inputStream);
173 
174             if (useTempDir)
175             {
176                 // Move the file to its final destination
177                 client.rename(transferFilename, destDir + "/" + filename);
178             }
179 
180             logger.info("Successfully wrote file '" + filename + "' to " + endpoint.getEndpointURI());
181         }
182         catch (Exception e)
183         {
184             logger.error("Unexpected exception attempting to write file, message was: " + e.getMessage(), e);
185 
186             sftpUtil.setErrorOccurredOnInputStream(inputStream);
187 
188             if (useTempDir)
189             {
190                 // Cleanup the remote temp dir from the not fullt completely
191                 // transferred file!
192                 String tempDir = sftpUtil.getTempDirOutbound();
193                 sftpUtil.cleanupTempDir(client, transferFilename, tempDir);
194             }
195             throw e;
196         }
197         finally
198         {
199             if (client != null)
200             {
201                 // If the connection fails, the client will be null, otherwise
202                 // disconnect.
203                 connector.releaseClient(endpoint, client);
204             }
205             // else
206             // {
207             // logger.warn("Unexpected null SFTPClient instance - operation probably failed ...");
208             // }
209 
210             inputStream.close();
211 
212         }
213 
214     }
215 
216     protected MuleMessage doSend(MuleEvent event) throws Exception
217     {
218         doDispatch(event);
219         return event.getMessage();
220     }
221 
222     // public Object getDelegateSession()
223     // {
224     // return null;
225     // }
226 
227     private String generateFilename(MuleMessage message, String pattern)
228     {
229         if (pattern == null)
230         {
231             pattern = connector.getOutputPattern();
232         }
233         return connector.getFilenameParser().getFilename(message, pattern);
234     }
235 }