View Javadoc

1   /*
2    * $Id: FileMessageRequester.java 11433 2008-03-20 03:43:57Z dirk.olmes $
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.file;
12  
13  import org.mule.DefaultMuleMessage;
14  import org.mule.MuleServer;
15  import org.mule.api.DefaultMuleException;
16  import org.mule.api.MuleException;
17  import org.mule.api.MuleMessage;
18  import org.mule.api.endpoint.InboundEndpoint;
19  import org.mule.api.transport.MessageAdapter;
20  import org.mule.transport.AbstractMessageRequester;
21  import org.mule.transport.DefaultMessageAdapter;
22  import org.mule.transport.file.filters.FilenameWildcardFilter;
23  import org.mule.transport.file.i18n.FileMessages;
24  import org.mule.util.FileUtils;
25  
26  import java.io.File;
27  import java.io.FileNotFoundException;
28  import java.io.FilenameFilter;
29  import java.net.URLDecoder;
30  
31  /**
32   * <code>FileMessageDispatcher</code> is used to read/write files to the filesystem
33   */
34  public class FileMessageRequester extends AbstractMessageRequester
35  {
36      private final FileConnector connector;
37  
38      public FileMessageRequester(InboundEndpoint endpoint)
39      {
40          super(endpoint);
41          this.connector = (FileConnector) endpoint.getConnector();
42      }
43  
44      /**
45       * There is no associated session for a file connector
46       * 
47       * @throws org.mule.api.MuleException
48       */
49      public Object getDelegateSession() throws MuleException
50      {
51          return null;
52      }
53  
54      /**
55       * Will attempt to do a receive from a directory, if the endpointUri resolves to
56       * a file name the file will be returned, otherwise the first file in the
57       * directory according to the filename filter configured on the connector.
58       * 
59       * @param timeout this is ignored when doing a receive on this dispatcher
60       * @return a message containing file contents or null if there was notthing to
61       *         receive
62       * @throws Exception
63       */
64  
65      protected MuleMessage doRequest(long timeout) throws Exception
66      {
67          File file = FileUtils.newFile(endpoint.getEndpointURI().getAddress());
68          File result = null;
69          FilenameFilter filenameFilter = null;
70          String filter = (String) endpoint.getProperty("filter");
71          if (filter != null)
72          {
73              filter = URLDecoder.decode(filter, MuleServer.getMuleContext().getConfiguration().getDefaultEncoding());
74              filenameFilter = new FilenameWildcardFilter(filter);
75          }
76          if (file.exists())
77          {
78              if (file.isFile())
79              {
80                  result = file;
81              }
82              else if (file.isDirectory())
83              {
84                  result = FileMessageDispatcher.getNextFile(endpoint.getEndpointURI().getAddress(), filenameFilter);
85              }
86              if (result != null)
87              {
88                  boolean checkFileAge = connector.getCheckFileAge();
89                  if (checkFileAge)
90                  {
91                      long fileAge = connector.getFileAge();
92                      long lastMod = result.lastModified();
93                      long now = System.currentTimeMillis();
94                      long thisFileAge = now - lastMod;
95                      if (thisFileAge < fileAge)
96                      {
97                          if (logger.isDebugEnabled())
98                          {
99                              logger.debug("The file has not aged enough yet, will return nothing for: "
100                                          + result.getCanonicalPath());
101                         }
102                         return null;
103                     }
104                 }
105 
106                 // Don't we need to try to obtain a file lock as we do with receiver
107                 String sourceFileOriginalName = result.getName();
108 
109                 // This isn't nice but is needed as MessageAdaptor is required to
110                 // resolve
111                 // destination file name, and StreamingReceiverFileInputStream is
112                 // required to create MessageAdaptor
113                 DefaultMessageAdapter fileParserMsgAdaptor = new DefaultMessageAdapter(null);
114                 fileParserMsgAdaptor.setProperty(FileConnector.PROPERTY_ORIGINAL_FILENAME, sourceFileOriginalName);
115 
116                 // set up destination file
117                 File destinationFile = null;
118                 String movDir = connector.getMoveToDirectory();
119                 if (movDir != null)
120                 {
121                     String destinationFileName = sourceFileOriginalName;
122                     String moveToPattern = connector.getMoveToPattern();
123                     if (moveToPattern != null)
124                     {
125                         destinationFileName = connector.getFilenameParser().getFilename(
126                             fileParserMsgAdaptor, moveToPattern);
127                     }
128                     // don't use new File() directly, see MULE-1112
129                     destinationFile = FileUtils.newFile(movDir, destinationFileName);
130                 }
131 
132                 MessageAdapter msgAdapter = null;
133                 try
134                 {
135                     if (connector.isStreaming())
136                     {
137                         msgAdapter = connector.getMessageAdapter(new ReceiverFileInputStream(result, connector.isAutoDelete(),
138                             destinationFile));
139                     }
140                     else
141                     {
142                         msgAdapter = connector.getMessageAdapter(result);
143                     }
144                 }
145                 catch (FileNotFoundException e)
146                 {
147                     // we can ignore since we did manage to acquire a lock, but just
148                     // in case
149                     logger.error("File being read disappeared!", e);
150                     return null;
151                 }
152                 msgAdapter.setProperty(FileConnector.PROPERTY_ORIGINAL_FILENAME, sourceFileOriginalName);
153 
154                 if (!connector.isStreaming())
155                 {
156                     moveOrDelete(result, destinationFile);
157                     return new DefaultMuleMessage(msgAdapter);
158                 }
159                 else
160                 {
161                     // If we are streaming no need to move/delete now, that will be
162                     // done when stream is closed
163                     return new DefaultMuleMessage(msgAdapter);
164                 }
165             }
166         }
167         return null;
168     }
169 
170     private void moveOrDelete(final File sourceFile, File destinationFile) throws DefaultMuleException
171     {
172 
173         if (destinationFile != null)
174         {
175             // move sourceFile to new destination
176             if (!FileUtils.moveFile(sourceFile, destinationFile))
177             {
178                 throw new DefaultMuleException(FileMessages.failedToMoveFile(sourceFile.getAbsolutePath(),
179                     destinationFile.getAbsolutePath()));
180             }
181         }
182         if (connector.isAutoDelete())
183         {
184             // no moveTo directory
185             if (destinationFile == null)
186             {
187                 // delete source
188                 if (!sourceFile.delete())
189                 {
190                     throw new DefaultMuleException(FileMessages.failedToDeleteFile(sourceFile.getAbsolutePath()));
191                 }
192             }
193             else
194             {
195                 // nothing to do here since moveFile() should have deleted
196                 // the source file for us
197             }
198         }
199 
200     }
201 
202     protected void doDispose()
203     {
204         // no op
205     }
206 
207     protected void doConnect() throws Exception
208     {
209         // no op
210     }
211 
212     protected void doDisconnect() throws Exception
213     {
214         // no op
215     }
216 
217 }