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>"));
         }
     }