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
021 import org.apache.camel.Consumer;
022 import org.apache.camel.ExchangePattern;
023 import org.apache.camel.Message;
024 import org.apache.camel.Processor;
025 import org.apache.camel.Producer;
026 import org.apache.camel.component.file.strategy.FileProcessStrategyFactory;
027 import org.apache.camel.component.file.strategy.FileProcessStrategySupport;
028 import org.apache.camel.component.file.strategy.NoOpFileProcessStrategy;
029 import org.apache.camel.impl.ScheduledPollEndpoint;
030 import org.apache.commons.logging.Log;
031 import org.apache.commons.logging.LogFactory;
032
033 /**
034 * A <a href="http://activemq.apache.org/camel/file.html">File Endpoint</a> for
035 * working with file systems
036 *
037 * @version $Revision: 41278 $
038 */
039 public class FileEndpoint extends ScheduledPollEndpoint<FileExchange> {
040 private static final transient Log LOG = LogFactory.getLog(FileEndpoint.class);
041 private File file;
042 private FileProcessStrategy fileProcessStrategy;
043 private boolean autoCreate = true;
044 private boolean lock = true;
045 private boolean delete;
046 private boolean noop;
047 private boolean append = true;
048 private String moveNamePrefix;
049 private String moveNamePostfix;
050 private String[] excludedNamePrefixes = {"."};
051 private String[] excludedNamePostfixes = {FileProcessStrategySupport.DEFAULT_LOCK_FILE_POSTFIX};
052 private int bufferSize = 128 * 1024;
053 private boolean ignoreFileNameHeader;
054
055 protected FileEndpoint(File file, String endpointUri, FileComponent component) {
056 super(endpointUri, component);
057 this.file = file;
058 }
059
060 public FileEndpoint(String endpointUri, File file) {
061 super(endpointUri);
062 this.file = file;
063 }
064
065 public Producer<FileExchange> createProducer() throws Exception {
066 Producer<FileExchange> result = new FileProducer(this);
067 return result;
068 }
069
070 public Consumer<FileExchange> createConsumer(Processor processor) throws Exception {
071 Consumer<FileExchange> result = new FileConsumer(this, processor);
072 configureConsumer(result);
073 return result;
074 }
075
076 /**
077 * Create a new exchange for communicating with this endpoint
078 *
079 * @param file the file
080 * @return the created exchange
081 */
082 public FileExchange createExchange(File file) {
083 return new FileExchange(getCamelContext(), getExchangePattern(), file);
084 }
085
086 public FileExchange createExchange() {
087 return createExchange(getFile());
088 }
089
090 public FileExchange createExchange(ExchangePattern pattern) {
091 return new FileExchange(getCamelContext(), pattern, file);
092 }
093
094 /**
095 * Configures the given message with the file which sets the body to the file object
096 * and sets the {@link FileComponent#HEADER_FILE_NAME} header.
097 */
098 public void configureMessage(File file, Message message) {
099 message.setBody(file);
100 String relativePath = file.getPath().substring(getFile().getPath().length());
101 if (relativePath.startsWith(File.separator) || relativePath.startsWith("/")) {
102 relativePath = relativePath.substring(1);
103 }
104 message.setHeader(FileComponent.HEADER_FILE_NAME, relativePath);
105 }
106
107 public File getFile() {
108 if (autoCreate && !file.exists()) {
109 file.mkdirs();
110 }
111 return file;
112 }
113
114 public boolean isSingleton() {
115 return true;
116 }
117
118 public boolean isAutoCreate() {
119 return this.autoCreate;
120 }
121
122 public void setAutoCreate(boolean autoCreate) {
123 this.autoCreate = autoCreate;
124 }
125
126 public FileProcessStrategy getFileStrategy() {
127 if (fileProcessStrategy == null) {
128 fileProcessStrategy = createFileStrategy();
129 LOG.debug("Using file process strategy: " + fileProcessStrategy);
130 }
131 return fileProcessStrategy;
132 }
133
134 /**
135 * Sets the strategy to be used when the file has been processed such as
136 * deleting or renaming it etc.
137 *
138 * @param fileProcessStrategy the new strategy to use
139 */
140 public void setFileStrategy(FileProcessStrategy fileProcessStrategy) {
141 this.fileProcessStrategy = fileProcessStrategy;
142 }
143
144 public boolean isDelete() {
145 return delete;
146 }
147
148 public void setDelete(boolean delete) {
149 this.delete = delete;
150 }
151
152 public boolean isLock() {
153 return lock;
154 }
155
156 public void setLock(boolean lock) {
157 this.lock = lock;
158 }
159
160 public String getMoveNamePostfix() {
161 return moveNamePostfix;
162 }
163
164 /**
165 * Sets the name postfix appended to moved files. For example to rename all
166 * the files from <tt>*</tt> to <tt>*.done</tt> set this value to <tt>.done</tt>
167 */
168 public void setMoveNamePostfix(String moveNamePostfix) {
169 this.moveNamePostfix = moveNamePostfix;
170 }
171
172 public String getMoveNamePrefix() {
173 return moveNamePrefix;
174 }
175
176 /**
177 * Sets the name prefix appended to moved files. For example to move
178 * processed files into a hidden directory called <tt>.camel</tt> set this value to
179 * <tt>.camel/</tt>
180 */
181 public void setMoveNamePrefix(String moveNamePrefix) {
182 this.moveNamePrefix = moveNamePrefix;
183 }
184
185 public String[] getExcludedNamePrefixes() {
186 return excludedNamePrefixes;
187 }
188
189 /**
190 * Sets the excluded file name prefixes, such as <tt>"."</tt> for hidden files which
191 * are excluded by default
192 */
193 public void setExcludedNamePrefixes(String[] excludedNamePrefixes) {
194 this.excludedNamePrefixes = excludedNamePrefixes;
195 }
196
197 public String[] getExcludedNamePostfixes() {
198 return excludedNamePostfixes;
199 }
200
201 /**
202 * Sets the excluded file name postfixes, such as {@link FileProcessStrategySupport#DEFAULT_LOCK_FILE_POSTFIX}
203 * to ignore lock files by default.
204 */
205 public void setExcludedNamePostfixes(String[] excludedNamePostfixes) {
206 this.excludedNamePostfixes = excludedNamePostfixes;
207 }
208
209 public boolean isNoop() {
210 return noop;
211 }
212
213 /**
214 * If set to true then the default {@link FileProcessStrategy} will be to use the
215 * {@link NoOpFileProcessStrategy} to not move or copy processed files
216 */
217 public void setNoop(boolean noop) {
218 this.noop = noop;
219 }
220
221 public boolean isAppend() {
222 return append;
223 }
224
225 /**
226 * When writing do we append to the end of the file, or replace it?
227 * The default is to append
228 */
229 public void setAppend(boolean append) {
230 this.append = append;
231 }
232
233 public int getBufferSize() {
234 return bufferSize;
235 }
236
237 /**
238 * Sets the buffer size used to read/write files
239 */
240 public void setBufferSize(int bufferSize) {
241 this.bufferSize = bufferSize;
242 }
243
244 public boolean isIgnoreFileNameHeader() {
245 return ignoreFileNameHeader;
246 }
247
248 /**
249 * If this flag is enabled then producers will ignore the {@link FileComponent#HEADER_FILE_NAME}
250 * header and generate a new dynamic file
251 */
252 public void setIgnoreFileNameHeader(boolean ignoreFileNameHeader) {
253 this.ignoreFileNameHeader = ignoreFileNameHeader;
254 }
255
256 /**
257 * A strategy method to lazily create the file strategy
258 */
259 protected FileProcessStrategy createFileStrategy() {
260 return FileProcessStrategyFactory.createFileProcessStrategy(isNoop(), isDelete(), isLock(), moveNamePrefix, moveNamePostfix);
261 }
262
263 }