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