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.strategy;
018    
019    import java.io.File;
020    
021    import org.apache.camel.Exchange;
022    import org.apache.camel.component.file.FileComponent;
023    import org.apache.camel.component.file.GenericFile;
024    import org.apache.camel.component.file.GenericFileEndpoint;
025    import org.apache.camel.component.file.GenericFileExclusiveReadLockStrategy;
026    import org.apache.camel.component.file.GenericFileOperations;
027    import org.apache.camel.util.ExchangeHelper;
028    import org.apache.camel.util.FileUtil;
029    import org.apache.commons.logging.Log;
030    import org.apache.commons.logging.LogFactory;
031    
032    /**
033     * Acquires read lock to the given file using a marker file so other Camel consumers wont acquire the same file.
034     * This is the default behavior in Camel 1.x.
035     */
036    public class MarkerFileExclusiveReadLockStrategy implements GenericFileExclusiveReadLockStrategy<File> {
037        private static final transient Log LOG = LogFactory.getLog(MarkerFileExclusiveReadLockStrategy.class);
038    
039        public void prepareOnStartup(GenericFileOperations<File> operations, GenericFileEndpoint<File> endpoint) {
040            String dir = endpoint.getConfiguration().getDirectory();
041            File file = new File(dir);
042    
043            if (LOG.isDebugEnabled()) {
044                LOG.debug("Prepare on startup by deleting orphaned lock files from: " + dir);
045            }
046    
047            deleteLockFiles(file, endpoint.isRecursive());
048        }
049    
050        @SuppressWarnings("unchecked")
051        public boolean acquireExclusiveReadLock(GenericFileOperations<File> operations,
052                                                GenericFile<File> file, Exchange exchange) throws Exception {
053    
054            String lockFileName = file.getAbsoluteFilePath() + FileComponent.DEFAULT_LOCK_FILE_POSTFIX;
055            if (LOG.isTraceEnabled()) {
056                LOG.trace("Locking the file: " + file + " using the lock file name: " + lockFileName);
057            }
058    
059            // create a plain file as marker filer for locking (do not use FileLock)
060            File lock = new File(lockFileName);
061            boolean acquired = lock.createNewFile();
062            if (acquired) {
063                exchange.setProperty("CamelFileLock", lock);
064                exchange.setProperty("CamelFileLockName", lockFileName);
065            }
066    
067            return acquired;
068        }
069    
070        public void releaseExclusiveReadLock(GenericFileOperations<File> operations,
071                                             GenericFile<File> file, Exchange exchange) throws Exception {
072    
073            File lock = ExchangeHelper.getMandatoryProperty(exchange, "CamelFileLock", File.class);
074            String lockFileName = ExchangeHelper.getMandatoryProperty(exchange, "CamelFileLockName", String.class);
075    
076            if (LOG.isTraceEnabled()) {
077                LOG.trace("Unlocking file: " + lockFileName);
078            }
079    
080            boolean deleted = FileUtil.deleteFile(lock);
081            if (LOG.isTraceEnabled()) {
082                LOG.trace("Lock file: " + lockFileName + " was deleted: " + deleted);
083            }
084        }
085    
086        public void setTimeout(long timeout) {
087            // noop
088        }
089    
090        private static void deleteLockFiles(File dir, boolean recursive) {
091            File[] files = dir.listFiles();
092            if (files == null || files.length == 0) {
093                return;
094            }
095    
096            for (File file : files) {
097                if (file.getName().startsWith(".")) {
098                    // files starting with dot should be skipped
099                    continue;
100                } else if (file.getName().endsWith(FileComponent.DEFAULT_LOCK_FILE_POSTFIX)) {
101                    LOG.warn("Deleting orphaned lock file: " + file);
102                    FileUtil.deleteFile(file);
103                } else if (recursive && file.isDirectory()) {
104                    deleteLockFiles(file, true);
105                }
106            }
107        }
108    
109    }