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;
018
019 import java.io.File;
020 import java.util.List;
021
022 import org.apache.camel.Processor;
023 import org.apache.camel.util.FileUtil;
024 import org.apache.camel.util.ObjectHelper;
025
026 /**
027 * File consumer.
028 */
029 public class FileConsumer extends GenericFileConsumer<File> {
030
031 private String endpointPath;
032
033 public FileConsumer(GenericFileEndpoint<File> endpoint, Processor processor, GenericFileOperations<File> operations) {
034 super(endpoint, processor, operations);
035 this.endpointPath = endpoint.getConfiguration().getDirectory();
036 }
037
038 @Override
039 protected boolean pollDirectory(String fileName, List<GenericFile<File>> fileList, int depth) {
040 log.trace("pollDirectory from fileName: {}", fileName);
041
042 depth++;
043
044 File directory = new File(fileName);
045 if (!directory.exists() || !directory.isDirectory()) {
046 log.debug("Cannot poll as directory does not exists or its not a directory: {}", directory);
047 if (getEndpoint().isDirectoryMustExist()) {
048 throw new GenericFileOperationFailedException("Directory does not exist: " + directory);
049 }
050 return true;
051 }
052
053 log.trace("Polling directory: {}", directory.getPath());
054 File[] files = directory.listFiles();
055 if (files == null || files.length == 0) {
056 // no files in this directory to poll
057 if (log.isTraceEnabled()) {
058 log.trace("No files found in directory: {}", directory.getPath());
059 }
060 return true;
061 } else {
062 // we found some files
063 if (log.isTraceEnabled()) {
064 log.trace("Found {} in directory: {}", files.length, directory.getPath());
065 }
066 }
067
068 for (File file : files) {
069 // check if we can continue polling in files
070 if (!canPollMoreFiles(fileList)) {
071 return false;
072 }
073
074 // trace log as Windows/Unix can have different views what the file is?
075 if (log.isTraceEnabled()) {
076 log.trace("Found file: {} [isAbsolute: {}, isDirectory: {}, isFile: {}, isHidden: {}]",
077 new Object[]{file, file.isAbsolute(), file.isDirectory(), file.isFile(), file.isHidden()});
078 }
079
080 // creates a generic file
081 GenericFile<File> gf = asGenericFile(endpointPath, file, getEndpoint().getCharset());
082
083 if (file.isDirectory()) {
084 if (endpoint.isRecursive() && isValidFile(gf, true) && depth < endpoint.getMaxDepth()) {
085 // recursive scan and add the sub files and folders
086 String subDirectory = fileName + File.separator + file.getName();
087 boolean canPollMore = pollDirectory(subDirectory, fileList, depth);
088 if (!canPollMore) {
089 return false;
090 }
091 }
092 } else {
093 // Windows can report false to a file on a share so regard it always as a file (if its not a directory)
094 if (isValidFile(gf, false) && depth >= endpoint.minDepth) {
095 if (isInProgress(gf)) {
096 if (log.isTraceEnabled()) {
097 log.trace("Skipping as file is already in progress: {}", gf.getFileName());
098 }
099 } else {
100 log.trace("Adding valid file: {}", file);
101 // matched file so add
102 fileList.add(gf);
103 }
104 }
105
106 }
107 }
108
109 return true;
110 }
111
112 /**
113 * Creates a new GenericFile<File> based on the given file.
114 *
115 * @param endpointPath the starting directory the endpoint was configured with
116 * @param file the source file
117 * @return wrapped as a GenericFile
118 */
119 public static GenericFile<File> asGenericFile(String endpointPath, File file, String charset) {
120 GenericFile<File> answer = new GenericFile<File>();
121 // use file specific binding
122 answer.setBinding(new FileBinding());
123
124 answer.setCharset(charset);
125 answer.setEndpointPath(endpointPath);
126 answer.setFile(file);
127 answer.setFileNameOnly(file.getName());
128 answer.setFileLength(file.length());
129 answer.setDirectory(file.isDirectory());
130 // must use FileUtil.isAbsolute to have consistent check for whether the file is
131 // absolute or not. As windows do not consider \ paths as absolute where as all
132 // other OS platforms will consider \ as absolute. The logic in Camel mandates
133 // that we align this for all OS. That is why we must use FileUtil.isAbsolute
134 // to return a consistent answer for all OS platforms.
135 answer.setAbsolute(FileUtil.isAbsolute(file));
136 answer.setAbsoluteFilePath(file.getAbsolutePath());
137 answer.setLastModified(file.lastModified());
138
139 // compute the file path as relative to the starting directory
140 File path;
141 String endpointNormalized = FileUtil.normalizePath(endpointPath);
142 if (file.getPath().startsWith(endpointNormalized)) {
143 // skip duplicate endpoint path
144 path = new File(ObjectHelper.after(file.getPath(), endpointNormalized + File.separator));
145 } else {
146 path = new File(file.getPath());
147 }
148
149 if (path.getParent() != null) {
150 answer.setRelativeFilePath(path.getParent() + File.separator + file.getName());
151 } else {
152 answer.setRelativeFilePath(path.getName());
153 }
154
155 // the file name should be the relative path
156 answer.setFileName(answer.getRelativeFilePath());
157
158 // use file as body as we have converters if needed as stream
159 answer.setBody(file);
160 return answer;
161 }
162
163 @Override
164 public FileEndpoint getEndpoint() {
165 return (FileEndpoint) super.getEndpoint();
166 }
167 }