https://bz.apache.org/bugzilla/show_bug.cgi?id=47552 Patch-by: Matthew Yanosmaster
| @@ -252,6 +252,7 @@ Matthew Hawthorne | |||
| Matthew Inger | |||
| Matthew Kuperus Heun | |||
| Matthew Watson | |||
| Matthew Yanos | |||
| Matthias Bhend | |||
| Michael Bayne | |||
| Michael Clarke | |||
| @@ -27,6 +27,10 @@ Fixed bugs: | |||
| Other changes: | |||
| -------------- | |||
| * <scp> now supports compression via the optional compressed attribute. | |||
| Bugzilla Report 47552 | |||
| Changes from Ant 1.9.6 TO Ant 1.9.7 | |||
| =================================== | |||
| @@ -1037,6 +1037,10 @@ | |||
| <first>Matthew</first> | |||
| <last>Watson</last> | |||
| </name> | |||
| <name> | |||
| <first>Matthew</first> | |||
| <last>Yanos</last> | |||
| </name> | |||
| <name> | |||
| <first>Michael</first> | |||
| <last>Bayne</last> | |||
| @@ -217,6 +217,12 @@ for more information. This task has been tested with jsch-0.1.2 and later.</p> | |||
| <em>since Ant 1.9.7</em></td> | |||
| <td align="center" valign="top">No, defaults to 3</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">compressed</td> | |||
| <td valign="top">Whether to enable compression during transfer. | |||
| <em>since Ant 1.9.8</em></td> | |||
| <td align="center" valign="top">No, defaults to false</td> | |||
| </tr> | |||
| </table> | |||
| <h3>Parameters specified as nested elements</h3> | |||
| @@ -40,6 +40,7 @@ public abstract class AbstractSshMessage { | |||
| private final Session session; | |||
| private final boolean verbose; | |||
| private final boolean compressed; | |||
| private LogListener listener = new LogListener() { | |||
| public void log(final String message) { | |||
| // do nothing; | |||
| @@ -61,7 +62,19 @@ public abstract class AbstractSshMessage { | |||
| * @since Ant 1.6.2 | |||
| */ | |||
| public AbstractSshMessage(final boolean verbose, final Session session) { | |||
| this(verbose, false, session); | |||
| } | |||
| /** | |||
| * Constructor for AbstractSshMessage | |||
| * @param verbose if true do verbose logging | |||
| * @param compression if true use compression | |||
| * @param session the ssh session to use | |||
| * @since Ant 1.9.8 | |||
| */ | |||
| public AbstractSshMessage(boolean verbose, boolean compressed, Session session) { | |||
| this.verbose = verbose; | |||
| this.compressed = compressed; | |||
| this.session = session; | |||
| } | |||
| @@ -191,6 +204,15 @@ public abstract class AbstractSshMessage { | |||
| return verbose; | |||
| } | |||
| /** | |||
| * Is the compressed attribute set. | |||
| * @return true if the compressed attribute is set | |||
| * @since Ant 1.9.8 | |||
| */ | |||
| protected final boolean getCompressed() { | |||
| return compressed; | |||
| } | |||
| /** | |||
| * Track progress every 10% if 100kb < filesize < 1mb. For larger | |||
| * files track progress for every percent transmitted. | |||
| @@ -54,6 +54,7 @@ public class Scp extends SSHBase { | |||
| private String fromUri; | |||
| private String toUri; | |||
| private boolean preserveLastModified = false; | |||
| private boolean compressed = false; | |||
| private List<ResourceCollection> rcs = null; | |||
| private boolean isFromRemote, isToRemote; | |||
| private boolean isSftp = false; | |||
| @@ -111,6 +112,15 @@ public class Scp extends SSHBase { | |||
| this.isFromRemote = true; | |||
| } | |||
| /** | |||
| * Sets flag to determine if compression should | |||
| * be used for the copy. | |||
| * @since Ant 1.9.8 | |||
| */ | |||
| public void setCompressed(boolean compressed) { | |||
| this.compressed = compressed; | |||
| } | |||
| /** | |||
| * Similar to {@link #setTodir setTodir} but explicitly states | |||
| * that the directory is a local. This is the only way to specify | |||
| @@ -295,7 +305,8 @@ public class Scp extends SSHBase { | |||
| new ScpFromMessage(getVerbose(), session, file, | |||
| getProject().resolveFile(toPath), | |||
| fromSshUri.endsWith("*"), | |||
| preserveLastModified); | |||
| preserveLastModified, | |||
| compressed); | |||
| } else { | |||
| message = | |||
| new ScpFromMessageBySftp(getVerbose(), session, file, | |||
| @@ -339,7 +350,7 @@ public class Scp extends SSHBase { | |||
| session = openSession(); | |||
| ScpToMessage message = null; | |||
| if (!isSftp) { | |||
| message = new ScpToMessage(getVerbose(), session, | |||
| message = new ScpToMessage(getVerbose(), compressed, session, | |||
| list, file, preserveLastModified); | |||
| } else { | |||
| message = new ScpToMessageBySftp(getVerbose(), session, | |||
| @@ -371,7 +382,7 @@ public class Scp extends SSHBase { | |||
| ScpToMessage message = null; | |||
| if (!isSftp) { | |||
| message = | |||
| new ScpToMessage(getVerbose(), session, | |||
| new ScpToMessage(getVerbose(), compressed, session, | |||
| getProject().resolveFile(fromPath), file, | |||
| preserveLastModified); | |||
| } else { | |||
| @@ -115,7 +115,29 @@ public class ScpFromMessage extends AbstractSshMessage { | |||
| final File aLocalFile, | |||
| final boolean recursive, | |||
| final boolean preserveLastModified) { | |||
| super(verbose, session); | |||
| this(verbose, session, aRemoteFile, aLocalFile, recursive, preserveLastModified, false); | |||
| } | |||
| /** | |||
| * Constructor for ScpFromMessage. | |||
| * @param verbose if true log extra information | |||
| * @param session the Scp session to use | |||
| * @param aRemoteFile the remote file name | |||
| * @param aLocalFile the local file | |||
| * @param recursive if true use recursion (-r option to scp) | |||
| * @param preserveLastModified whether to preserve file | |||
| * @param compressed if true use compression (-C option to scp) | |||
| * modification times | |||
| * @since Ant 1.9.8 | |||
| */ | |||
| public ScpFromMessage(boolean verbose, | |||
| Session session, | |||
| String aRemoteFile, | |||
| File aLocalFile, | |||
| boolean recursive, | |||
| boolean preserveLastModified, | |||
| boolean compressed) { | |||
| super(verbose, compressed, session); | |||
| this.remoteFile = aRemoteFile; | |||
| this.localFile = aLocalFile; | |||
| this.isRecursive = recursive; | |||
| @@ -132,6 +154,9 @@ public class ScpFromMessage extends AbstractSshMessage { | |||
| if (isRecursive) { | |||
| command += "-r "; | |||
| } | |||
| if (getCompressed()) { | |||
| command += "-C "; | |||
| } | |||
| command += remoteFile; | |||
| final Channel channel = openExecChannel(command); | |||
| try { | |||
| @@ -61,7 +61,18 @@ public class ScpToMessage extends AbstractSshMessage { | |||
| * @since Ant 1.7 | |||
| */ | |||
| public ScpToMessage(final boolean verbose, final Session session) { | |||
| super(verbose, session); | |||
| this(verbose, false, session); | |||
| } | |||
| /** | |||
| * Constructor for ScpToMessage | |||
| * @param verbose if true do verbose logging | |||
| * @param compressed if true use compression | |||
| * @param session the ssh session to use | |||
| * @since Ant 1.9.8 | |||
| */ | |||
| public ScpToMessage(final boolean verbose, boolean compressed, final Session session) { | |||
| super(verbose, compressed, session); | |||
| } | |||
| /** | |||
| @@ -78,7 +89,26 @@ public class ScpToMessage extends AbstractSshMessage { | |||
| final File aLocalFile, | |||
| final String aRemotePath, | |||
| final boolean preserveLastModified) { | |||
| this(verbose, session, aRemotePath); | |||
| this(verbose, false, session, aLocalFile, aRemotePath, preserveLastModified); | |||
| } | |||
| /** | |||
| * Constructor for a local file to remote. | |||
| * @param verbose if true do verbose logging | |||
| * @param compressed if true use compression | |||
| * @param session the scp session to use | |||
| * @param aLocalFile the local file | |||
| * @param aRemotePath the remote path | |||
| * @param preserveLastModified whether to preserve the last modified timestamps | |||
| * @since Ant 1.9.8 | |||
| */ | |||
| public ScpToMessage(final boolean verbose, | |||
| final boolean compressed, | |||
| final Session session, | |||
| final File aLocalFile, | |||
| final String aRemotePath, | |||
| final boolean preserveLastModified) { | |||
| this(verbose, compressed, session, aRemotePath); | |||
| this.localFile = aLocalFile; | |||
| this.preserveLastModified = preserveLastModified; | |||
| } | |||
| @@ -97,7 +127,26 @@ public class ScpToMessage extends AbstractSshMessage { | |||
| final List aDirectoryList, | |||
| final String aRemotePath, | |||
| final boolean preserveLastModified) { | |||
| this(verbose, session, aRemotePath); | |||
| this(verbose, false, session, aDirectoryList, aRemotePath, preserveLastModified); | |||
| } | |||
| /** | |||
| * Constructor for a local directories to remote. | |||
| * @param verbose if true do verbose logging | |||
| * @param compressed whether to use compression | |||
| * @param session the scp session to use | |||
| * @param aDirectoryList a list of directories | |||
| * @param aRemotePath the remote path | |||
| * @param preserveLastModified whether to preserve the last modified timestamps | |||
| * @since Ant 1.9.8 | |||
| */ | |||
| public ScpToMessage(final boolean verbose, | |||
| final boolean compressed, | |||
| final Session session, | |||
| final List aDirectoryList, | |||
| final String aRemotePath, | |||
| final boolean preserveLastModified) { | |||
| this(verbose, compressed, session, aRemotePath); | |||
| this.directoryList = aDirectoryList; | |||
| this.preserveLastModified = preserveLastModified; | |||
| } | |||
| @@ -142,7 +191,22 @@ public class ScpToMessage extends AbstractSshMessage { | |||
| private ScpToMessage(final boolean verbose, | |||
| final Session session, | |||
| final String aRemotePath) { | |||
| super(verbose, session); | |||
| this(verbose, false, session, aRemotePath); | |||
| } | |||
| /** | |||
| * Constructor for ScpToMessage. | |||
| * @param verbose if true do verbose logging | |||
| * @param compressed if true use compression | |||
| * @param session the scp session to use | |||
| * @param aRemotePath the remote path | |||
| * @since Ant 1.9.8 | |||
| */ | |||
| private ScpToMessage(final boolean verbose, | |||
| final boolean compressed, | |||
| final Session session, | |||
| final String aRemotePath) { | |||
| super(verbose, compressed, session); | |||
| this.remotePath = aRemotePath; | |||
| } | |||
| @@ -187,7 +251,15 @@ public class ScpToMessage extends AbstractSshMessage { | |||
| } | |||
| private void doSingleTransfer() throws IOException, JSchException { | |||
| final String cmd = "scp -t " + (getPreserveLastModified() ? "-p " : "") + remotePath; | |||
| StringBuilder sb = new StringBuilder("scp -t "); | |||
| if (getPreserveLastModified()) { | |||
| sb.append("-p "); | |||
| } | |||
| if (getCompressed()) { | |||
| sb.append("-C "); | |||
| } | |||
| sb.append(remotePath); | |||
| final String cmd = sb.toString(); | |||
| final Channel channel = openExecChannel(cmd); | |||
| try { | |||
| @@ -206,10 +278,15 @@ public class ScpToMessage extends AbstractSshMessage { | |||
| } | |||
| private void doMultipleTransfer() throws IOException, JSchException { | |||
| final Channel channel = | |||
| openExecChannel("scp -r -d -t " | |||
| + (getPreserveLastModified() ? "-p " : "") | |||
| + remotePath); | |||
| StringBuilder sb = new StringBuilder("scp -r -d -t "); | |||
| if (getPreserveLastModified()) { | |||
| sb.append("-p "); | |||
| } | |||
| if (getCompressed()) { | |||
| sb.append("-C "); | |||
| } | |||
| sb.append(remotePath); | |||
| final Channel channel = openExecChannel(sb.toString()); | |||
| try { | |||
| final OutputStream out = channel.getOutputStream(); | |||
| final InputStream in = channel.getInputStream(); | |||