You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gn...@apache.org on 2020/01/30 20:37:01 UTC
[camel] 01/02: [CAMEL-14451] Fix jdk >= 9 compilation issue
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 4dfad46f0ebe44f0394184436ca7faea6ed7607b
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Thu Jan 30 16:35:13 2020 +0100
[CAMEL-14451] Fix jdk >= 9 compilation issue
---
.../camel/component/file/GenericFileEndpoint.java | 342 +++++++++++++++++----
.../file/remote/RemoteFileConfiguration.java | 63 ++--
.../component/file/remote/RemoteFileEndpoint.java | 25 +-
.../tools/apt/EndpointAnnotationProcessor.java | 2 +-
4 files changed, 347 insertions(+), 85 deletions(-)
diff --git a/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java b/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java
index 0b1e959..f73a881 100644
--- a/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java
+++ b/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java
@@ -68,134 +68,356 @@ public abstract class GenericFileEndpoint<T> extends ScheduledPollEndpoint imple
// common options
- @UriParam(label = "advanced", defaultValue = "true")
+ @UriParam(label = "advanced", defaultValue = "true", description = "Automatically create missing directories in " +
+ "the file's pathname. For the file consumer, that means creating the starting directory. For the file " +
+ "producer, it means the directory the files should be written to.")
protected boolean autoCreate = true;
- @UriParam(label = "advanced", defaultValue = "" + FileUtil.BUFFER_SIZE)
+ @UriParam(label = "advanced", defaultValue = "" + FileUtil.BUFFER_SIZE, description = "Buffer size in bytes used " +
+ "for writing files (or in case of FTP for downloading and uploading files).")
protected int bufferSize = FileUtil.BUFFER_SIZE;
- @UriParam
+ @UriParam(description = "This option is used to specify the encoding of the file. You can use this on the " +
+ "consumer, to specify the encodings of the files, which allow Camel to know the charset it should load " +
+ "the file content in case the file content is being accessed. Likewise when writing a file, you can use " +
+ "this option to specify which charset to write the file as well. Do mind that when writing the file " +
+ "Camel may have to read the message content into memory to be able to convert the data into the " +
+ "configured charset, so do not use this if you have big messages.")
protected String charset;
- @UriParam(javaType = "java.lang.String")
+ @UriParam(javaType = "java.lang.String", description = "Use Expression such as File Language to dynamically set " +
+ "the filename. For consumers, it's used as a filename filter. For producers, it's used to evaluate the " +
+ "filename to write. If an expression is set, it take precedence over the CamelFileName header. (Note: " +
+ "The header itself can also be an Expression). The expression options support both String and Expression " +
+ "types. If the expression is a String type, it is always evaluated using the File Language. If the " +
+ "expression is an Expression type, the specified Expression type is used - this allows you, for " +
+ "instance, to use OGNL expressions. For the consumer, you can use it to filter filenames, so you can " +
+ "for instance consume today's file using the File Language syntax: mydata-${date:now:yyyyMMdd}.txt. The " +
+ "producers support the CamelOverruleFileName header which takes precedence over any existing " +
+ "CamelFileName header; the CamelOverruleFileName is a header that is used only once, and makes it easier " +
+ "as this avoids to temporary store CamelFileName and have to restore it afterwards.")
protected Expression fileName;
- @UriParam
+ @UriParam(description = "Producer: If provided, then Camel will write a 2nd done file when the original file has " +
+ "been written. The done file will be empty. This option configures what file name to use. Either you can " +
+ "specify a fixed name. Or you can use dynamic placeholders. The done file will always be written in the " +
+ "same folder as the original file.<p/> Consumer: If provided, Camel will only consume files if a done " +
+ "file exists. This option configures what file name to use. Either you can specify a fixed name. Or you " +
+ "can use dynamic placeholders.The done file is always expected in the same folder as the original " +
+ "file.<p/> Only ${file.name} and ${file.name.next} is supported as dynamic placeholders.")
protected String doneFileName;
// producer options
- @UriParam(label = "producer")
+ @UriParam(label = "producer", description = "Flatten is used to flatten the file name path to strip any leading " +
+ "paths, so it's just the file name. This allows you to consume recursively into sub-directories, but " +
+ "when you eg write the files to another directory they will be written in a single directory. " +
+ "Setting this to true on the producer enforces that any file name in CamelFileName header will be " +
+ "stripped for any leading paths.")
protected boolean flatten;
- @UriParam(label = "producer", defaultValue = "Override")
+ @UriParam(label = "producer", defaultValue = "Override", description = "What to do if a file already exists with " +
+ "the same name. Override, which is the default, replaces the existing file.<p/>" +
+ " - Append - adds content to the existing file.<p/> " +
+ " - Fail - throws a GenericFileOperationException, indicating that there is already an existing file.<p/> " +
+ " - Ignore - silently ignores the problem and does not override the existing file, " +
+ "but assumes everything is okay.<p/> " +
+ " - Move - option requires to use the moveExisting option to be configured as well. The option " +
+ "eagerDeleteTargetFile can be used to control what to do if an moving the file, and there " +
+ "exists already an existing file, otherwise causing the move operation to fail. The Move option will move " +
+ "any existing files, before writing the target file.<p/> " +
+ " - TryRename is only applicable if tempFileName option is in use. This allows to try renaming the file " +
+ "from the temporary name to the actual name, without doing any exists check. This check may be faster on " +
+ "some file systems and especially FTP servers.")
protected GenericFileExist fileExist = GenericFileExist.Override;
- @UriParam(label = "producer")
+ @UriParam(label = "producer", description = "This option is used to write the file using a temporary name and " +
+ "then, after the write is complete, rename it to the real name. Can be used to identify files being " +
+ "written and also avoid consumers (not using exclusive read locks) reading in progress files. Is often " +
+ "used by FTP when uploading big files.")
protected String tempPrefix;
- @UriParam(label = "producer", javaType = "java.lang.String")
+ @UriParam(label = "producer", javaType = "java.lang.String", description = "The same as tempPrefix option but " +
+ "offering a more fine grained control on the naming of the temporary filename as it uses the File " +
+ "Language. The location for tempFilename is relative to the final file location in the option " +
+ "'fileName', not the target directory in the base uri. For example if option fileName includes a " +
+ "directory prefix: dir/finalFilename then tempFileName is relative to that subdirectory dir.")
protected Expression tempFileName;
- @UriParam(label = "producer,advanced", defaultValue = "true")
+ @UriParam(label = "producer,advanced", defaultValue = "true", description = "Whether or not to eagerly delete " +
+ "any existing target file. This option only applies when you use fileExists=Override and the " +
+ "tempFileName option as well. You can use this to disable (set it to false) deleting the target " +
+ "file before the temp file is written. For example you may write big files and want the target file " +
+ "to exists during the temp file is being written. This ensure the target file is only deleted until " +
+ "the very last moment, just before the temp file is being renamed to the target filename. This option " +
+ "is also used to control whether to delete any existing files when fileExist=Move is enabled, and an " +
+ "existing file exists. If this option copyAndDeleteOnRenameFails false, then an exception will be thrown " +
+ "if an existing file existed, if its true, then the existing file is deleted before the move operation.")
protected boolean eagerDeleteTargetFile = true;
- @UriParam(label = "producer,advanced")
+ @UriParam(label = "producer,advanced", description = "Will keep the last modified timestamp from the source file " +
+ "(if any). Will use the Exchange.FILE_LAST_MODIFIED header to located the timestamp. This header can " +
+ "contain either a java.util.Date or long with the timestamp. If the timestamp exists and the option is " +
+ "enabled it will set this timestamp on the written file. Note: This option only applies to the file " +
+ "producer. You cannot use this option with any of the ftp producers.")
protected boolean keepLastModified;
- @UriParam(label = "producer,advanced")
+ @UriParam(label = "producer,advanced", description = "Used to specify if a null body is allowed during file " +
+ "writing. If set to true then an empty file will be created, when set to false, and attempting to send" +
+ " a null body to the file component, a GenericFileWriteException of 'Cannot write null body to file.' " +
+ "will be thrown. If the `fileExist` option is set to 'Override', then the file will be truncated, and " +
+ "if set to `append` the file will remain unchanged.")
protected boolean allowNullBody;
- @UriParam(label = "producer", defaultValue = "true")
+ @UriParam(label = "producer", defaultValue = "true", description = "Used for jailing (restricting) writing files " +
+ "to the starting directory (and sub) only. This is enabled by default to not allow Camel to write files " +
+ "to outside directories (to be more secured out of the box). You can turn this off to allow writing " +
+ "files to directories outside the starting directory, such as parent or root folders.")
protected boolean jailStartingDirectory = true;
- @UriParam(label = "producer")
+ @UriParam(label = "producer", description = "Used to append characters (text) after writing files. This can for " +
+ "example be used to add new lines or other separators when writing and appending to existing files. <p/> " +
+ "To specify new-line (slash-n or slash-r) or tab (slash-t) characters then escape with an extra slash, " +
+ "eg slash-slash-n.")
protected String appendChars;
// consumer options
@UriParam
protected GenericFileConfiguration configuration;
- @UriParam(label = "consumer,advanced")
+ @UriParam(label = "consumer,advanced", description = "A pluggable " +
+ "org.apache.camel.component.file.GenericFileProcessStrategy " +
+ "allowing you to implement your own readLock option or similar. Can also be used when special conditions " +
+ "must be met before a file can be consumed, such as a special ready file exists. If this option is set " +
+ "then the readLock option does not apply.")
protected GenericFileProcessStrategy<T> processStrategy;
- @UriParam(label = "consumer,advanced")
+ @UriParam(label = "consumer,advanced", description = "A pluggable in-progress repository " +
+ "org.apache.camel.spi.IdempotentRepository. The in-progress repository is used to account the current in " +
+ "progress files being consumed. By default a memory based repository is used.")
protected IdempotentRepository inProgressRepository = MemoryIdempotentRepository.memoryIdempotentRepository(DEFAULT_IN_PROGRESS_CACHE_SIZE);
- @UriParam(label = "consumer,advanced")
+ @UriParam(label = "consumer,advanced", description = "When consuming, a local work directory can be used to " +
+ "store the remote file content directly in local files, to avoid loading the content into memory. This " +
+ "is beneficial, if you consume a very big remote file and thus can conserve memory.")
protected String localWorkDirectory;
- @UriParam(label = "consumer")
+ @UriParam(label = "consumer", description = "If true, the file is not moved or deleted in any way. This option " +
+ "is good for readonly data, or for ETL type requirements. If noop=true, Camel will set idempotent=true " +
+ "as well, to avoid consuming the same files over and over again.")
protected boolean noop;
- @UriParam(label = "consumer")
+ @UriParam(label = "consumer", description = "If a directory, will look for files in all the sub-directories as well.")
protected boolean recursive;
- @UriParam(label = "consumer")
+ @UriParam(label = "consumer", description = "If true, the file will be deleted after it is processed successfully.")
protected boolean delete;
- @UriParam(label = "consumer")
+ @UriParam(label = "consumer", description = "When pre-sort is enabled then the consumer will sort the file and " +
+ "directory names during polling, that was retrieved from the file system. You may want to do this in " +
+ "case you need to operate on the files in a sorted order. The pre-sort is executed before the consumer " +
+ "starts to filter, and accept files to process by Camel. This option is default=false meaning disabled.")
protected boolean preSort;
- @UriParam(label = "consumer,filter")
+ @UriParam(label = "consumer,filter", description = "To define a maximum messages to gather per poll. By default " +
+ "no maximum is set. Can be used to set a limit of e.g. 1000 to avoid when starting up the server that " +
+ "there are thousands of files. Set a value of 0 or negative to disabled it. Notice: If this option is " +
+ "in use then the File and FTP components will limit before any sorting. For example if you have 100000 " +
+ "files and use maxMessagesPerPoll=500, then only the first 500 files will be picked up, and then sorted. " +
+ "You can use the eagerMaxMessagesPerPoll option and set this to false to allow to scan all files first " +
+ "and then sort afterwards.")
protected int maxMessagesPerPoll;
- @UriParam(label = "consumer,filter", defaultValue = "true")
+ @UriParam(label = "consumer,filter", defaultValue = "true", description = "Allows for controlling whether the " +
+ "limit from maxMessagesPerPoll is eager or not. If eager then the limit is during the scanning of files. " +
+ "Where as false would scan all files, and then perform sorting. Setting this option to false allows for " +
+ "sorting all files first, and then limit the poll. Mind that this requires a higher memory usage as all " +
+ "file details are in memory to perform the sorting.")
protected boolean eagerMaxMessagesPerPoll = true;
- @UriParam(label = "consumer,filter", defaultValue = "" + Integer.MAX_VALUE)
+ @UriParam(label = "consumer,filter", defaultValue = "" + Integer.MAX_VALUE, description = "The maximum depth to " +
+ "traverse when recursively processing a directory.")
protected int maxDepth = Integer.MAX_VALUE;
- @UriParam(label = "consumer,filter")
+ @UriParam(label = "consumer,filter", description = "The minimum depth to start processing when recursively " +
+ "processing a directory. Using minDepth=1 means the base directory. Using minDepth=2 means the first " +
+ "sub directory.")
protected int minDepth;
- @UriParam(label = "consumer,filter")
+ @UriParam(label = "consumer,filter", description = "Is used to include files, if filename matches the regex " +
+ "pattern (matching is case in-sensitive). <p/> Notice if you use symbols such as plus sign and others " +
+ "you would need to configure this using the RAW() syntax if configuring this as an endpoint uri. See " +
+ "more details at <a href=\"http://camel.apache.org/how-do-i-configure-endpoints.html\">configuring " +
+ "endpoint uris</a>")
protected String include;
- @UriParam(label = "consumer,filter")
+ @UriParam(label = "consumer,filter", description = "Is used to exclude files, if filename matches the regex " +
+ "pattern (matching is case in-senstive). <p/> Notice if you use symbols such as plus sign and others " +
+ "you would need to configure this using the RAW() syntax if configuring this as an endpoint uri. See " +
+ "more details at <a href=\"http://camel.apache.org/how-do-i-configure-endpoints.html\">configuring " +
+ "" +
+ "endpoint uris</a>")
protected String exclude;
- @UriParam(label = "consumer,filter", javaType = "java.lang.String")
+ @UriParam(label = "consumer,filter", javaType = "java.lang.String", description = "Expression (such as Simple " +
+ "Language) used to dynamically set the filename when moving it after processing. To move files into " +
+ "a .done subdirectory just enter .done.")
protected Expression move;
- @UriParam(label = "consumer", javaType = "java.lang.String")
+ @UriParam(label = "consumer", javaType = "java.lang.String", description = "Sets the move failure expression " +
+ "based on Simple language. For example, to move files into a .error subdirectory use: .error. Note: " +
+ "When moving the files to the fail location Camel will handle the error and will not pick up the " +
+ "file again.")
protected Expression moveFailed;
- @UriParam(label = "consumer", javaType = "java.lang.String")
+ @UriParam(label = "consumer", javaType = "java.lang.String", description = "Expression (such as File Language) " +
+ "used to dynamically set the filename when moving it before processing. For example to move in-progress " +
+ "files into the order directory set this value to order.")
protected Expression preMove;
- @UriParam(label = "producer", javaType = "java.lang.String")
+ @UriParam(label = "producer", javaType = "java.lang.String", description = "Expression (such as File Language) " +
+ "used to compute file name to use when fileExist=Move is configured. To move files into a backup " +
+ "subdirectory just enter backup. This option only supports the following File Language tokens: " +
+ "\"file:name\", \"file:name.ext\", \"file:name.noext\", \"file:onlyname\", \"file:onlyname.noext\", " +
+ "\"file:ext\", and \"file:parent\". Notice the \"file:parent\" is not supported by the FTP component, " +
+ "as the FTP component can only move any existing files to a relative directory based on current dir " +
+ "as base.")
protected Expression moveExisting;
- @UriParam(label = "producer,advanced")
+ @UriParam(label = "producer,advanced", description = "Strategy (Custom Strategy) used to move file with special " +
+ "naming token to use when fileExist=Move is configured. By default, there is an implementation used if " +
+ "no custom strategy is provided")
protected FileMoveExistingStrategy moveExistingFileStrategy;
- @UriParam(label = "consumer,filter", defaultValue = "false")
+ @UriParam(label = "consumer,filter", defaultValue = "false", description = "Option to use the Idempotent " +
+ "Consumer EIP pattern to let Camel skip already processed files. Will by default use a memory based " +
+ "LRUCache that holds 1000 entries. If noop=true then idempotent will be enabled as well to avoid " +
+ "consuming the same files over and over again.")
protected Boolean idempotent;
- @UriParam(label = "consumer,filter", javaType = "java.lang.String")
+ @UriParam(label = "consumer,filter", javaType = "java.lang.String", description = "To use a custom idempotent " +
+ "key. By default the absolute path of the file is used. You can use the File Language, for example to " +
+ "use the file name and file size, you can do: idempotentKey=${file:name}-${file:size}")
protected Expression idempotentKey;
- @UriParam(label = "consumer,filter")
+ @UriParam(label = "consumer,filter", description = "A pluggable repository org.apache.camel.spi.IdempotentRepository " +
+ "which by default use MemoryMessageIdRepository if none is specified and idempotent is true.")
protected IdempotentRepository idempotentRepository;
- @UriParam(label = "consumer,filter")
+ @UriParam(label = "consumer,filter", description = "Pluggable filter as a org.apache.camel.component.file.GenericFileFilter " +
+ "class. Will skip files if filter returns false in its accept() method.")
protected GenericFileFilter<T> filter;
- @UriParam(label = "consumer,filter", javaType = "java.lang.String")
+ @UriParam(label = "consumer,filter", javaType = "java.lang.String", description = "Filters the directory based on " +
+ "Simple language. For example to filter on current date, you can use a simple date pattern such as " +
+ "${date:now:yyyMMdd}")
protected Predicate filterDirectory;
- @UriParam(label = "consumer,filter", javaType = "java.lang.String")
+ @UriParam(label = "consumer,filter", javaType = "java.lang.String", description = "Filters the file based on " +
+ "Simple language. For example to filter on file size, you can use ${file:size} > 5000")
protected Predicate filterFile;
- @UriParam(label = "consumer,filter", defaultValue = "true")
+ @UriParam(label = "consumer,filter", defaultValue = "true", description = "Sets case sensitive flag on ant filter.")
protected boolean antFilterCaseSensitive = true;
protected volatile AntPathMatcherGenericFileFilter<T> antFilter;
- @UriParam(label = "consumer,filter")
+ @UriParam(label = "consumer,filter", description = "Ant style filter inclusion. Multiple inclusions may be " +
+ "specified in comma-delimited format.")
protected String antInclude;
- @UriParam(label = "consumer,filter")
+ @UriParam(label = "consumer,filter", description = "Ant style filter exclusion. If both antInclude and antExclude are used, antExclude takes precedence over antInclude. Multiple exclusions may be specified in comma-delimited format.")
protected String antExclude;
- @UriParam(label = "consumer,sort")
+ @UriParam(label = "consumer,sort", description = "Pluggable sorter as a " +
+ "java.util.Comparator<org.apache.camel.component.file.GenericFile> class.")
protected Comparator<GenericFile<T>> sorter;
- @UriParam(label = "consumer,sort", javaType = "java.lang.String")
+ @UriParam(label = "consumer,sort", javaType = "java.lang.String", description = "Built-in sort by using the " +
+ "File Language. Supports nested sorts, so you can have a sort by file name and as a 2nd group sort " +
+ "by modified date.")
protected Comparator<Exchange> sortBy;
- @UriParam(label = "consumer,sort")
+ @UriParam(label = "consumer,sort", description = "To shuffle the list of files (sort in random order)")
protected boolean shuffle;
- @UriParam(label = "consumer,lock", defaultValue = "none", enums = "none,markerFile,fileLock,rename,changed,idempotent,idempotent-changed,idempotent-rename")
+ @UriParam(label = "consumer,lock", defaultValue = "none", enums = "none,markerFile,fileLock,rename,changed,idempotent,idempotent-changed,idempotent-rename",
+ description = "Used by consumer, to only poll the files if it has exclusive read-lock on the file (i.e. " +
+ "the file is not in-progress or being written). Camel will wait until the file lock is granted. " +
+ "This option provides the build in strategies:<p/>" +
+ " - none - No read lock is in use<p/>" +
+ " - markerFile - Camel creates a marker file (fileName.camelLock) and then holds a lock on it. " +
+ "This option is not available for the FTP component<p/>" +
+ " - changed - Changed is using file length/modification timestamp to detect whether the file " +
+ "is currently being copied or not. Will at least use 1 sec to determine this, so this option " +
+ "cannot consume files as fast as the others, but can be more reliable as the JDK IO API " +
+ "cannot always determine whether a file is currently being used by another process. The option " +
+ "readLockCheckInterval can be used to set the check frequency.<p/>" +
+ " - fileLock - is for using java.nio.channels.FileLock. This option is not avail for Windows OS " +
+ "and the FTP component. This approach should be avoided when accessing a remote file system via " +
+ "a mount/share unless that file system supports distributed file locks.<p/>" +
+ " - rename - rename is for using a try to rename the file as a test if we can get exclusive " +
+ "read-lock.<p/>" +
+ " - idempotent - (only for file component) idempotent is for using a idempotentRepository " +
+ "as the read-lock. This allows to use read locks that supports clustering if the idempotent " +
+ "repository implementation supports that.<p/>" +
+ " - idempotent-changed - (only for file component) idempotent-changed is for using a " +
+ "idempotentRepository and changed as the combined read-lock. This allows to use read locks " +
+ "that supports clustering if the idempotent repository implementation supports that.<p/>" +
+ " - idempotent-rename - (only for file component) idempotent-rename is for using a " +
+ "idempotentRepository and rename as the combined read-lock. This allows to use read locks " +
+ "that supports clustering if the idempotent repository implementation supports that.<p/>" +
+ "Notice: The various read locks is not all suited to work in clustered mode, where concurrent " +
+ "consumers on different nodes is competing for the same files on a shared file system. The " +
+ "markerFile using a close to atomic operation to create the empty marker file, but its not " +
+ "guaranteed to work in a cluster. The fileLock may work better but then the file system need " +
+ "to support distributed file locks, and so on. Using the idempotent read lock can support " +
+ "clustering if the idempotent repository supports clustering, such as Hazelcast Component or " +
+ "Infinispan.")
protected String readLock = "none";
- @UriParam(label = "consumer,lock", defaultValue = "1000")
+ @UriParam(label = "consumer,lock", defaultValue = "1000", description = "Interval in millis for the read-lock, " +
+ "if supported by the read lock. This interval is used for sleeping between attempts to acquire the read " +
+ "lock. For example when using the changed read lock, you can set a higher interval period to cater for " +
+ "slow writes. The default of 1 sec. may be too fast if the producer is very slow writing the file. <p/>" +
+ "Notice: For FTP the default readLockCheckInterval is 5000. <p/> The readLockTimeout value must be " +
+ "higher than readLockCheckInterval, but a rule of thumb is to have a timeout that is at least 2 or more " +
+ "times higher than the readLockCheckInterval. This is needed to ensure that amble time is allowed for " +
+ "the read lock process to try to grab the lock before the timeout was hit.")
protected long readLockCheckInterval = 1000;
- @UriParam(label = "consumer,lock", defaultValue = "10000")
+ @UriParam(label = "consumer,lock", defaultValue = "10000", description = "Optional timeout in millis for the " +
+ "read-lock, if supported by the read-lock. If the read-lock could not be granted and the timeout " +
+ "triggered, then Camel will skip the file. At next poll Camel, will try the file again, and this time " +
+ "maybe the read-lock could be granted. Use a value of 0 or lower to indicate forever. Currently " +
+ "fileLock, changed and rename support the timeout. <p/> Notice: For FTP the default readLockTimeout " +
+ "value is 20000 instead of 10000. <p/> The readLockTimeout value must be higher than " +
+ "readLockCheckInterval, but a rule of thumb is to have a timeout that is at least 2 or more times " +
+ "higher than the readLockCheckInterval. This is needed to ensure that amble time is allowed for the " +
+ "read lock process to try to grab the lock before the timeout was hit.")
protected long readLockTimeout = 10000;
- @UriParam(label = "consumer,lock", defaultValue = "true")
+ @UriParam(label = "consumer,lock", defaultValue = "true", description = "Whether to use marker file with the " +
+ "changed, rename, or exclusive read lock types. By default a marker file is used as well to guard " +
+ "against other processes picking up the same files. This behavior can be turned off by setting this " +
+ "option to false. For example if you do not want to write marker files to the file systems by the " +
+ "Camel application.")
protected boolean readLockMarkerFile = true;
- @UriParam(label = "consumer,lock", defaultValue = "true")
+ @UriParam(label = "consumer,lock", defaultValue = "true", description = "Whether or not read lock with marker " +
+ "files should upon startup delete any orphan read lock files, which may have been left on the file " +
+ "system, if Camel was not properly shutdown (such as a JVM crash). <p/> If turning this option to " +
+ "<tt>false</tt> then any orphaned lock file will cause Camel to not attempt to pickup that file, this " +
+ "could also be due another node is concurrently reading files from the same shared directory.")
protected boolean readLockDeleteOrphanLockFiles = true;
- @UriParam(label = "consumer,lock", defaultValue = "DEBUG")
+ @UriParam(label = "consumer,lock", defaultValue = "DEBUG", description = "Logging level used when a read lock " +
+ "could not be acquired. By default a DEBUG is logged. You can change this level, for example to OFF to " +
+ "not have any logging. This option is only applicable for readLock of types: changed, fileLock, " +
+ "idempotent, idempotent-changed, idempotent-rename, rename.")
protected LoggingLevel readLockLoggingLevel = LoggingLevel.DEBUG;
- @UriParam(label = "consumer,lock", defaultValue = "1")
+ @UriParam(label = "consumer,lock", defaultValue = "1", description = "This option is applied only for " +
+ "readLock=changed. It allows you to configure a minimum file length. By default Camel expects the file " +
+ "to contain data, and thus the default value is 1. You can set this option to zero, to allow consuming " +
+ "zero-length files.")
protected long readLockMinLength = 1;
- @UriParam(label = "consumer,lock", defaultValue = "0")
+ @UriParam(label = "consumer,lock", defaultValue = "0", description = "This option is applied only for " +
+ "readLock=changed. It allows to specify a minimum age the file must be before attempting to acquire " +
+ "the read lock. For example use readLockMinAge=300s to require the file is at last 5 minutes old. This " +
+ "can speedup the changed read lock as it will only attempt to acquire files which are at least " +
+ "that given age.")
protected long readLockMinAge;
- @UriParam(label = "consumer,lock", defaultValue = "true")
+ @UriParam(label = "consumer,lock", defaultValue = "true", description = "This option is applied only for " +
+ "readLock=idempotent. It allows to specify whether to remove the file name entry from the idempotent " +
+ "repository when processing the file failed and a rollback happens. If this option is false, then the " +
+ "file name entry is confirmed (as if the file did a commit).")
protected boolean readLockRemoveOnRollback = true;
- @UriParam(label = "consumer,lock")
+ @UriParam(label = "consumer,lock", description = "This option is applied only for readLock=idempotent. It allows " +
+ "to specify whether to remove the file name entry from the idempotent repository when processing the " +
+ "file is succeeded and a commit happens. <p/> By default the file is not removed which ensures that " +
+ "any race-condition do not occur so another active node may attempt to grab the file. Instead the " +
+ "idempotent repository may support eviction strategies that you can configure to evict the file name " +
+ "entry after X minutes - this ensures no problems with race conditions. <p/> See more details at the " +
+ "readLockIdempotentReleaseDelay option.")
protected boolean readLockRemoveOnCommit;
- @UriParam(label = "consumer,lock")
+ @UriParam(label = "consumer,lock", description = "Whether to delay the release task for a period of millis. <p/> " +
+ "This can be used to delay the release tasks to expand the window when a file is regarded as " +
+ "read-locked, in an active/active cluster scenario with a shared idempotent repository, to ensure " +
+ "other nodes cannot potentially scan and acquire the same file, due to race-conditions. By expanding " +
+ "the time-window of the release tasks helps prevents these situations. Note delaying is only needed " +
+ "if you have configured readLockRemoveOnCommit to true.")
protected int readLockIdempotentReleaseDelay;
- @UriParam(label = "consumer,lock")
+ @UriParam(label = "consumer,lock", description = "Whether the delayed release task should be synchronous or " +
+ "asynchronous. <p/> See more details at the readLockIdempotentReleaseDelay option.")
protected boolean readLockIdempotentReleaseAsync;
- @UriParam(label = "consumer,lock")
+ @UriParam(label = "consumer,lock", description = "The number of threads in the scheduled thread pool when using " +
+ "asynchronous release tasks. Using a default of 1 core threads should be sufficient in almost all " +
+ "use-cases, only set this to a higher value if either updating the idempotent repository is slow, or " +
+ "there are a lot of files to process. This option is not in-use if you use a shared thread pool by " +
+ "configuring the readLockIdempotentReleaseExecutorService option. <p/> See more details at the " +
+ "readLockIdempotentReleaseDelay option.")
protected int readLockIdempotentReleaseAsyncPoolSize;
- @UriParam(label = "consumer,lock")
+ @UriParam(label = "consumer,lock", description = "To use a custom and shared thread pool for asynchronous " +
+ "release tasks. <p/> See more details at the readLockIdempotentReleaseDelay option.")
protected ScheduledExecutorService readLockIdempotentReleaseExecutorService;
- @UriParam(label = "consumer,lock")
+ @UriParam(label = "consumer,lock", description = "Pluggable read-lock as a org.apache.camel.component.file.GenericFileExclusiveReadLockStrategy implementation.")
protected GenericFileExclusiveReadLockStrategy<T> exclusiveReadLockStrategy;
- @UriParam(label = "consumer,advanced")
+ @UriParam(label = "consumer,advanced", description = "To use a custom " +
+ "{@link org.apache.camel.spi.ExceptionHandler} to handle any thrown exceptions that happens during " +
+ "the file on completion process where the consumer does either a commit or rollback. The default " +
+ "implementation will log any exception at WARN level and ignore.")
protected ExceptionHandler onCompletionExceptionHandler;
private Pattern includePattern;
diff --git a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java
index dc0de9a..4ec44e5 100644
--- a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java
+++ b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java
@@ -41,41 +41,68 @@ public abstract class RemoteFileConfiguration extends GenericFileConfiguration {
// component name is implied as the protocol, eg ftp/ftps etc
private String protocol;
- @UriPath @Metadata(required = true)
+ @UriPath(description = "Hostname of the FTP server") @Metadata(required = true)
private String host;
- @UriPath
+ @UriPath(description = "Port of the FTP server")
private int port;
- @UriPath(name = "directoryName")
+ @UriPath(name = "directoryName", description = "The starting directory")
private String directoryName;
- @UriParam(label = "security", secret = true)
+ @UriParam(label = "security", secret = true, description = "Username to use for login")
private String username;
- @UriParam(label = "security", secret = true)
+ @UriParam(label = "security", secret = true, description = "Password to use for login")
private String password;
- @UriParam
+ @UriParam(description = "Specifies the file transfer mode, BINARY or ASCII. Default is ASCII (false).")
private boolean binary;
- @UriParam
+ @UriParam(description = "Sets passive mode connections.<br/> Default is active mode connections.")
private boolean passiveMode;
- @UriParam(defaultValue = "10000", label = "advanced")
+ @UriParam(defaultValue = "10000", label = "advanced", description = "Sets the connect timeout for waiting " +
+ "for a connection to be established <p/> Used by both FTPClient and JSCH")
private int connectTimeout = 10000;
- @UriParam(defaultValue = "30000", label = "advanced")
+ @UriParam(defaultValue = "30000", label = "advanced", description = "Sets the data timeout for waiting for " +
+ "reply <p/> Used only by FTPClient")
private int timeout = 30000;
- @UriParam(defaultValue = "300000", label = "advanced")
+ @UriParam(defaultValue = "300000", label = "advanced", description = "Sets the so timeout <p/> FTP and FTPS " +
+ "Only for Camel 2.4. SFTP for Camel 2.14.3/2.15.3/2.16 onwards. Is the SocketOptions.SO_TIMEOUT value " +
+ "in millis. Recommended option is to set this to 300000 so as not have a hanged connection. On SFTP this " +
+ "option is set as timeout on the JSCH Session instance.")
private int soTimeout = 300000;
- @UriParam(label = "advanced")
+ @UriParam(label = "advanced", description = "Should an exception be thrown if connection failed (exhausted) <p/> " +
+ "By default exception is not thrown and a <tt>WARN</tt> is logged. You can use this to enable exception " +
+ "being thrown and handle the thrown exception from the {@link " +
+ "org.apache.camel.spi.PollingConsumerPollStrategy} rollback method.")
private boolean throwExceptionOnConnectFailed;
- @UriParam(label = "advanced")
+ @UriParam(label = "advanced", description = "Sets optional site command(s) to be executed after successful " +
+ "login. <p/> Multiple site commands can be separated using a new line character.")
private String siteCommand;
- @UriParam(defaultValue = "true", label = "advanced")
+ @UriParam(defaultValue = "true", label = "advanced", description = "Sets whether we should stepwise change " +
+ "directories while traversing file structures when downloading files, or as well when uploading a file " +
+ "to a directory. <p/> You can disable this if you for example are in a situation where you cannot change " +
+ "directory on the FTP server due security reasons. @param stepwise whether to use change directory or not")
private boolean stepwise = true;
- @UriParam(defaultValue = "UNIX")
+ @UriParam(defaultValue = "UNIX", description = "Sets the path separator to be used. <p/> UNIX = Uses unix style " +
+ "path separator Windows = Uses windows style path separator Auto = (is default) Use existing path " +
+ "separator in file name")
private PathSeparator separator = PathSeparator.UNIX;
- @UriParam(label = "consumer")
+ @UriParam(label = "consumer", description = "Sets the download method to use when not using a local working " +
+ "directory. If set to true, the remote files are streamed to the route as they are read. When set to " +
+ "false, the remote files are loaded into memory before being sent into the route.")
private boolean streamDownload;
- @UriParam(defaultValue = "true", label = "consumer,advanced")
+ @UriParam(defaultValue = "true", label = "consumer,advanced", description = "Whether to allow using LIST " +
+ "command when downloading a file. <p/> Default is <tt>true</tt>. In some use cases you may want to " +
+ "download a specific file and are not allowed to use the LIST command, and therefore you can set " +
+ "this option to <tt>false</tt>. Notice when using this option, then the specific file to download " +
+ "does <b>not</b> include meta-data information such as file size, timestamp, permissions etc, because " +
+ "those information is only possible to retrieve when LIST command is in use.")
private boolean useList = true;
- @UriParam(label = "consumer,advanced")
+ @UriParam(label = "consumer,advanced", description = "Whether to ignore when (trying to list files in " +
+ "directories or when downloading a file), which does not exist or due to permission error. <p/> " +
+ "By default when a directory or file does not exists or insufficient permission, then an exception " +
+ "is thrown. Setting this option to <tt>true</tt> allows to ignore that instead.")
private boolean ignoreFileNotFoundOrPermissionError;
- @UriParam(label = "producer,advanced", defaultValue = "true")
+ @UriParam(label = "producer,advanced", defaultValue = "true", description = "Whether to send a noop command " +
+ "as a pre-write check before uploading files to the FTP server. <p/> This is enabled by default as " +
+ "a validation of the connection is still valid, which allows to silently re-connect to be able to " +
+ "upload the file. However if this causes problems, you can turn this option off.")
private boolean sendNoop = true;
public RemoteFileConfiguration() {
diff --git a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileEndpoint.java b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileEndpoint.java
index fdf7646..eed2033 100644
--- a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileEndpoint.java
+++ b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileEndpoint.java
@@ -39,17 +39,30 @@ public abstract class RemoteFileEndpoint<T> extends GenericFileEndpoint<T> {
private static final Logger LOG = LoggerFactory.getLogger(RemoteFileEndpoint.class);
- @UriParam(label = "advanced")
+ @UriParam(label = "advanced", description = "Specifies the maximum reconnect attempts Camel performs when it " +
+ "tries to connect to the remote FTP server. Use 0 to disable this behavior.")
private int maximumReconnectAttempts = 3;
- @UriParam(label = "advanced")
+ @UriParam(label = "advanced", description = "Delay in millis Camel will wait before performing a reconnect attempt.")
private long reconnectDelay = 1000;
- @UriParam(label = "common")
+ @UriParam(label = "common", description = "Whether or not to disconnect from remote FTP server right after use. " +
+ "Disconnect will only disconnect the current connection to the FTP server. If you have a consumer which " +
+ "you want to stop, then you need to stop the consumer/route instead.")
private boolean disconnect;
- @UriParam(label = "producer,advanced")
+ @UriParam(label = "producer,advanced", description = "Whether or not to disconnect from remote FTP server right " +
+ "after a Batch upload is complete. disconnectOnBatchComplete will only disconnect the current connection " +
+ "to the FTP server.")
private boolean disconnectOnBatchComplete;
- @UriParam(label = "common,advanced")
+ @UriParam(label = "common,advanced", description = "If set this option to be true, camel-ftp will use the list " +
+ "file directly to check if the file exists. Since some FTP server may not support to list the file " +
+ "directly, if the option is false, camel-ftp will use the old way to list the directory and check if the " +
+ "file exists. This option also influences readLock=changed to control whether it performs a fast check " +
+ "to update file information or not. This can be used to speed up the process if the FTP server has a lot " +
+ "of files.")
private boolean fastExistsCheck;
- @UriParam(label = "consumer,advanced")
+ @UriParam(label = "consumer,advanced", description = "Whether the FTP consumer should download the file. If this " +
+ "option is set to false, then the message body will be null, but the consumer will still trigger a Camel " +
+ "Exchange that has details about the file such as file name, file size, etc. It's just that the file will " +
+ "not be downloaded.")
private boolean download = true;
public RemoteFileEndpoint() {
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
index 6a9c3b0..36975ac 100644
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
@@ -215,7 +215,7 @@ public class EndpointAnnotationProcessor extends AbstractCamelAnnotationProcesso
option.setDescription(doc);
if (isNullOrEmpty(doc)) {
- throw new IllegalStateException("Empty doc for option: " + option.getName() + ", parent options:\n"
+ throw new IllegalStateException("Empty doc for option: " + option.getName() + ", parent options: "
+ (parentOptions != null ? Jsoner.serialize(JsonMapper.asJsonObject(parentOptions)) : "<null>"));
}
}