/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.camel.component.file.remote; import java.net.URI; import org.apache.camel.component.file.GenericFileConfiguration; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriPath; import org.apache.camel.util.ObjectHelper; /** * Configuration of the FTP server */ public abstract class RemoteFileConfiguration extends GenericFileConfiguration { /** * Path separator as either unix or windows style. * <p/> * UNIX = Path separator / is used * Windows = Path separator \ is used * Auto = Use existing path separator in file name */ public enum PathSeparator { UNIX, Windows, Auto } // component name is implied as the protocol, eg ftp/ftps etc private String protocol; @UriPath @Metadata(required = "true") private String host; @UriPath private int port; @UriPath(name = "directoryName") private String directoryName; @UriParam(label = "security", secret = true) private String username; @UriParam(label = "security", secret = true) private String password; @UriParam private boolean binary; @UriParam private boolean passiveMode; @UriParam(defaultValue = "10000", label = "advanced") private int connectTimeout = 10000; @UriParam(defaultValue = "30000", label = "advanced") private int timeout = 30000; @UriParam(defaultValue = "300000", label = "advanced") private int soTimeout = 300000; @UriParam(defaultValue = "32768", label = "consumer,advanced") private int receiveBufferSize = 32 * 1024; @UriParam(label = "advanced") private boolean throwExceptionOnConnectFailed; @UriParam(label = "advanced") private String siteCommand; @UriParam(defaultValue = "true", label = "advanced") private boolean stepwise = true; @UriParam(defaultValue = "UNIX") private PathSeparator separator = PathSeparator.UNIX; @UriParam(label = "consumer") private boolean streamDownload; @UriParam(defaultValue = "true", label = "consumer,advanced") private boolean useList = true; @UriParam(label = "consumer,advanced") private boolean ignoreFileNotFoundOrPermissionError; @UriParam(label = "producer,advanced", defaultValue = "true") private boolean sendNoop = true; public RemoteFileConfiguration() { } public RemoteFileConfiguration(URI uri) { configure(uri); } @Override public boolean needToNormalize() { return false; } @Override public void configure(URI uri) { super.configure(uri); // after configure the directory has been resolved, so we can use it for directoryName // (directoryName is the name we use in the other file components, to use consistent name) setDirectoryName(getDirectory()); setProtocol(uri.getScheme()); setDefaultPort(); // UserInfo can contain both username and password as: user:pwd@ftpserver // see: http://en.wikipedia.org/wiki/URI_scheme String username = uri.getUserInfo(); String pw = null; if (username != null && username.contains(":")) { pw = ObjectHelper.after(username, ":"); username = ObjectHelper.before(username, ":"); } if (username != null) { setUsername(username); } if (pw != null) { setPassword(pw); } setHost(uri.getHost()); setPort(uri.getPort()); } /** * Returns human readable server information for logging purpose */ public String remoteServerInformation() { return protocol + "://" + (username != null ? username : "anonymous") + "@" + host + ":" + getPort(); } protected abstract void setDefaultPort(); public String getHost() { return host; } /** * Hostname of the FTP server */ public void setHost(String host) { this.host = host; } public int getPort() { return port; } /** * Port of the FTP server */ public void setPort(int port) { // only set port if provided with a positive number if (port > 0) { this.port = port; } } public String getPassword() { return password; } /** * Password to use for login */ public void setPassword(String password) { this.password = password; } public String getProtocol() { return protocol; } /** * The ftp protocol to use */ public void setProtocol(String protocol) { this.protocol = protocol; } public String getUsername() { return username; } /** * Username to use for login */ public void setUsername(String username) { this.username = username; } public String getDirectoryName() { return directoryName; } /** * The starting directory */ public void setDirectoryName(String directoryName) { this.directoryName = directoryName; } public boolean isBinary() { return binary; } /** * Specifies the file transfer mode, BINARY or ASCII. Default is ASCII (false). */ public void setBinary(boolean binary) { this.binary = binary; } public boolean isPassiveMode() { return passiveMode; } /** * Sets passive mode connections. * <br/> * Default is active mode connections. */ public void setPassiveMode(boolean passiveMode) { this.passiveMode = passiveMode; } public int getConnectTimeout() { return connectTimeout; } /** * Sets the connect timeout for waiting for a connection to be established * <p/> * Used by both FTPClient and JSCH */ public void setConnectTimeout(int connectTimeout) { this.connectTimeout = connectTimeout; } public int getTimeout() { return timeout; } /** * Sets the data timeout for waiting for reply * <p/> * Used only by FTPClient */ public void setTimeout(int timeout) { this.timeout = timeout; } public int getSoTimeout() { return soTimeout; } /** * Sets the so timeout * <p/> * Used only by FTPClient */ public void setSoTimeout(int soTimeout) { this.soTimeout = soTimeout; } public int getReceiveBufferSize() { return receiveBufferSize; } /** * The receive (download) buffer size * <p/> * Used only by FTPClient */ public void setReceiveBufferSize(int receiveBufferSize) { this.receiveBufferSize = receiveBufferSize; } public boolean isThrowExceptionOnConnectFailed() { return throwExceptionOnConnectFailed; } /** * 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. */ public void setThrowExceptionOnConnectFailed(boolean throwExceptionOnConnectFailed) { this.throwExceptionOnConnectFailed = throwExceptionOnConnectFailed; } public String getSiteCommand() { return siteCommand; } /** * Sets optional site command(s) to be executed after successful login. * <p/> * Multiple site commands can be separated using a new line character (\n). * * @param siteCommand the site command(s). */ public void setSiteCommand(String siteCommand) { this.siteCommand = siteCommand; } public boolean isStepwise() { return stepwise; } /** * 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 */ public void setStepwise(boolean stepwise) { this.stepwise = stepwise; } public PathSeparator getSeparator() { return separator; } /** * 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 */ public void setSeparator(PathSeparator separator) { this.separator = separator; } public boolean isStreamDownload() { return streamDownload; } /** * 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. */ public void setStreamDownload(boolean streamDownload) { this.streamDownload = streamDownload; } public boolean isUseList() { return useList; } /** * 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>. */ public void setUseList(boolean useList) { this.useList = useList; } public boolean isIgnoreFileNotFoundOrPermissionError() { return ignoreFileNotFoundOrPermissionError; } /** * Whether to ignore when trying to download a file which does not exist or due to permission error. * <p/> * By default when a file does not exists or insufficient permission, then an exception is thrown. * Setting this option to <tt>true</tt> allows to ignore that instead. */ public void setIgnoreFileNotFoundOrPermissionError(boolean ignoreFileNotFoundOrPermissionError) { this.ignoreFileNotFoundOrPermissionError = ignoreFileNotFoundOrPermissionError; } public boolean isSendNoop() { return sendNoop; } /** * 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. */ public void setSendNoop(boolean sendNoop) { this.sendNoop = sendNoop; } /** * Normalizes the given path according to the configured path separator. * * @param path the given path * @return the normalized path */ public String normalizePath(String path) { if (ObjectHelper.isEmpty(path) || separator == PathSeparator.Auto) { return path; } if (separator == PathSeparator.UNIX) { // unix style return path.replace('\\', '/'); } else { // windows style return path.replace('/', '\\'); } } }