dir -> directory

This commit is contained in:
Mark Fisher
2011-09-02 08:24:47 -04:00
parent 962e089bf0
commit 754917bb4e
9 changed files with 272 additions and 251 deletions

View File

@@ -30,7 +30,7 @@ public abstract class FileHeaders {
public static final String ORIGINAL_FILE = PREFIX + "originalFile";
public static final String REMOTE_DIR = PREFIX + "remoteDir";
public static final String REMOTE_DIRECTORY = PREFIX + "remoteDirectory";
public static final String REMOTE_FILE = PREFIX + "remoteFile";

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.file.remote;
import java.util.Date;
@@ -20,30 +21,30 @@ import java.util.Date;
/**
* Abstract implementation of {@link FileInfo}; provides a setter
* for the remote directory and a generic toString implementation.
*
* @author Gary Russell
* @since 2.1
*
*/
public abstract class AbstractFileInfo<F> implements FileInfo<F>, Comparable<FileInfo<F>> {
private String remoteDir;
private String remoteDirectory;
/**
* @param remoteDir the remoteDir to set
* @param remoteDirectory the remoteDirectory to set
*/
public void setRemoteDir(String remoteDir) {
this.remoteDir = remoteDir;
public void setRemoteDirectory(String remoteDirectory) {
this.remoteDirectory = remoteDirectory;
}
public String getRemoteDir() {
return remoteDir;
public String getRemoteDirectory() {
return remoteDirectory;
}
public String toString() {
return "FileInfo [isDir=" + isDir() + ", isLink=" + isLink()
return "FileInfo [isDirectory=" + isDirectory() + ", isLink=" + isLink()
+ ", Size=" + getSize() + ", ModifiedTime="
+ new Date(getModified()) + ", Filename=" + getFilename()
+ ", RemoteDir=" + getRemoteDir() + ", Permissions=" + getPermissions() + "]";
+ ", RemoteDirectory=" + getRemoteDirectory() + ", Permissions=" + getPermissions() + "]";
}
public int compareTo(FileInfo<F> o) {

View File

@@ -13,20 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.file.remote;
/**
* Represents a remote file info - abstraction over underlying implementation
* Represents a remote file info - an abstraction over the underlying implementation.
*
* @author Gary Russell
* @since 2.1
*
*/
public interface FileInfo<F> {
/**
* @return true if the remote file is a directory
*/
public abstract boolean isDir();
public abstract boolean isDirectory();
/**
* @return true if the remote file is a link
@@ -51,7 +52,7 @@ public interface FileInfo<F> {
/**
* @return the remote directory in which the file resides
*/
public abstract String getRemoteDir();
public abstract String getRemoteDirectory();
/**
* @return a string representing the permissions of the remote

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.file.remote.gateway;
import java.io.File;
@@ -43,9 +44,10 @@ import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Base class for Outbound Gateways that perform remote file operations.
*
* @author Gary Russell
* @since 2.1
*
*/
public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReplyProducingMessageHandler {
@@ -97,228 +99,6 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
new SpelExpressionParser().parseExpression(expression));
}
@Override
protected void onInit() {
super.onInit();
Assert.notNull(this.command, "command must not be null");
Assert.isTrue(COMMAND_LS.equals(this.command) || COMMAND_GET.equals(this.command) ||
COMMAND_RM.equals(this.command),
"command must be one of ls, get, rm");
if (COMMAND_RM.equals(this.command)) {
Assert.isNull(this.filter, "Filters are not supported with the rm command");
} else if (COMMAND_GET.equals(this.command)) {
Assert.notNull(this.localDirectory, "localDirectory must not be null");
try {
if (!this.localDirectory.exists()) {
if (this.autoCreateLocalDirectory) {
if (logger.isDebugEnabled()) {
logger.debug("The '" + this.localDirectory + "' directory doesn't exist; Will create.");
}
if (!this.localDirectory.mkdirs()) {
throw new IOException("Failed to make local directory: " + this.localDirectory);
}
}
else {
throw new FileNotFoundException(this.localDirectory.getName());
}
}
}
catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new MessagingException(
"Failure during initialization of: " + this.getComponentType(), e);
}
}
}
@Override
protected Object handleRequestMessage(Message<?> requestMessage) {
Session session = this.sessionFactory.getSession();
try {
if (COMMAND_LS.equals(this.command)) {
String dir = this.processor.processMessage(requestMessage);
if (!dir.endsWith("/")) {
dir += "/";
}
return MessageBuilder.withPayload(ls(session, dir))
.setHeader(FileHeaders.REMOTE_DIR, dir)
.build();
} else if (COMMAND_GET.equals(this.command)) {
String remoteFilePath = this.processor.processMessage(requestMessage);
String remoteFilename = getRemoteFilename(remoteFilePath);
String remoteDir = remoteFilePath.substring(0, remoteFilePath.indexOf(remoteFilename));
if (remoteDir.length() == 0) {
remoteDir = "/";
}
return MessageBuilder.withPayload(get(session, remoteFilePath, remoteFilename))
.setHeader(FileHeaders.REMOTE_DIR, remoteDir)
.setHeader(FileHeaders.REMOTE_FILE, remoteFilename)
.build();
} else if (COMMAND_RM.equals(this.command)) {
String remoteFilePath = this.processor.processMessage(requestMessage);
String remoteFilename = getRemoteFilename(remoteFilePath);
String remoteDir = remoteFilePath.substring(0, remoteFilePath.indexOf(remoteFilename));
if (remoteDir.length() == 0) {
remoteDir = "/";
}
return MessageBuilder.withPayload(rm(session, remoteFilePath))
.setHeader(FileHeaders.REMOTE_DIR, remoteDir)
.setHeader(FileHeaders.REMOTE_FILE, remoteFilename)
.build();
} else {
return null;
}
} catch (IOException e) {
throw new MessagingException(requestMessage, e);
} finally {
session.close();
}
}
protected List<?> ls(Session session, String dir) throws IOException {
List<F> lsFiles = new ArrayList<F>();
F[] files = session.<F>list(dir);
if (!ObjectUtils.isEmpty(files)) {
Collection<F> filteredFiles = this.filterFiles(files);
for (F file : filteredFiles) {
if (file != null) {
if (this.options.contains(OPTION_SUBDIRS) ||
!isDir(file)) {
lsFiles.add(file);
}
}
}
} else {
return lsFiles;
}
if (!this.options.contains(OPTION_LINKS)) {
purgeLinks(lsFiles);
}
if (!this.options.contains(OPTION_ALL)) {
purgeDots(lsFiles);
}
if (this.options.contains(OPTION_NAME_ONLY)) {
List<String> results = new ArrayList<String>();
for (F file : lsFiles) {
results.add(getFilename(file));
}
if (!this.options.contains(OPTION_NOSORT)) {
Collections.sort(results);
}
return results;
} else {
List<AbstractFileInfo<F>> canonicalFiles = this.asFileInfoList(lsFiles);
for (AbstractFileInfo<F> file : canonicalFiles) {
file.setRemoteDir(dir);
}
if (!this.options.contains(OPTION_NOSORT)) {
Collections.sort(canonicalFiles);
}
return canonicalFiles;
}
}
protected final List<F> filterFiles(F[] files) {
return (this.filter != null) ? this.filter.filterFiles(files) : Arrays.asList(files);
}
protected void purgeLinks(List<F> lsFiles) {
Iterator<F> iterator = lsFiles.iterator();
while (iterator.hasNext()) {
if (this.isLink(iterator.next())) {
iterator.remove();
}
}
}
protected void purgeDots(List<F> lsFiles) {
Iterator<F> iterator = lsFiles.iterator();
while (iterator.hasNext()) {
if (getFilename(iterator.next()).startsWith(".")) {
iterator.remove();
}
}
}
/**
* Copy a remote file to the configured local directory.
* @param session
* @param remoteFilePath
* @return
* @throws IOException
*/
protected File get(Session session, String remoteFilePath, String remoteFilename)
throws IOException {
F[] files = session.<F>list(remoteFilePath);
if (files.length != 1 || isDir(files[0]) || isLink(files[0])) {
throw new MessagingException(remoteFilePath + " is not a file");
}
File localFile = new File(this.localDirectory, remoteFilename);
if (!localFile.exists()) {
String tempFileName = localFile.getAbsolutePath() + this.temporaryFileSuffix;
File tempFile = new File(tempFileName);
FileOutputStream fileOutputStream = new FileOutputStream(tempFile);
try {
session.read(remoteFilePath, fileOutputStream);
}
catch (Exception e) {
if (e instanceof RuntimeException){
throw (RuntimeException) e;
}
else {
throw new MessagingException("Failure occurred while copying from remote to local directory", e);
}
}
finally {
try {
fileOutputStream.close();
}
catch (Exception ignored2) {
}
}
if (!tempFile.renameTo(localFile)) {
throw new MessagingException("Failed to rename local file");
}
if (this.options.contains(OPTION_PRESERVE_TIMESTAMP)) {
localFile.setLastModified(getModified(files[0]));
}
return localFile;
} else {
throw new MessagingException("Local file " + localFile + " already exists");
}
}
/**
* @param remoteFilePath
* @return
*/
protected String getRemoteFilename(String remoteFilePath) {
String remoteFileName;
int index = remoteFilePath.lastIndexOf(this.remoteFileSeparator);
if (index < 0) {
remoteFileName = remoteFilePath;
} else {
remoteFileName = remoteFilePath.substring(index + 1);
}
return remoteFileName;
}
protected boolean rm(Session session, String remoteFilePath)
throws IOException {
return session.remove(remoteFilePath);
}
abstract protected boolean isDir(F file);
abstract protected boolean isLink(F file);
abstract protected String getFilename(F file);
abstract protected long getModified(F file);
abstract protected List<AbstractFileInfo<F>> asFileInfoList(Collection<F> files);
/**
* @param options the options to set
@@ -365,4 +145,230 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
this.filter = filter;
}
@Override
protected void onInit() {
super.onInit();
Assert.notNull(this.command, "command must not be null");
Assert.isTrue(COMMAND_LS.equals(this.command) || COMMAND_GET.equals(this.command) ||
COMMAND_RM.equals(this.command),
"command must be one of ls, get, rm");
if (COMMAND_RM.equals(this.command)) {
Assert.isNull(this.filter, "Filters are not supported with the rm command");
} else if (COMMAND_GET.equals(this.command)) {
Assert.notNull(this.localDirectory, "localDirectory must not be null");
try {
if (!this.localDirectory.exists()) {
if (this.autoCreateLocalDirectory) {
if (logger.isDebugEnabled()) {
logger.debug("The '" + this.localDirectory + "' directory doesn't exist; Will create.");
}
if (!this.localDirectory.mkdirs()) {
throw new IOException("Failed to make local directory: " + this.localDirectory);
}
}
else {
throw new FileNotFoundException(this.localDirectory.getName());
}
}
}
catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new MessagingException(
"Failure during initialization of: " + this.getComponentType(), e);
}
}
}
@Override
protected Object handleRequestMessage(Message<?> requestMessage) {
Session session = this.sessionFactory.getSession();
try {
if (COMMAND_LS.equals(this.command)) {
String dir = this.processor.processMessage(requestMessage);
if (!dir.endsWith("/")) {
dir += "/";
}
return MessageBuilder.withPayload(ls(session, dir))
.setHeader(FileHeaders.REMOTE_DIRECTORY, dir)
.build();
} else if (COMMAND_GET.equals(this.command)) {
String remoteFilePath = this.processor.processMessage(requestMessage);
String remoteFilename = getRemoteFilename(remoteFilePath);
String remoteDir = remoteFilePath.substring(0, remoteFilePath.indexOf(remoteFilename));
if (remoteDir.length() == 0) {
remoteDir = "/";
}
return MessageBuilder.withPayload(get(session, remoteFilePath, remoteFilename))
.setHeader(FileHeaders.REMOTE_DIRECTORY, remoteDir)
.setHeader(FileHeaders.REMOTE_FILE, remoteFilename)
.build();
} else if (COMMAND_RM.equals(this.command)) {
String remoteFilePath = this.processor.processMessage(requestMessage);
String remoteFilename = getRemoteFilename(remoteFilePath);
String remoteDir = remoteFilePath.substring(0, remoteFilePath.indexOf(remoteFilename));
if (remoteDir.length() == 0) {
remoteDir = "/";
}
return MessageBuilder.withPayload(rm(session, remoteFilePath))
.setHeader(FileHeaders.REMOTE_DIRECTORY, remoteDir)
.setHeader(FileHeaders.REMOTE_FILE, remoteFilename)
.build();
} else {
return null;
}
} catch (IOException e) {
throw new MessagingException(requestMessage, e);
} finally {
session.close();
}
}
protected List<?> ls(Session session, String dir) throws IOException {
List<F> lsFiles = new ArrayList<F>();
F[] files = session.<F>list(dir);
if (!ObjectUtils.isEmpty(files)) {
Collection<F> filteredFiles = this.filterFiles(files);
for (F file : filteredFiles) {
if (file != null) {
if (this.options.contains(OPTION_SUBDIRS) || !isDirectory(file)) {
lsFiles.add(file);
}
}
}
}
else {
return lsFiles;
}
if (!this.options.contains(OPTION_LINKS)) {
purgeLinks(lsFiles);
}
if (!this.options.contains(OPTION_ALL)) {
purgeDots(lsFiles);
}
if (this.options.contains(OPTION_NAME_ONLY)) {
List<String> results = new ArrayList<String>();
for (F file : lsFiles) {
results.add(getFilename(file));
}
if (!this.options.contains(OPTION_NOSORT)) {
Collections.sort(results);
}
return results;
}
else {
List<AbstractFileInfo<F>> canonicalFiles = this.asFileInfoList(lsFiles);
for (AbstractFileInfo<F> file : canonicalFiles) {
file.setRemoteDirectory(dir);
}
if (!this.options.contains(OPTION_NOSORT)) {
Collections.sort(canonicalFiles);
}
return canonicalFiles;
}
}
protected final List<F> filterFiles(F[] files) {
return (this.filter != null) ? this.filter.filterFiles(files) : Arrays.asList(files);
}
protected void purgeLinks(List<F> lsFiles) {
Iterator<F> iterator = lsFiles.iterator();
while (iterator.hasNext()) {
if (this.isLink(iterator.next())) {
iterator.remove();
}
}
}
protected void purgeDots(List<F> lsFiles) {
Iterator<F> iterator = lsFiles.iterator();
while (iterator.hasNext()) {
if (getFilename(iterator.next()).startsWith(".")) {
iterator.remove();
}
}
}
/**
* Copy a remote file to the configured local directory.
* @param session
* @param remoteFilePath
* @return
* @throws IOException
*/
protected File get(Session session, String remoteFilePath, String remoteFilename)
throws IOException {
F[] files = session.<F>list(remoteFilePath);
if (files.length != 1 || isDirectory(files[0]) || isLink(files[0])) {
throw new MessagingException(remoteFilePath + " is not a file");
}
File localFile = new File(this.localDirectory, remoteFilename);
if (!localFile.exists()) {
String tempFileName = localFile.getAbsolutePath() + this.temporaryFileSuffix;
File tempFile = new File(tempFileName);
FileOutputStream fileOutputStream = new FileOutputStream(tempFile);
try {
session.read(remoteFilePath, fileOutputStream);
}
catch (Exception e) {
if (e instanceof RuntimeException){
throw (RuntimeException) e;
}
else {
throw new MessagingException("Failure occurred while copying from remote to local directory", e);
}
}
finally {
try {
fileOutputStream.close();
}
catch (Exception ignored2) {
}
}
if (!tempFile.renameTo(localFile)) {
throw new MessagingException("Failed to rename local file");
}
if (this.options.contains(OPTION_PRESERVE_TIMESTAMP)) {
localFile.setLastModified(getModified(files[0]));
}
return localFile;
}
else {
throw new MessagingException("Local file " + localFile + " already exists");
}
}
/**
* @param remoteFilePath
* @return
*/
protected String getRemoteFilename(String remoteFilePath) {
String remoteFileName;
int index = remoteFilePath.lastIndexOf(this.remoteFileSeparator);
if (index < 0) {
remoteFileName = remoteFilePath;
}
else {
remoteFileName = remoteFilePath.substring(index + 1);
}
return remoteFileName;
}
protected boolean rm(Session session, String remoteFilePath)
throws IOException {
return session.remove(remoteFilePath);
}
abstract protected boolean isDirectory(F file);
abstract protected boolean isLink(F file);
abstract protected String getFilename(F file);
abstract protected long getModified(F file);
abstract protected List<AbstractFileInfo<F>> asFileInfoList(Collection<F> files);
}

View File

@@ -65,7 +65,7 @@ public class AbstractRemoteFileOutboundGatewayTests {
assertSame(files[1], out.getPayload().get(0)); // sort by default
assertSame(files[0], out.getPayload().get(1));
assertEquals("testremote/x/",
out.getHeaders().get(FileHeaders.REMOTE_DIR));
out.getHeaders().get(FileHeaders.REMOTE_DIRECTORY));
}
/**
@@ -99,7 +99,7 @@ public class AbstractRemoteFileOutboundGatewayTests {
assertSame(files[0], out.getPayload().get(0));
assertSame(files[1], out.getPayload().get(1));
assertEquals("testremote/x/",
out.getHeaders().get(FileHeaders.REMOTE_DIR));
out.getHeaders().get(FileHeaders.REMOTE_DIRECTORY));
}
@Test
@@ -276,7 +276,7 @@ public class AbstractRemoteFileOutboundGatewayTests {
assertTrue(outFile.exists());
outFile.delete();
assertEquals("/",
out.getHeaders().get(FileHeaders.REMOTE_DIR));
out.getHeaders().get(FileHeaders.REMOTE_DIRECTORY));
assertEquals("f1",
out.getHeaders().get(FileHeaders.REMOTE_FILE));
}
@@ -330,7 +330,7 @@ public class AbstractRemoteFileOutboundGatewayTests {
assertEquals(modified.getTime() / 1000 * 1000, outFile.lastModified());
outFile.delete();
assertEquals("x/",
out.getHeaders().get(FileHeaders.REMOTE_DIR));
out.getHeaders().get(FileHeaders.REMOTE_DIRECTORY));
assertEquals("f1",
out.getHeaders().get(FileHeaders.REMOTE_FILE));
}
@@ -393,7 +393,7 @@ public class AbstractRemoteFileOutboundGatewayTests {
assertEquals(Boolean.TRUE, out.getPayload());
verify(session).remove("testremote/x/f1");
assertEquals("testremote/x/",
out.getHeaders().get(FileHeaders.REMOTE_DIR));
out.getHeaders().get(FileHeaders.REMOTE_DIRECTORY));
assertEquals("f1",
out.getHeaders().get(FileHeaders.REMOTE_FILE));
}
@@ -408,8 +408,8 @@ class TestRemoteFileOutboundGateway extends AbstractRemoteFileOutboundGateway<Te
}
@Override
protected boolean isDir(TestLsEntry file) {
return file.isDir();
protected boolean isDirectory(TestLsEntry file) {
return file.isDirectory();
}
@Override
@@ -454,7 +454,7 @@ class TestLsEntry extends AbstractFileInfo<TestLsEntry> {
this.permissions = permissions;
}
public boolean isDir() {
public boolean isDirectory() {
return this.dir;
}

View File

@@ -27,6 +27,8 @@ import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.ftp.session.FtpFileInfo;
/**
* Outbound Gateway for performing remote file operations via FTP/FTPS.
*
* @author Gary Russell
* @since 2.1
*/
@@ -38,7 +40,7 @@ public class FtpOutboundGateway extends AbstractRemoteFileOutboundGateway<FTPFil
}
@Override
protected boolean isDir(FTPFile file) {
protected boolean isDirectory(FTPFile file) {
return file.isDirectory();
}

View File

@@ -13,26 +13,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.ftp.session;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.integration.file.remote.AbstractFileInfo;
import org.springframework.integration.file.remote.FileInfo;
import org.springframework.util.Assert;
/**
* A {@link FileInfo} implementation for FTP/FTPS.
*
* @author Gary Russell
* @since 2.1
*
*/
public class FtpFileInfo extends AbstractFileInfo<FTPFile> {
private final FTPFile ftpFile;
public FtpFileInfo(FTPFile ftpFile) {
Assert.notNull(ftpFile, "FTPFile must not be null");
this.ftpFile = ftpFile;
}
public boolean isDir() {
public boolean isDirectory() {
return this.ftpFile.isDirectory();
}

View File

@@ -28,6 +28,8 @@ import org.springframework.integration.sftp.session.SftpFileInfo;
import com.jcraft.jsch.ChannelSftp.LsEntry;
/**
* Outbound Gateway for performing remote file operations via SFTP.
*
* @author Gary Russell
* @since 2.1
*/
@@ -44,7 +46,7 @@ public class SftpOutboundGateway extends AbstractRemoteFileOutboundGateway<LsEnt
}
@Override
protected boolean isDir(LsEntry file) {
protected boolean isDirectory(LsEntry file) {
return file.getAttrs().isDir();
}

View File

@@ -13,18 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.sftp.session;
import org.springframework.integration.file.remote.AbstractFileInfo;
import org.springframework.integration.file.remote.FileInfo;
import org.springframework.util.Assert;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.SftpATTRS;
/**
* A {@link FileInfo} implementation for SFTP.
*
* @author Gary Russell
* @since 2.1
*
*/
public class SftpFileInfo extends AbstractFileInfo<LsEntry> {
@@ -32,7 +35,9 @@ public class SftpFileInfo extends AbstractFileInfo<LsEntry> {
private final SftpATTRS attrs;
public SftpFileInfo(LsEntry lsEntry) {
Assert.notNull("LsEntry must not be null");
this.lsEntry = lsEntry;
this.attrs = lsEntry.getAttrs();
}
@@ -41,7 +46,7 @@ public class SftpFileInfo extends AbstractFileInfo<LsEntry> {
* @return
* @see com.jcraft.jsch.SftpATTRS#isDir()
*/
public boolean isDir() {
public boolean isDirectory() {
return this.attrs.isDir();
}