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 com.jcraft.jsch.ChannelSftp;
022    import org.apache.camel.Processor;
023    import org.apache.camel.component.file.GenericFile;
024    import org.apache.camel.util.FileUtil;
025    import org.apache.camel.util.ObjectHelper;
026    
027    /**
028     * Secure FTP consumer
029     */
030    public class SftpConsumer extends RemoteFileConsumer<ChannelSftp.LsEntry> {
031    
032        private String endpointPath;
033    
034        public SftpConsumer(RemoteFileEndpoint<ChannelSftp.LsEntry> endpoint, Processor processor, RemoteFileOperations<ChannelSftp.LsEntry> operations) {
035            super(endpoint, processor, operations);
036            this.endpointPath = endpoint.getConfiguration().getDirectory();
037        }
038    
039        protected void pollDirectory(String fileName, List<GenericFile<ChannelSftp.LsEntry>> fileList) {
040            if (fileName == null) {
041                return;
042            }
043    
044            // remove trailing /
045            fileName = FileUtil.stripTrailingSeparator(fileName);
046    
047            if (log.isTraceEnabled()) {
048                log.trace("Polling directory: " + fileName);
049            }
050            List<ChannelSftp.LsEntry> files = operations.listFiles(fileName);
051            for (ChannelSftp.LsEntry file : files) {
052                if (file.getAttrs().isDir()) {
053                    RemoteFile<ChannelSftp.LsEntry> remote = asRemoteFile(fileName, file);
054                    if (endpoint.isRecursive() && isValidFile(remote, true)) {
055                        // recursive scan and add the sub files and folders
056                        String directory = fileName + "/" + file.getFilename();
057                        pollDirectory(directory, fileList);
058                    }
059                    // we cannot use file.getAttrs().isLink on Windows, so we dont invoke the method
060                    // just assuming its a file we should poll
061                } else {
062                    RemoteFile<ChannelSftp.LsEntry> remote = asRemoteFile(fileName, file);
063                    if (isValidFile(remote, false)) {
064                        if (isInProgress(remote)) {
065                            if (log.isTraceEnabled()) {
066                                log.trace("Skipping as file is already in progress: " + remote.getFileName());
067                            }
068                        } else {
069                            // matched file so add
070                            fileList.add(remote);
071                        }
072                    }
073                }
074            }
075        }
076    
077        private RemoteFile<ChannelSftp.LsEntry> asRemoteFile(String directory, ChannelSftp.LsEntry file) {
078            RemoteFile<ChannelSftp.LsEntry> answer = new RemoteFile<ChannelSftp.LsEntry>();
079    
080            answer.setEndpointPath(endpointPath);
081            answer.setFile(file);
082            answer.setFileName(file.getFilename());
083            answer.setFileNameOnly(file.getFilename());
084            answer.setFileLength(file.getAttrs().getSize());
085            answer.setLastModified(file.getAttrs().getMTime() * 1000L);
086            answer.setHostname(((RemoteFileConfiguration) endpoint.getConfiguration()).getHost());
087    
088            // all ftp files is considered as relative
089            answer.setAbsolute(false);
090    
091            // create a pseudo absolute name
092            String absoluteFileName = (ObjectHelper.isNotEmpty(directory) ? directory + "/" : "") + file.getFilename();
093            answer.setAbsoluteFilePath(absoluteFileName);
094    
095            // the relative filename, skip the leading endpoint configured path
096            String relativePath = ObjectHelper.after(absoluteFileName, endpointPath);
097            // skip trailing /
098            relativePath = FileUtil.stripLeadingSeparator(relativePath);
099            answer.setRelativeFilePath(relativePath);
100    
101            return answer;
102        }
103    
104    }