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.file;
8   
9   import org.mule.DefaultMuleMessage;
10  import org.mule.api.DefaultMuleException;
11  import org.mule.api.MuleException;
12  import org.mule.api.MuleMessage;
13  import org.mule.api.endpoint.InboundEndpoint;
14  import org.mule.api.lifecycle.CreateException;
15  import org.mule.api.routing.filter.Filter;
16  import org.mule.transport.AbstractMessageRequester;
17  import org.mule.transport.file.i18n.FileMessages;
18  import org.mule.util.FileUtils;
19  
20  import java.io.File;
21  import java.io.FileFilter;
22  import java.io.FileNotFoundException;
23  import java.io.FilenameFilter;
24  import java.io.IOException;
25  
26  /**
27   * <code>FileMessageRequester</code> is used to read/write files to the filesystem
28   */
29  public class FileMessageRequester extends AbstractMessageRequester
30  {
31      private final FileConnector fileConnector;
32  
33      private String workDir = null;
34      private String workFileNamePattern = null;
35      private FilenameFilter filenameFilter = null;
36      private FileFilter fileFilter = null;
37  
38      public FileMessageRequester(InboundEndpoint endpoint) throws MuleException
39      {
40          super(endpoint);
41          this.fileConnector = (FileConnector) endpoint.getConnector();
42  
43          this.workDir = fileConnector.getWorkDirectory();
44          this.workFileNamePattern = fileConnector.getWorkFileNamePattern();
45  
46          Filter filter = endpoint.getFilter();
47          if (filter instanceof FilenameFilter)
48          {
49              filenameFilter = (FilenameFilter) filter;
50          }
51          else if (filter instanceof FileFilter)
52          {
53              fileFilter = (FileFilter) filter;
54          }
55          else if (filter != null)
56          {
57              throw new CreateException(FileMessages.invalidFileFilter(endpoint.getEndpointURI()), this);
58          }
59      }
60  
61      /**
62       * There is no associated session for a file connector
63       *
64       * @throws org.mule.api.MuleException
65       */
66      public Object getDelegateSession() throws MuleException
67      {
68          return null;
69      }
70  
71      /**
72       * Will attempt to do a receive from a directory, if the endpointUri resolves to
73       * a file name the file will be returned, otherwise the first file in the
74       * directory according to the filename filter configured on the connector.
75       *
76       * @param timeout this is ignored when doing a receive on this dispatcher
77       * @return a message containing file contents or null if there was notthing to
78       *         receive
79       * @throws Exception
80       */
81      @Override
82      protected MuleMessage doRequest(long timeout) throws Exception
83      {
84          File file = FileUtils.newFile(endpoint.getEndpointURI().getAddress());
85          File result = null;
86  
87          if (file.exists())
88          {
89              if (file.isFile())
90              {
91                  result = file;
92              }
93              else if (file.isDirectory())
94              {
95                  if (fileFilter != null)
96                  {
97                      result = FileMessageDispatcher.getNextFile(
98                          endpoint.getEndpointURI().getAddress(), fileFilter);
99                  }
100                 else
101                 {
102                     result = FileMessageDispatcher.getNextFile(
103                         endpoint.getEndpointURI().getAddress(), filenameFilter);
104                 }
105             }
106 
107             if (result != null)
108             {
109                 boolean checkFileAge = fileConnector.getCheckFileAge();
110                 if (checkFileAge)
111                 {
112                     long fileAge = fileConnector.getFileAge();
113                     long lastMod = result.lastModified();
114                     long now = System.currentTimeMillis();
115                     long thisFileAge = now - lastMod;
116                     if (thisFileAge < fileAge)
117                     {
118                         if (logger.isDebugEnabled())
119                         {
120                             logger.debug("The file has not aged enough yet, will return nothing for: "
121                                          + result.getCanonicalPath());
122                         }
123                         return null;
124                     }
125                 }
126 
127                 // Don't we need to try to obtain a file lock as we do with receiver
128                 String sourceFileOriginalName = result.getName();
129 
130                 File workFile = null;
131                 if (workDir != null)
132                 {
133                     String workFileName = formatUsingFilenameParser(sourceFileOriginalName, workFileNamePattern);
134 
135                     // don't use new File() directly, see MULE-1112
136                     workFile = FileUtils.newFile(workDir, workFileName);
137 
138                     fileConnector.move(result, workFile);
139 
140                     // Now the Work File is the Source file
141                     result = workFile;
142                 }
143 
144                 // set up destination file
145                 File destinationFile = null;
146                 String movDir = getMoveDirectory();
147                 if (movDir != null)
148                 {
149                     String destinationFileName = sourceFileOriginalName;
150                     String moveToPattern = getMoveToPattern();
151                     if (moveToPattern != null)
152                     {
153                         destinationFileName = formatUsingFilenameParser(sourceFileOriginalName, moveToPattern);
154                     }
155                     // don't use new File() directly, see MULE-1112
156                     destinationFile = FileUtils.newFile(movDir, destinationFileName);
157                 }
158 
159                 MuleMessage returnMessage = null;
160                 String encoding = endpoint.getEncoding();
161                 try
162                 {
163                     if (fileConnector.isStreaming())
164                     {
165                         ReceiverFileInputStream receiverStream = new ReceiverFileInputStream(result,
166                             fileConnector.isAutoDelete(), destinationFile);
167                         returnMessage = createMuleMessage(receiverStream, encoding);
168                     }
169                     else
170                     {
171                         returnMessage = createMuleMessage(result, encoding);
172                     }
173                 }
174                 catch (FileNotFoundException e)
175                 {
176                     // we can ignore since we did manage to acquire a lock, but just
177                     // in case
178                     logger.error("File being read disappeared!", e);
179                     return null;
180                 }
181                 returnMessage.setOutboundProperty(FileConnector.PROPERTY_ORIGINAL_FILENAME, sourceFileOriginalName);
182 
183                 if (!fileConnector.isStreaming())
184                 {
185                     moveOrDelete(result, destinationFile);
186                 }
187 
188                 // If we are streaming no need to move/delete now, that will be
189                 // done when stream is closed
190                 return returnMessage;
191             }
192         }
193         return null;
194     }
195 
196     protected String formatUsingFilenameParser(String originalName, String pattern)
197     {
198         // This isn't nice but is needed as MuleMessage is required to resolve
199         // destination file name
200         DefaultMuleMessage fileParserMessasge = new DefaultMuleMessage(null, fileConnector.getMuleContext());
201         fileParserMessasge.setOutboundProperty(FileConnector.PROPERTY_ORIGINAL_FILENAME,
202             originalName);
203 
204         return fileConnector.getFilenameParser().getFilename(fileParserMessasge, pattern);
205     }
206 
207     private void moveOrDelete(final File sourceFile, File destinationFile) throws DefaultMuleException
208     {
209 
210         if (destinationFile != null)
211         {
212             // move sourceFile to new destination
213             try
214             {
215                 FileUtils.moveFile(sourceFile, destinationFile);
216             }
217             catch (IOException e)
218             {
219                 throw new DefaultMuleException(FileMessages.failedToMoveFile(sourceFile.getAbsolutePath(),
220                     destinationFile.getAbsolutePath()));
221             }
222         }
223         if (fileConnector.isAutoDelete())
224         {
225             // no moveTo directory
226             if (destinationFile == null)
227             {
228                 // delete source
229                 if (!sourceFile.delete())
230                 {
231                     throw new DefaultMuleException(FileMessages.failedToDeleteFile(sourceFile));
232                 }
233             }
234             else
235             {
236                 // nothing to do here since moveFile() should have deleted
237                 // the source file for us
238             }
239         }
240     }
241 
242     @Override
243     protected void doDispose()
244     {
245         // no op
246     }
247 
248     @Override
249     protected void doConnect() throws Exception
250     {
251         // no op
252     }
253 
254     @Override
255     protected void doDisconnect() throws Exception
256     {
257         // no op
258     }
259 
260     protected String getMoveDirectory()
261     {
262         String moveDirectory = (String) endpoint.getProperty(FileConnector.PROPERTY_MOVE_TO_DIRECTORY);
263         if (moveDirectory == null)
264         {
265             moveDirectory = fileConnector.getMoveToDirectory();
266         }
267         return moveDirectory;
268     }
269 
270     protected String getMoveToPattern()
271     {
272         String pattern = (String) endpoint.getProperty(FileConnector.PROPERTY_MOVE_TO_PATTERN);
273         if (pattern == null)
274         {
275             pattern = fileConnector.getMoveToPattern();
276         }
277         return pattern;
278     }
279 }