1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport.ftp;
12
13 import org.mule.DefaultMuleMessage;
14 import org.mule.api.MuleMessage;
15 import org.mule.api.endpoint.InboundEndpoint;
16 import org.mule.api.lifecycle.CreateException;
17 import org.mule.api.service.Service;
18 import org.mule.api.transport.Connector;
19 import org.mule.transport.AbstractPollingMessageReceiver;
20 import org.mule.transport.file.FileConnector;
21
22 import java.io.FilenameFilter;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.text.MessageFormat;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Set;
31
32 import javax.resource.spi.work.Work;
33
34 import org.apache.commons.net.ftp.FTPClient;
35 import org.apache.commons.net.ftp.FTPFile;
36 import org.apache.commons.net.ftp.FTPReply;
37
38 public class FtpMessageReceiver extends AbstractPollingMessageReceiver
39 {
40 protected final FtpConnector connector;
41 protected final FilenameFilter filenameFilter;
42
43
44
45
46 protected final Set scheduledFiles = Collections.synchronizedSet(new HashSet());
47 protected final Set currentFiles = Collections.synchronizedSet(new HashSet());
48
49 public FtpMessageReceiver(Connector connector,
50 Service service,
51 InboundEndpoint endpoint,
52 long frequency) throws CreateException
53 {
54 super(connector, service, endpoint);
55
56 this.setFrequency(frequency);
57
58 this.connector = (FtpConnector) connector;
59
60 if (endpoint.getFilter() instanceof FilenameFilter)
61 {
62 this.filenameFilter = (FilenameFilter) endpoint.getFilter();
63 }
64 else
65 {
66 this.filenameFilter = null;
67 }
68 }
69
70 public void poll() throws Exception
71 {
72 FTPFile[] files = listFiles();
73
74 synchronized (scheduledFiles)
75 {
76 for (int i = 0; i < files.length; i++)
77 {
78 final FTPFile file = files[i];
79 final String fileName = file.getName();
80
81 if (!scheduledFiles.contains(fileName) && !currentFiles.contains(fileName))
82 {
83 scheduledFiles.add(fileName);
84 getWorkManager().scheduleWork(new FtpWork(fileName, file));
85 }
86 }
87 }
88 }
89
90 protected FTPFile[] listFiles() throws Exception
91 {
92 FTPClient client = null;
93 try
94 {
95 client = connector.createFtpClient(endpoint);
96 FTPFile[] files = client.listFiles();
97
98 if (!FTPReply.isPositiveCompletion(client.getReplyCode()))
99 {
100 throw new IOException("Failed to list files. Ftp error: " + client.getReplyCode());
101 }
102
103 if (files == null || files.length == 0)
104 {
105 return files;
106 }
107
108 List v = new ArrayList();
109
110 for (int i = 0; i < files.length; i++)
111 {
112 if (files[i].isFile())
113 {
114 if (filenameFilter == null || filenameFilter.accept(null, files[i].getName()))
115 {
116 v.add(files[i]);
117 }
118 }
119 }
120
121 return (FTPFile[]) v.toArray(new FTPFile[v.size()]);
122 }
123 finally
124 {
125 if (client != null)
126 {
127 connector.releaseFtp(endpoint.getEndpointURI(), client);
128 }
129 }
130 }
131
132 protected void processFile(FTPFile file) throws Exception
133 {
134 logger.debug("entering processFile()");
135
136 FTPClient client = null;
137 try
138 {
139 if (!connector.validateFile(file))
140 {
141 return;
142 }
143
144 client = connector.createFtpClient(endpoint);
145
146 MuleMessage message;
147 InputStream stream = client.retrieveFileStream(file.getName());
148 if (stream == null)
149 {
150 throw new IOException(MessageFormat.format("Failed to retrieve file {0}. Ftp error: {1}",
151 new Object[]{file.getName(), new Integer(client.getReplyCode())}));
152 }
153 message = new DefaultMuleMessage(connector.getMessageAdapter(stream));
154
155
156 message.setProperty(FileConnector.PROPERTY_ORIGINAL_FILENAME, file.getName());
157 message.setProperty(FileConnector.PROPERTY_FILE_SIZE, new Long(file.getSize()));
158 routeMessage(message);
159
160 postProcess(client, file, message);
161 }
162 finally
163 {
164 logger.debug("leaving processFile()");
165 if (client != null)
166 {
167 connector.releaseFtp(endpoint.getEndpointURI(), client);
168 }
169 }
170 }
171
172 protected void postProcess(FTPClient client, FTPFile file, MuleMessage message) throws Exception
173 {
174 if (!client.deleteFile(file.getName()))
175 {
176 throw new IOException(MessageFormat.format("Failed to delete file {0}. Ftp error: {1}",
177 new Object[]{file.getName(), new Integer(client.getReplyCode())}));
178 }
179 logger.debug("Deleted processed file " + file.getName());
180 }
181
182 protected void doConnect() throws Exception
183 {
184
185
186 }
187
188 protected void doDisconnect() throws Exception
189 {
190
191 }
192
193 protected void doDispose()
194 {
195
196 }
197
198 private final class FtpWork implements Work
199 {
200 private final String name;
201 private final FTPFile file;
202
203 private FtpWork(String name, FTPFile file)
204 {
205 this.name = name;
206 this.file = file;
207 }
208
209 public void run()
210 {
211 try
212 {
213 currentFiles.add(name);
214 processFile(file);
215 }
216 catch (Exception e)
217 {
218 connector.handleException(e);
219 }
220 finally
221 {
222 currentFiles.remove(name);
223 scheduledFiles.remove(name);
224 }
225 }
226
227 public void release()
228 {
229
230 }
231 }
232
233 }