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 org.apache.camel.Exchange;
020    import org.apache.camel.component.file.GenericFile;
021    import org.apache.camel.component.file.GenericFileEndpoint;
022    import org.apache.camel.component.file.GenericFileOperationFailedException;
023    import org.apache.camel.component.file.GenericFileOperations;
024    
025    public class GenericFileDeleteProcessStrategy<T> extends GenericFileProcessStrategySupport<T> {
026    
027        private GenericFileRenamer<T> failureRenamer;
028        private GenericFileRenamer<T> beginRenamer;
029    
030        @Override
031        public boolean begin(GenericFileOperations<T> operations, GenericFileEndpoint<T> endpoint, Exchange exchange, GenericFile<T> file) throws Exception {
032    
033            // must invoke super
034            boolean result = super.begin(operations, endpoint, exchange, file);
035            if (!result) {
036                return false;
037            }
038    
039            // okay we got the file then execute the begin renamer
040            if (beginRenamer != null) {
041                GenericFile<T> newName = beginRenamer.renameFile(exchange, file);
042                GenericFile<T> to = renameFile(operations, file, newName);
043                if (to != null) {
044                    to.bindToExchange(exchange);
045                }
046            }
047    
048            return true;
049        }
050    
051        @Override
052        public void commit(GenericFileOperations<T> operations, GenericFileEndpoint<T> endpoint, Exchange exchange, GenericFile<T> file) throws Exception {
053    
054            // special for file lock strategy as we must release that lock first before we can delete the file
055            boolean releaseEager = exclusiveReadLockStrategy instanceof FileLockExclusiveReadLockStrategy;
056    
057            if (releaseEager) {
058                exclusiveReadLockStrategy.releaseExclusiveReadLock(operations, file, exchange);
059            }
060    
061            try {
062                deleteLocalWorkFile(exchange);
063                operations.releaseRetreivedFileResources(exchange);
064    
065                int retries = 3;
066                boolean deleted = false;
067    
068                while (retries > 0 && !deleted) {
069                    retries--;
070    
071                    if (operations.deleteFile(file.getAbsoluteFilePath())) {
072                        // file is deleted
073                        deleted = true;
074                        break;
075                    }
076    
077                    // some OS can report false when deleting but the file is still deleted
078                    // use exists to check instead
079                    boolean exits = operations.existsFile(file.getAbsoluteFilePath());
080                    if (!exits) {
081                        deleted = true;
082                    } else {
083                        log.trace("File was not deleted at this attempt will try again in 1 sec.: {}", file);
084                        // sleep a bit and try again
085                        Thread.sleep(1000);
086                    }
087                }
088                if (!deleted) {
089                    throw new GenericFileOperationFailedException("Cannot delete file: " + file);
090                }
091            } finally {
092                // must release lock last
093                if (!releaseEager && exclusiveReadLockStrategy != null) {
094                    exclusiveReadLockStrategy.releaseExclusiveReadLock(operations, file, exchange);
095                }
096            }
097        }
098    
099        @Override
100        public void rollback(GenericFileOperations<T> operations, GenericFileEndpoint<T> endpoint, Exchange exchange, GenericFile<T> file) throws Exception {
101            try {
102                deleteLocalWorkFile(exchange);
103                operations.releaseRetreivedFileResources(exchange);
104    
105                // moved the failed file if specifying the moveFailed option
106                if (failureRenamer != null) {
107                    // create a copy and bind the file to the exchange to be used by the renamer to evaluate the file name
108                    Exchange copy = exchange.copy();
109                    file.bindToExchange(copy);
110                    // must preserve message id
111                    copy.getIn().setMessageId(exchange.getIn().getMessageId());
112                    copy.setExchangeId(exchange.getExchangeId());
113    
114                    GenericFile<T> newName = failureRenamer.renameFile(copy, file);
115                    renameFile(operations, file, newName);
116                }
117            } finally {
118                // must release lock last
119                if (exclusiveReadLockStrategy != null) {
120                    exclusiveReadLockStrategy.releaseExclusiveReadLock(operations, file, exchange);
121                }
122            }
123        }
124    
125        public GenericFileRenamer<T> getFailureRenamer() {
126            return failureRenamer;
127        }
128    
129        public void setFailureRenamer(GenericFileRenamer<T> failureRenamer) {
130            this.failureRenamer = failureRenamer;
131        }
132    
133        public GenericFileRenamer<T> getBeginRenamer() {
134            return beginRenamer;
135        }
136    
137        public void setBeginRenamer(GenericFileRenamer<T> beginRenamer) {
138            this.beginRenamer = beginRenamer;
139        }
140    }