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