001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.component.file.remote;
018    
019    import java.util.List;
020    
021    import org.apache.camel.Processor;
022    import org.apache.camel.component.file.GenericFile;
023    import org.apache.camel.util.FileUtil;
024    import org.apache.camel.util.ObjectHelper;
025    import org.apache.commons.net.ftp.FTPFile;
026    
027    /**
028     * FTP consumer
029     */
030    public class FtpConsumer extends RemoteFileConsumer<FTPFile> {
031    
032        protected String endpointPath;
033    
034        public FtpConsumer(RemoteFileEndpoint<FTPFile> endpoint, Processor processor, RemoteFileOperations<FTPFile> fileOperations) {
035            super(endpoint, processor, fileOperations);
036            this.endpointPath = endpoint.getConfiguration().getDirectory();
037        }
038    
039        protected boolean pollDirectory(String fileName, List<GenericFile<FTPFile>> fileList) {
040            if (log.isTraceEnabled()) {
041                log.trace("pollDirectory from fileName: " + fileName);
042            }
043            if (fileName == null) {
044                return true;
045            }
046    
047            // remove trailing /
048            fileName = FileUtil.stripTrailingSeparator(fileName);
049    
050            if (log.isTraceEnabled()) {
051                log.trace("Polling directory: " + fileName);
052            }
053            List<FTPFile> files = operations.listFiles(fileName);
054            if (files == null || files.isEmpty()) {
055                // no files in this directory to poll
056                if (log.isTraceEnabled()) {
057                    log.trace("No files found in directory: " + fileName);
058                }
059                return true;
060            } else {
061                // we found some files
062                if (log.isTraceEnabled()) {
063                    log.trace("Found " + files.size() + " in directory: " + fileName);
064                }
065            }
066    
067            for (FTPFile file : files) {
068    
069                // check if we can continue polling in files
070                if (!canPollMoreFiles(fileList)) {
071                    return false;
072                }
073    
074                if (file.isDirectory()) {
075                    RemoteFile<FTPFile> remote = asRemoteFile(fileName, file);
076                    if (endpoint.isRecursive() && isValidFile(remote, true)) {
077                        // recursive scan and add the sub files and folders
078                        String subDirectory = fileName + "/" + file.getName();
079                        boolean canPollMore = pollDirectory(subDirectory, fileList);
080                        if (!canPollMore) {
081                            return false;
082                        }
083                    }
084                } else if (file.isFile()) {
085                    RemoteFile<FTPFile> remote = asRemoteFile(fileName, file);
086                    if (isValidFile(remote, false)) {
087                        if (isInProgress(remote)) {
088                            if (log.isTraceEnabled()) {
089                                log.trace("Skipping as file is already in progress: " + remote.getFileName());
090                            }
091                        } else {
092                            // matched file so add
093                            fileList.add(remote);
094                        }
095                    }
096                } else {
097                    log.debug("Ignoring unsupported remote file type: " + file);
098                }
099            }
100    
101            return true;
102        }
103    
104        private RemoteFile<FTPFile> asRemoteFile(String directory, FTPFile file) {
105            RemoteFile<FTPFile> answer = new RemoteFile<FTPFile>();
106    
107            answer.setEndpointPath(endpointPath);
108            answer.setFile(file);
109            answer.setFileName(file.getName());
110            answer.setFileNameOnly(file.getName());
111            answer.setFileLength(file.getSize());
112            if (file.getTimestamp() != null) {
113                answer.setLastModified(file.getTimestamp().getTimeInMillis());
114            }
115            answer.setHostname(((RemoteFileConfiguration) endpoint.getConfiguration()).getHost());
116    
117            // all ftp files is considered as relative
118            answer.setAbsolute(false);
119    
120            // create a pseudo absolute name
121            String absoluteFileName = (ObjectHelper.isNotEmpty(directory) ? directory + "/" : "") + file.getName();
122            answer.setAbsoluteFilePath(absoluteFileName);
123    
124            // the relative filename, skip the leading endpoint configured path
125            String relativePath = ObjectHelper.after(absoluteFileName, endpointPath);
126            // skip leading /
127            relativePath = FileUtil.stripLeadingSeparator(relativePath);
128            answer.setRelativeFilePath(relativePath);
129    
130            return answer;
131        }
132    
133    }