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 */
017package org.apache.camel.component.file.strategy;
018
019import java.io.File;
020import java.io.IOException;
021
022import org.apache.camel.Exchange;
023import org.apache.camel.component.file.GenericFile;
024import org.apache.camel.component.file.GenericFileEndpoint;
025import org.apache.camel.component.file.GenericFileExclusiveReadLockStrategy;
026import org.apache.camel.component.file.GenericFileOperationFailedException;
027import org.apache.camel.component.file.GenericFileOperations;
028import org.apache.camel.component.file.GenericFileProcessStrategy;
029import org.apache.camel.util.FileUtil;
030import org.slf4j.Logger;
031import org.slf4j.LoggerFactory;
032
033/**
034 * Base class for implementations of {@link GenericFileProcessStrategy}.
035 */
036public abstract class GenericFileProcessStrategySupport<T> implements GenericFileProcessStrategy<T> {
037    protected final Logger log = LoggerFactory.getLogger(getClass());
038    protected GenericFileExclusiveReadLockStrategy<T> exclusiveReadLockStrategy;
039
040    public void prepareOnStartup(GenericFileOperations<T> operations, GenericFileEndpoint<T> endpoint) throws Exception {
041        if (exclusiveReadLockStrategy != null) {
042            exclusiveReadLockStrategy.prepareOnStartup(operations, endpoint);
043        }
044    }
045
046    public boolean begin(GenericFileOperations<T> operations, GenericFileEndpoint<T> endpoint, Exchange exchange, GenericFile<T> file) throws Exception {
047        // if we use exclusive read then acquire the exclusive read (waiting until we got it)
048        if (exclusiveReadLockStrategy != null) {
049            boolean lock = exclusiveReadLockStrategy.acquireExclusiveReadLock(operations, file, exchange);
050            if (!lock) {
051                // do not begin since we could not get the exclusive read lock
052                return false;
053            }
054        }
055
056        return true;
057    }
058
059    public void abort(GenericFileOperations<T> operations, GenericFileEndpoint<T> endpoint, Exchange exchange, GenericFile<T> file) throws Exception {
060        deleteLocalWorkFile(exchange);
061        operations.releaseRetreivedFileResources(exchange);
062
063        // must release lock last
064        if (exclusiveReadLockStrategy != null) {
065            exclusiveReadLockStrategy.releaseExclusiveReadLockOnAbort(operations, file, exchange);
066        }
067    }
068
069    public void commit(GenericFileOperations<T> operations, GenericFileEndpoint<T> endpoint, Exchange exchange, GenericFile<T> file) throws Exception {
070        deleteLocalWorkFile(exchange);
071        operations.releaseRetreivedFileResources(exchange);
072
073        // must release lock last
074        if (exclusiveReadLockStrategy != null) {
075            exclusiveReadLockStrategy.releaseExclusiveReadLockOnCommit(operations, file, exchange);
076        }
077    }
078
079    public void rollback(GenericFileOperations<T> operations, GenericFileEndpoint<T> endpoint, Exchange exchange, GenericFile<T> file) throws Exception {
080        deleteLocalWorkFile(exchange);
081        operations.releaseRetreivedFileResources(exchange);
082
083        // must release lock last
084        if (exclusiveReadLockStrategy != null) {
085            exclusiveReadLockStrategy.releaseExclusiveReadLockOnRollback(operations, file, exchange);
086        }
087    }
088
089    public GenericFileExclusiveReadLockStrategy<T> getExclusiveReadLockStrategy() {
090        return exclusiveReadLockStrategy;
091    }
092
093    public void setExclusiveReadLockStrategy(GenericFileExclusiveReadLockStrategy<T> exclusiveReadLockStrategy) {
094        this.exclusiveReadLockStrategy = exclusiveReadLockStrategy;
095    }
096    
097    protected GenericFile<T> renameFile(GenericFileOperations<T> operations, GenericFile<T> from, GenericFile<T> to) throws IOException {
098        // deleting any existing files before renaming
099        try {
100            operations.deleteFile(to.getAbsoluteFilePath());
101        } catch (GenericFileOperationFailedException e) {
102            // ignore the file does not exists
103        }
104        
105        // make parent folder if missing
106        boolean mkdir = operations.buildDirectory(to.getParent(), to.isAbsolute());
107        
108        if (!mkdir) {
109            throw new GenericFileOperationFailedException("Cannot create directory: " + to.getParent() + " (could be because of denied permissions)");
110        }
111
112        log.debug("Renaming file: {} to: {}", from, to);
113        boolean renamed = operations.renameFile(from.getAbsoluteFilePath(), to.getAbsoluteFilePath());
114        if (!renamed) {
115            throw new GenericFileOperationFailedException("Cannot rename file: " + from + " to: " + to);
116        }
117
118        return to;
119    }
120
121    protected void deleteLocalWorkFile(Exchange exchange) {
122        // delete local work file, if it was used (eg by ftp component)
123        File local = exchange.getIn().getHeader(Exchange.FILE_LOCAL_WORK_PATH, File.class);
124        if (local != null && local.exists()) {
125            boolean deleted = FileUtil.deleteFile(local);
126            log.trace("Local work file: {} was deleted: {}", local, deleted);
127        }
128    }
129}
130