Coverage Report - org.mule.transport.ftp.FtpMessageReceiver
 
Classes in this File Line Coverage Branch Coverage Complexity
FtpMessageReceiver
91%
52/57
56%
18/32
2.818
FtpMessageReceiver$1
N/A
N/A
2.818
FtpMessageReceiver$FtpWork
79%
11/14
N/A
2.818
 
 1  
 /*
 2  
  * $Id: FtpMessageReceiver.java 12377 2008-07-17 15:59:53Z tcarlson $
 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.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  
     // there's nothing like homegrown pseudo-2PC.. :/
 44  
     // shared state management like this should go into the connector and use
 45  
     // something like commons-tx
 46  10
     protected final Set scheduledFiles = Collections.synchronizedSet(new HashSet());
 47  10
     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  10
         super(connector, service, endpoint);
 55  
 
 56  10
         this.setFrequency(frequency);
 57  
 
 58  10
         this.connector = (FtpConnector) connector;
 59  
 
 60  10
         if (endpoint.getFilter() instanceof FilenameFilter)
 61  
         {
 62  0
             this.filenameFilter = (FilenameFilter) endpoint.getFilter();
 63  
         }
 64  
         else
 65  
         {
 66  10
             this.filenameFilter = null;
 67  
         }
 68  10
     }
 69  
 
 70  
     public void poll() throws Exception
 71  
     {
 72  10
         FTPFile[] files = listFiles();
 73  
 
 74  6
         synchronized (scheduledFiles)
 75  
         {
 76  12
             for (int i = 0; i < files.length; i++)
 77  
             {
 78  6
                 final FTPFile file = files[i];
 79  6
                 final String fileName = file.getName();
 80  
 
 81  6
                 if (!scheduledFiles.contains(fileName) && !currentFiles.contains(fileName))
 82  
                 {
 83  6
                     scheduledFiles.add(fileName);
 84  6
                     getWorkManager().scheduleWork(new FtpWork(fileName, file));
 85  
                 }
 86  
             }
 87  6
         }
 88  6
     }
 89  
 
 90  
     protected FTPFile[] listFiles() throws Exception
 91  
     {
 92  10
         FTPClient client = null;
 93  
         try
 94  
         {
 95  10
             client = connector.createFtpClient(endpoint);
 96  6
             FTPFile[] files = client.listFiles();
 97  
 
 98  6
             if (!FTPReply.isPositiveCompletion(client.getReplyCode()))
 99  
             {
 100  0
                 throw new IOException("Failed to list files. Ftp error: " + client.getReplyCode());
 101  
             }
 102  
 
 103  6
             if (files == null || files.length == 0)
 104  
             {
 105  0
                 return files;
 106  
             }
 107  
 
 108  6
             List v = new ArrayList();
 109  
 
 110  12
             for (int i = 0; i < files.length; i++)
 111  
             {
 112  6
                 if (files[i].isFile())
 113  
                 {
 114  6
                     if (filenameFilter == null || filenameFilter.accept(null, files[i].getName()))
 115  
                     {
 116  6
                         v.add(files[i]);
 117  
                     }
 118  
                 }
 119  
             }
 120  
 
 121  6
             return (FTPFile[]) v.toArray(new FTPFile[v.size()]);
 122  
         }
 123  
         finally
 124  
         {
 125  10
             if (client != null)
 126  
             {
 127  6
                 connector.releaseFtp(endpoint.getEndpointURI(), client);
 128  
             }
 129  
         }
 130  
     }
 131  
 
 132  
     protected void processFile(FTPFile file) throws Exception
 133  
     {
 134  6
         logger.debug("entering processFile()");
 135  
 
 136  6
         FTPClient client = null;
 137  
         try
 138  
         {
 139  6
             if (!connector.validateFile(file))
 140  
             {
 141  
                 return;
 142  
             }
 143  
             
 144  6
             client = connector.createFtpClient(endpoint);
 145  
 
 146  
             MuleMessage message;
 147  6
             InputStream stream = client.retrieveFileStream(file.getName());
 148  6
             if (stream == null)
 149  
             {
 150  0
                 throw new IOException(MessageFormat.format("Failed to retrieve file {0}. Ftp error: {1}",
 151  
                         new Object[]{file.getName(), new Integer(client.getReplyCode())}));
 152  
             }
 153  6
             message = new DefaultMuleMessage(connector.getMessageAdapter(stream));
 154  
             
 155  
 
 156  6
             message.setProperty(FileConnector.PROPERTY_ORIGINAL_FILENAME, file.getName());
 157  6
             message.setProperty(FileConnector.PROPERTY_FILE_SIZE, new Long(file.getSize()));
 158  6
             routeMessage(message);
 159  
 
 160  6
             postProcess(client, file, message);
 161  
         }
 162  
         finally
 163  
         {
 164  6
             logger.debug("leaving processFile()");
 165  6
             if (client != null)
 166  
             {
 167  6
                 connector.releaseFtp(endpoint.getEndpointURI(), client);
 168  
             }
 169  
         }
 170  6
     }
 171  
 
 172  
     protected void postProcess(FTPClient client, FTPFile file, MuleMessage message) throws Exception
 173  
     {
 174  6
         if (!client.deleteFile(file.getName()))
 175  
         {
 176  0
             throw new IOException(MessageFormat.format("Failed to delete file {0}. Ftp error: {1}",
 177  
                     new Object[]{file.getName(), new Integer(client.getReplyCode())}));
 178  
         }
 179  6
         logger.debug("Deleted processed file " + file.getName());
 180  6
     }
 181  
     
 182  
     protected void doConnect() throws Exception
 183  
     {
 184  
         // why?!
 185  
         //connector.releaseFtp(getEndpointURI());
 186  4
     }
 187  
 
 188  
     protected void doDisconnect() throws Exception
 189  
     {
 190  
         // no op
 191  4
     }
 192  
 
 193  
     protected void doDispose()
 194  
     {
 195  
         // template method
 196  12
     }
 197  
 
 198  6
     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  6
         {
 205  6
             this.name = name;
 206  6
             this.file = file;
 207  6
         }
 208  
 
 209  
         public void run()
 210  
         {
 211  
             try
 212  
             {
 213  6
                 currentFiles.add(name);
 214  6
                 processFile(file);
 215  
             }
 216  0
             catch (Exception e)
 217  
             {
 218  0
                 connector.handleException(e);
 219  
             }
 220  
             finally
 221  
             {
 222  6
                 currentFiles.remove(name);
 223  6
                 scheduledFiles.remove(name);
 224  6
             }
 225  6
         }
 226  
 
 227  
         public void release()
 228  
         {
 229  
             // no op
 230  0
         }
 231  
     }
 232  
 
 233  
 }