View Javadoc

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