Author: davsclaus
Date: Sat Jul 26 04:13:57 2008
New Revision: 679979
URL: http://svn.apache.org/viewvc?rev=679979&view=rev
Log:
CAMEL-758: SFTP and FTPProdcer - creating remote folders should handle existing
folders
Added:
activemq/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerBuildDirectoryTest.java
(with props)
Modified:
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpProducer.java
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpProducer.java
Modified:
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpProducer.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpProducer.java?rev=679979&r1=679978&r2=679979&view=diff
==============================================================================
---
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpProducer.java
(original)
+++
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpProducer.java
Sat Jul 26 04:13:57 2008
@@ -47,12 +47,12 @@
} catch (FTPConnectionClosedException e) {
// If the server disconnected us, then we must manually disconnect
// the client before attempting to reconnect
- LOG.warn("Disconnecting due to exception: " + e.toString());
+ LOG.warn("Disconnecting due to exception: " + e.getMessage());
disconnect();
// Rethrow to signify that we didn't deliver
throw e;
} catch (RuntimeCamelException e) {
- LOG.warn("Caught RuntimeCamelException: " + e.toString());
+ LOG.warn("Caught RuntimeCamelException: " + e.getMessage(), e);
LOG.warn("Hoping an explicit disconnect/reconnect will solve the
problem");
disconnect();
// Rethrow to signify that we didn't deliver
@@ -61,40 +61,40 @@
}
protected void connectIfNecessary() throws IOException {
- // TODO: is there a way to avoid copy-pasting the reconnect logic?
if (!client.isConnected()) {
- LOG.warn("FtpProducer's client isn't connected, trying to
reconnect...");
+ LOG.debug("Not connected, trying to reconnect.");
endpoint.connect(client);
- LOG.info("Connected to " + endpoint.getConfiguration());
+ LOG.info("Connected to " +
endpoint.getConfiguration().remoteServerInformation());
}
}
public void disconnect() throws IOException {
- LOG.info("FtpProducer's client is being explicitly disconnected");
+ LOG.debug("Disconnecting from " +
endpoint.getConfiguration().remoteServerInformation());
endpoint.disconnect(client);
}
public void process(RemoteFileExchange exchange) throws Exception {
InputStream payload = exchange.getIn().getBody(InputStream.class);
try {
+ String remoteServer =
endpoint.getConfiguration().remoteServerInformation();
String fileName = createFileName(exchange.getIn(),
endpoint.getConfiguration());
int lastPathIndex = fileName.lastIndexOf('/');
if (lastPathIndex != -1) {
String directory = fileName.substring(0, lastPathIndex);
if (!buildDirectory(client, directory)) {
- LOG.warn("Couldn't build directory: " + directory + "
(either permissions deny it, or it already exists)");
+ LOG.warn("Couldn't build directory: " + directory + "
(could be because of denied permissions)");
}
}
- final boolean success = client.storeFile(fileName, payload);
+ boolean success = client.storeFile(fileName, payload);
if (!success) {
- // TODO: Should we not have better exception for this?
- throw new RuntimeCamelException("Error sending file: " +
fileName);
+ throw new RuntimeCamelException("Error sending file: " +
fileName + " to: " + remoteServer);
}
- RemoteFileConfiguration config = endpoint.getConfiguration();
- LOG.info("Sent: " + fileName + " to " +
config.toString().substring(0, config.toString().indexOf(config.getFile())));
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Sent: " + fileName + " to: " + remoteServer);
+ }
} finally {
if (payload != null) {
payload.close();
@@ -108,7 +108,7 @@
try {
connectIfNecessary();
} catch (IOException e) {
- LOG.warn("Couldn't connect to " + endpoint.getConfiguration());
+ LOG.warn("Couldn't connect to: " +
endpoint.getConfiguration().remoteServerInformation());
}
super.doStart();
}
@@ -121,24 +121,24 @@
}
protected static boolean buildDirectory(FTPClient ftpClient, String
dirName) throws IOException {
- boolean atLeastOneSuccess = false;
- final StringBuilder sb = new StringBuilder(dirName.length());
- final String[] dirs = dirName.split("\\/");
-
- for (String dir : dirs) {
- sb.append(dir).append('/');
- String directory = sb.toString();
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("Trying to build directory: " + directory);
- }
- final boolean success = ftpClient.makeDirectory(directory);
+ String originalDirectory = ftpClient.printWorkingDirectory();
- if (!atLeastOneSuccess && success) {
- atLeastOneSuccess = true;
+ boolean success = false;
+ try {
+ // maybe the full directory already exsits
+ success = ftpClient.changeWorkingDirectory(dirName);
+ if (!success) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Trying to build remote directory: " + dirName);
+ }
+ success = ftpClient.makeDirectory(dirName);
}
+ } finally {
+ // change back to original directory
+ ftpClient.changeWorkingDirectory(originalDirectory);
}
- return atLeastOneSuccess;
+ return success;
}
+
}
Modified:
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java?rev=679979&r1=679978&r2=679979&view=diff
==============================================================================
---
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java
(original)
+++
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConfiguration.java
Sat Jul 26 04:13:57 2008
@@ -46,7 +46,14 @@
}
public String toString() {
- return protocol + "://" + username + "@" + host + ":" + port + "/" +
file;
+ return remoteServerInformation() + "/" + file;
+ }
+
+ /**
+ * Returns human readable server information for logging purpose
+ */
+ public String remoteServerInformation() {
+ return protocol + "://" + username + "@" + host + ":" + port;
}
public void configure(URI uri) {
Modified:
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpProducer.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpProducer.java?rev=679979&r1=679978&r2=679979&view=diff
==============================================================================
---
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpProducer.java
(original)
+++
activemq/camel/trunk/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpProducer.java
Sat Jul 26 04:13:57 2008
@@ -16,7 +16,6 @@
*/
package org.apache.camel.component.file.remote;
-
import java.io.IOException;
import java.io.InputStream;
@@ -29,7 +28,6 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
public class SftpProducer extends RemoteFileProducer<RemoteFileExchange> {
private static final transient Log LOG =
LogFactory.getLog(SftpProducer.class);
@@ -46,30 +44,29 @@
protected void connectIfNecessary() throws JSchException {
if (channel == null || !channel.isConnected()) {
if (session == null || !session.isConnected()) {
- LOG.info("Session isn't connected, trying to recreate and
connect...");
+ LOG.debug("Session isn't connected, trying to recreate and
connect.");
session = endpoint.createSession();
session.connect();
}
- LOG.info("Channel isn't connected, trying to recreate and
connect...");
+ LOG.debug("Channel isn't connected, trying to recreate and
connect.");
channel = endpoint.createChannelSftp(session);
channel.connect();
- LOG.info("Connected to " + endpoint.getConfiguration().toString());
+ LOG.info("Connected to " +
endpoint.getConfiguration().remoteServerInformation());
}
}
protected void disconnect() throws JSchException {
if (session != null) {
- LOG.info("Session is being explicitly disconnected");
+ LOG.debug("Session is being explicitly disconnected");
session.disconnect();
}
if (channel != null) {
- LOG.info("Channel is being explicitly disconnected");
+ LOG.debug("Channel is being explicitly disconnected");
channel.disconnect();
}
}
public void process(Exchange exchange) throws Exception {
- // TODO: is there a way to avoid copy-pasting the reconnect logic?
connectIfNecessary();
// If the attempt to connect isn't successful, then the thrown
// exception will signify that we couldn't deliver
@@ -78,15 +75,16 @@
} catch (JSchException e) {
// If the connection has gone stale, then we must manually
disconnect
// the client before attempting to reconnect
- LOG.warn("Disconnecting due to exception: " + e.toString());
+ LOG.warn("Disconnecting due to exception: " + e.getMessage());
disconnect();
// Rethrow to signify that we didn't deliver
throw e;
} catch (SftpException e) {
// Still not sure if/when these come up and what we should do
about them
// client.disconnect();
- LOG.warn("Caught SftpException:" + e.toString());
- LOG.warn("Doing nothing for now, need to determine an appropriate
action");
+ LOG.warn("Caught SftpException:" + e.getMessage(), e);
+ LOG.warn("Hoping an explicit disconnect/reconnect will solve the
problem");
+ disconnect();
// Rethrow to signify that we didn't deliver
throw e;
}
@@ -95,6 +93,7 @@
public void process(RemoteFileExchange exchange) throws Exception {
InputStream payload = exchange.getIn().getBody(InputStream.class);
try {
+ String remoteServer =
endpoint.getConfiguration().remoteServerInformation();
String fileName = createFileName(exchange.getIn(),
endpoint.getConfiguration());
int lastPathIndex = fileName.lastIndexOf('/');
@@ -102,12 +101,15 @@
String directory = fileName.substring(0, lastPathIndex);
boolean success = buildDirectory(channel, directory);
if (!success) {
- LOG.warn("Couldn't build directory: " + directory + "
(either permissions deny it, or it already exists)");
+ LOG.warn("Couldn't build directory: " + directory + "
(could be because of denied permissions)");
}
}
channel.put(payload, fileName);
- LOG.info("Sent: " + fileName + " to " +
endpoint.getConfiguration());
+
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Sent: " + fileName + " to: " + remoteServer);
+ }
} finally {
if (payload != null) {
payload.close();
@@ -121,7 +123,7 @@
try {
connectIfNecessary();
} catch (JSchException e) {
- LOG.warn("Couldn't connect to " + endpoint.getConfiguration());
+ LOG.warn("Couldn't connect to: " +
endpoint.getConfiguration().remoteServerInformation());
}
super.doStart();
}
@@ -135,24 +137,31 @@
protected static boolean buildDirectory(ChannelSftp sftpClient, String
dirName)
throws IOException, SftpException {
+ String originalDirectory = sftpClient.pwd();
- boolean atLeastOneSuccess = false;
- final StringBuilder sb = new StringBuilder(dirName.length());
- final String[] dirs = dirName.split("\\/");
- for (String dir : dirs) {
- sb.append(dir).append('/');
- String directory = sb.toString();
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("Trying to build directory: " + directory);
+ boolean success = false;
+ try {
+ // maybe the full directory already exsits
+ try {
+ sftpClient.cd(dirName);
+ success = true;
+ } catch (SftpException e) {
+ // ignore, we could not change directory so try to create it
instead
}
- sftpClient.mkdir(directory);
- if (!atLeastOneSuccess) {
- atLeastOneSuccess = true;
+
+ if (!success) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Trying to build remote directory: " + dirName);
+ }
+ sftpClient.mkdir(dirName);
+ success = true;
}
+ } finally {
+ // change back to original directory
+ sftpClient.cd(originalDirectory);
}
- return atLeastOneSuccess;
+ return success;
}
}
\ No newline at end of file
Added:
activemq/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerBuildDirectoryTest.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerBuildDirectoryTest.java?rev=679979&view=auto
==============================================================================
---
activemq/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerBuildDirectoryTest.java
(added)
+++
activemq/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerBuildDirectoryTest.java
Sat Jul 26 04:13:57 2008
@@ -0,0 +1,65 @@
+/**
+ * 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.io.File;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.converter.IOConverter;
+import org.apache.camel.component.file.FileComponent;
+
+/**
+ * Unit test to verify that Camel can build remote directory on FTP server if
missing (full or part of).
+ */
+public class FtpProducerBuildDirectoryTest extends FtpServerTestSupport {
+
+ private String port = "20018";
+ private String ftpUrl = "ftp://[EMAIL PROTECTED]:" + port +
"/upload/user/claus?binary=false&password=admin";
+
+ public String getPort() {
+ return port;
+ }
+
+ public void testProduceAndBuildFullRemotFolderTest() throws Exception {
+ deleteDirectory("./res/home/");
+
+ template.sendBodyAndHeader(ftpUrl, "Hello World",
FileComponent.HEADER_FILE_NAME, "claus.txt");
+
+ File file = new File("./res/home/upload/user/claus/claus.txt");
+ file = file.getAbsoluteFile();
+ assertTrue("The uploaded file should exists", file.exists());
+ assertEquals("Hello World", IOConverter.toString(file));
+ }
+
+ public void testProduceAndBuildPartOfRemotFolderTest() throws Exception {
+ deleteDirectory("./res/home/");
+ createDirectory("./res/home/upload/user/superman");
+
+ template.sendBodyAndHeader(ftpUrl, "Bye World",
FileComponent.HEADER_FILE_NAME, "claus.txt");
+
+ File file = new File("./res/home/upload/user/claus/claus.txt");
+ file = file.getAbsoluteFile();
+ assertTrue("The uploaded file should exists", file.exists());
+ assertEquals("Bye World", IOConverter.toString(file));
+ }
+
+ private static void createDirectory(String s) {
+ File file = new File(s);
+ file.mkdirs();
+ }
+
+}
Propchange:
activemq/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerBuildDirectoryTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
activemq/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpProducerBuildDirectoryTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date