View Javadoc

1   /*
2    * $Id: FtpMessageRequester.java 19191 2010-08-25 21:05:23Z tcarlson $
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.ftp;
12  
13  import org.mule.api.MuleMessage;
14  import org.mule.api.endpoint.EndpointURI;
15  import org.mule.api.endpoint.InboundEndpoint;
16  import org.mule.api.lifecycle.CreateException;
17  import org.mule.api.lifecycle.InitialisationException;
18  import org.mule.transport.AbstractMessageRequester;
19  
20  import java.io.File;
21  import java.io.FilenameFilter;
22  import java.io.IOException;
23  
24  import org.apache.commons.net.ftp.FTPClient;
25  import org.apache.commons.net.ftp.FTPFile;
26  import org.apache.commons.net.ftp.FTPReply;
27  
28  public class FtpMessageRequester extends AbstractMessageRequester
29  {
30      protected final FtpConnector connector;
31  
32      public FtpMessageRequester(InboundEndpoint endpoint)
33      {
34          super(endpoint);
35          this.connector = (FtpConnector) endpoint.getConnector();
36      }
37  
38      @Override
39      protected void doDispose()
40      {
41          // no op
42      }
43  
44      @Override
45      protected void doConnect() throws Exception
46      {
47          // no op
48      }
49  
50      @Override
51      protected void doDisconnect() throws Exception
52      {
53          try
54          {
55              EndpointURI uri = endpoint.getEndpointURI();
56              FTPClient client = connector.getFtp(uri);
57              connector.destroyFtp(uri, client);
58          }
59          catch (Exception e)
60          {
61              // pool may be closed
62          }
63      }
64  
65      /**
66       * Make a specific request to the underlying transport
67       *
68       * @param timeout The maximum time the operation should block before returning.
69       *         The call should return immediately if there is data available. If
70       *         no data becomes available before the timeout elapses, null will be
71       *         returned.
72       * @return The result of the request wrapped in a MuleMessage object. <code>null</code> will be
73       *          returned if no data was avaialable
74       * @throws Exception if the call to the underlying protocol cuases an exception
75       */
76      @Override
77      protected MuleMessage doRequest(long timeout) throws Exception
78      {
79          FTPClient client = null;
80          try
81          {
82              client = connector.createFtpClient(endpoint);
83              FTPFile fileToProcess = findFileToProcess(client);
84              if (fileToProcess == null)
85              {
86                  return null;
87              }
88  
89              fileToProcess = prepareFile(client, fileToProcess);
90  
91              FtpMuleMessageFactory messageFactory = createMuleMessageFactory(client);
92              return messageFactory.create(fileToProcess, endpoint.getEncoding());
93          }
94          finally
95          {
96              connector.releaseFtp(endpoint.getEndpointURI(), client);
97          }
98      }
99      
100     @Override
101     protected void initializeMessageFactory() throws InitialisationException
102     {
103         // Do not initialize the muleMessageFactory instance variable of our super class as 
104         // we're creating MuleMessageFactory instances per request. 
105         // See createMuleMessageFactory(FTPClient) below.
106     }
107 
108     protected FtpMuleMessageFactory createMuleMessageFactory(FTPClient client) throws CreateException
109     {
110         FtpMuleMessageFactory factory = (FtpMuleMessageFactory) createMuleMessageFactory();
111         // We might want to use isStreaming from connector, but for now maintain existing behaviour.
112         factory.setStreaming(false);
113         factory.setFtpClient(client);
114         
115         return factory;
116     }
117 
118     protected FTPFile prepareFile(FTPClient client, FTPFile file) throws IOException
119     {
120         return file;
121     }
122 
123     protected FTPFile findFileToProcess(FTPClient client) throws Exception
124     {
125         FTPFile[] files = listFiles(client);
126 
127         if (files != null)
128         {
129             FilenameFilter filenameFilter = getFilenameFilter();
130             for (int i = 0; i < files.length; i++)
131             {
132                 FTPFile file = files[i];
133                 if (file.isFile())
134                 {
135                     if (filenameFilter.accept(null, file.getName()))
136                     {
137                         if (connector.validateFile(file))
138                         {
139                             // only read the first one
140                             return file;
141                         }
142                     }
143                 }
144             }
145         }
146         
147         return null;
148     }
149 
150     protected FTPFile[] listFiles(FTPClient client) throws IOException
151     {
152         FTPFile[] files = client.listFiles();
153         if (!FTPReply.isPositiveCompletion(client.getReplyCode()))
154         {
155             throw new IOException("Ftp error: " + client.getReplyCode());
156         }
157         
158         if (files == null || files.length == 0)
159         {
160             return null;
161         }
162         
163         return files;
164     }
165 
166     protected FilenameFilter getFilenameFilter()
167     {
168         if (endpoint.getFilter() instanceof FilenameFilter)
169         {
170             return (FilenameFilter) endpoint.getFilter();
171         }
172         
173         return new AcceptAllFilenameFilter();
174     }
175     
176     private static class AcceptAllFilenameFilter implements FilenameFilter
177     {
178         public AcceptAllFilenameFilter()
179         {
180             super();
181         }
182         
183         public boolean accept(File dir, String name)
184         {
185             return true;
186         }
187     }
188 }