Repository: camel Updated Branches: refs/heads/camel-2.14.x 638355862 -> 25d14cf78 refs/heads/master cb5237aba -> 3c53313d0
CAMEL-8266 Allows ignoring directories for SFTP/FTP having no read permission using ignoreFileNotFoundOrPermissionError Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/3c53313d Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/3c53313d Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/3c53313d Branch: refs/heads/master Commit: 3c53313d0fcb2fd31110cd47f3981ea98bf3081f Parents: cb5237a Author: Shreyas Purohit <shreyas.puro...@gmail.com> Authored: Sat Jan 24 20:31:14 2015 -0800 Committer: Shreyas Purohit <shreyas.puro...@gmail.com> Committed: Sat Jan 24 20:33:22 2015 -0800 ---------------------------------------------------------------------- .../component/file/remote/FtpConsumer.java | 20 +++- .../file/remote/RemoteFileConsumer.java | 50 +++++++- .../component/file/remote/SftpConsumer.java | 2 +- .../remote/RemoteFileIgnoreDoPollErrorTest.java | 118 +++++++++++++++++++ 4 files changed, 181 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/3c53313d/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpConsumer.java ---------------------------------------------------------------------- diff --git a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpConsumer.java b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpConsumer.java index fff8e93..ba5d32c 100644 --- a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpConsumer.java +++ b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpConsumer.java @@ -22,6 +22,7 @@ import java.util.List; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.component.file.GenericFile; +import org.apache.camel.component.file.GenericFileOperationFailedException; import org.apache.camel.util.FileUtil; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.URISupport; @@ -59,7 +60,7 @@ public class FtpConsumer extends RemoteFileConsumer<FTPFile> { } protected boolean pollSubDirectory(String absolutePath, String dirName, List<GenericFile<FTPFile>> fileList, int depth) { - boolean answer = doPollDirectory(absolutePath, dirName, fileList, depth); + boolean answer = doSafePollSubDirectory(absolutePath, dirName, fileList, depth); // change back to parent directory when finished polling sub directory if (isStepwise()) { operations.changeToParentDirectory(); @@ -167,10 +168,19 @@ public class FtpConsumer extends RemoteFileConsumer<FTPFile> { @Override protected boolean ignoreCannotRetrieveFile(String name, Exchange exchange, Exception cause) { if (getEndpoint().getConfiguration().isIgnoreFileNotFoundOrPermissionError()) { - // error code 550 is file not found - int code = exchange.getIn().getHeader(FtpConstants.FTP_REPLY_CODE, 0, int.class); - if (code == 550) { - return true; + if (exchange != null) { + // error code 550 is file not found + int code = exchange.getIn().getHeader(FtpConstants.FTP_REPLY_CODE, 0, int.class); + if (code == 550) { + return true; + } + } + if (cause != null && cause instanceof GenericFileOperationFailedException) { + GenericFileOperationFailedException generic = ObjectHelper.getException(GenericFileOperationFailedException.class, cause); + //exchange is null and cause has the reason for failure to read directories + if (generic.getCode() == 550) { + return true; + } } } return super.ignoreCannotRetrieveFile(name, exchange, cause); http://git-wip-us.apache.org/repos/asf/camel/blob/3c53313d/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConsumer.java ---------------------------------------------------------------------- diff --git a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConsumer.java b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConsumer.java index de242da..bb418e2 100644 --- a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConsumer.java +++ b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConsumer.java @@ -17,9 +17,11 @@ package org.apache.camel.component.file.remote; import java.io.IOException; +import java.util.List; import org.apache.camel.Exchange; import org.apache.camel.Processor; +import org.apache.camel.component.file.GenericFile; import org.apache.camel.component.file.GenericFileConsumer; import org.apache.camel.component.file.GenericFileOperationFailedException; @@ -70,13 +72,13 @@ public abstract class RemoteFileConsumer<T> extends GenericFileConsumer<T> { if (!loggedInWarning) { log.warn(message); loggedInWarning = true; - } + } return false; } else { // need to log the failed log again loggedInWarning = false; } - + return true; } @@ -98,7 +100,7 @@ public abstract class RemoteFileConsumer<T> extends GenericFileConsumer<T> { exchange.setProperty(Exchange.UNIT_OF_WORK_PROCESS_SYNC, Boolean.TRUE); return super.processExchange(exchange); } - + @Override protected boolean isRetrieveFile() { return getEndpoint().isDownload(); @@ -165,4 +167,46 @@ public abstract class RemoteFileConsumer<T> extends GenericFileConsumer<T> { return ((RemoteFileEndpoint<?>) endpoint).remoteServerInformation(); } + /** + * Executes doPollDirectory and on exception checks if it can be ignored by calling ignoreCannotRetrieveFile . + * + * @param absolutePath The path of the directory to poll + * @param dirName The name of the directory to poll + * @param fileList current list of files gathered + * @param depth the current depth of the directory + * @return whether or not to continue polling, <tt>false</tt> means the maxMessagesPerPoll limit has been hit + * @throws GenericFileOperationFailedException if the exception during doPollDirectory can not be ignored + */ + protected boolean doSafePollSubDirectory(String absolutePath, String dirName, List<GenericFile<T>> fileList, int depth) { + try { + log.trace("Polling sub directory: {} from: {}", absolutePath, endpoint); + //Try to poll the directory + return doPollDirectory(absolutePath, dirName, fileList, depth); + } catch (Exception e) { + log.debug("Caught exception " + e.getMessage()); + if (ignoreCannotRetrieveFile(absolutePath, null, e)) { + log.trace("Ignoring file error " + e.getMessage() + " for " + absolutePath); + //indicate no files in this directory to poll, continue with fileList + return true; + } else { + log.trace("Not ignoring file error " + e.getMessage() + " for " + absolutePath); + if (e instanceof GenericFileOperationFailedException) { + throw (GenericFileOperationFailedException) e; + } else { + throw new GenericFileOperationFailedException("Cannot poll sub-directory: " + absolutePath + " from: " + endpoint, e); + } + } + } + } + + /** + * Poll directory given by dirName or absolutePath + * + * @param absolutePath The path of the directory to poll + * @param dirName The name of the directory to poll + * @param fileList current list of files gathered + * @param depth the current depth of the directory + * @return whether or not to continue polling, <tt>false</tt> means the maxMessagesPerPoll limit has been hit + */ + protected abstract boolean doPollDirectory(String absolutePath, String dirName, List<GenericFile<T>> fileList, int depth); } http://git-wip-us.apache.org/repos/asf/camel/blob/3c53313d/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpConsumer.java ---------------------------------------------------------------------- diff --git a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpConsumer.java b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpConsumer.java index 0d0906b..0f2f536 100644 --- a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpConsumer.java +++ b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpConsumer.java @@ -58,7 +58,7 @@ public class SftpConsumer extends RemoteFileConsumer<ChannelSftp.LsEntry> { } protected boolean pollSubDirectory(String absolutePath, String dirName, List<GenericFile<ChannelSftp.LsEntry>> fileList, int depth) { - boolean answer = doPollDirectory(absolutePath, dirName, fileList, depth); + boolean answer = doSafePollSubDirectory(absolutePath, dirName, fileList, depth); // change back to parent directory when finished polling sub directory if (isStepwise()) { operations.changeToParentDirectory(); http://git-wip-us.apache.org/repos/asf/camel/blob/3c53313d/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/RemoteFileIgnoreDoPollErrorTest.java ---------------------------------------------------------------------- diff --git a/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/RemoteFileIgnoreDoPollErrorTest.java b/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/RemoteFileIgnoreDoPollErrorTest.java new file mode 100644 index 0000000..3ca70b6 --- /dev/null +++ b/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/RemoteFileIgnoreDoPollErrorTest.java @@ -0,0 +1,118 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.file.remote; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.component.file.GenericFile; +import org.apache.camel.component.file.GenericFileOperationFailedException; +import org.apache.camel.component.file.GenericFileProducer; +import org.junit.Assert; +import org.junit.Test; + +public class RemoteFileIgnoreDoPollErrorTest { + private final RemoteFileEndpoint<Object> remoteFileEndpoint = new RemoteFileEndpoint<Object>() { + @Override + protected RemoteFileConsumer<Object> buildConsumer(Processor processor) { + return null; + } + + @Override + protected GenericFileProducer<Object> buildProducer() { + return null; + } + + @Override + public RemoteFileOperations<Object> createRemoteFileOperations() throws Exception { + return null; + } + + @Override + public String getScheme() { + return null; + } + }; + + @Test + public void testReadDirErrorIsHandled() throws Exception { + RemoteFileConsumer<Object> consumer = getRemoteFileConsumer("true", true); + boolean result = consumer.doSafePollSubDirectory("anyPath", "adir", new ArrayList<GenericFile<Object>>(), 0); + Assert.assertTrue(result); + } + + @Test + public void testReadDirErrorIsHandledWithNoMorePoll() throws Exception { + RemoteFileConsumer<Object> consumer = getRemoteFileConsumer("false", true); + boolean result = consumer.doSafePollSubDirectory("anyPath", "adir", new ArrayList<GenericFile<Object>>(), 0); + Assert.assertFalse(result); + } + + @Test + public void testReadDirErrorNotHandled() throws Exception { + RemoteFileConsumer<Object> consumer = getRemoteFileConsumer("IllegalStateException", false); + try { + consumer.doSafePollSubDirectory("anyPath", "adir", new ArrayList<GenericFile<Object>>(), 0); + Assert.fail("Must throw wrapped IllegalStateException in GenericFileOperationFailedException"); + } catch (GenericFileOperationFailedException e) { + Assert.assertTrue(e.getCause() instanceof IllegalStateException); + } + } + + @Test + public void testReadDirErrorNotHandledForGenericFileOperationException() throws Exception { + RemoteFileConsumer<Object> consumer = getRemoteFileConsumer("GenericFileOperationFailedException", false); + try { + consumer.doSafePollSubDirectory("anyPath", "adir", new ArrayList<GenericFile<Object>>(), 0); + Assert.fail("Must throw GenericFileOperationFailedException"); + } catch (GenericFileOperationFailedException e) { + Assert.assertNull(e.getCause()); + } + } + + private RemoteFileConsumer<Object> getRemoteFileConsumer(final String doPollResult, final boolean ignoreCannotRetrieveFile) { + return new RemoteFileConsumer<Object>(remoteFileEndpoint, null, null) { + @Override + protected boolean doPollDirectory(String absolutePath, String dirName, List<GenericFile<Object>> genericFiles, int depth) { + switch (doPollResult) { + case "IllegalStateException": + throw new IllegalStateException("Problem"); + case "GenericFileOperationFailedException": + throw new GenericFileOperationFailedException("Perm error"); + case "true": + return true; + default: + return false; + } + } + @Override + protected boolean pollDirectory(String fileName, List<GenericFile<Object>> genericFiles, int depth) { + return false; + } + @Override + protected boolean isMatched(GenericFile<Object> file, String doneFileName, List<Object> files) { + return false; + } + @Override + protected boolean ignoreCannotRetrieveFile(String name, Exchange exchange, Exception cause) { + return ignoreCannotRetrieveFile; + } + }; + } +}