| @@ -253,6 +253,7 @@ Matthew Hawthorne | |||||
| Matthew Inger | Matthew Inger | ||||
| Matthew Kuperus Heun | Matthew Kuperus Heun | ||||
| Matthew Watson | Matthew Watson | ||||
| Matthew Yanos | |||||
| Matthias Bhend | Matthias Bhend | ||||
| Michael Bayne | Michael Bayne | ||||
| Michael Clarke | Michael Clarke | ||||
| @@ -42,6 +42,9 @@ Other changes: | |||||
| converting from AssertionError. | converting from AssertionError. | ||||
| Bugzilla Report 58982 | Bugzilla Report 58982 | ||||
| * <scp> now supports compression via the optional compressed attribute. | |||||
| Bugzilla Report 47552 | |||||
| Changes from Ant 1.9.6 TO Ant 1.9.7 | Changes from Ant 1.9.6 TO Ant 1.9.7 | ||||
| =================================== | =================================== | ||||
| @@ -1041,6 +1041,10 @@ | |||||
| <first>Matthew</first> | <first>Matthew</first> | ||||
| <last>Watson</last> | <last>Watson</last> | ||||
| </name> | </name> | ||||
| <name> | |||||
| <first>Matthew</first> | |||||
| <last>Yanos</last> | |||||
| </name> | |||||
| <name> | <name> | ||||
| <first>Michael</first> | <first>Michael</first> | ||||
| <last>Bayne</last> | <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> | <em>since Ant 1.9.7</em></td> | ||||
| <td align="center" valign="top">No, defaults to 3</td> | <td align="center" valign="top">No, defaults to 3</td> | ||||
| </tr> | </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> | </table> | ||||
| <h3>Parameters specified as nested elements</h3> | <h3>Parameters specified as nested elements</h3> | ||||
| @@ -40,6 +40,7 @@ public abstract class AbstractSshMessage { | |||||
| private final Session session; | private final Session session; | ||||
| private final boolean verbose; | private final boolean verbose; | ||||
| private final boolean compressed; | |||||
| private LogListener listener = new LogListener() { | private LogListener listener = new LogListener() { | ||||
| public void log(final String message) { | public void log(final String message) { | ||||
| // do nothing; | // do nothing; | ||||
| @@ -61,7 +62,19 @@ public abstract class AbstractSshMessage { | |||||
| * @since Ant 1.6.2 | * @since Ant 1.6.2 | ||||
| */ | */ | ||||
| public AbstractSshMessage(final boolean verbose, final Session session) { | 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.verbose = verbose; | ||||
| this.compressed = compressed; | |||||
| this.session = session; | this.session = session; | ||||
| } | } | ||||
| @@ -191,6 +204,15 @@ public abstract class AbstractSshMessage { | |||||
| return verbose; | 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 | * Track progress every 10% if 100kb < filesize < 1mb. For larger | ||||
| * files track progress for every percent transmitted. | * files track progress for every percent transmitted. | ||||
| @@ -54,6 +54,7 @@ public class Scp extends SSHBase { | |||||
| private String fromUri; | private String fromUri; | ||||
| private String toUri; | private String toUri; | ||||
| private boolean preserveLastModified = false; | private boolean preserveLastModified = false; | ||||
| private boolean compressed = false; | |||||
| private List<ResourceCollection> rcs = null; | private List<ResourceCollection> rcs = null; | ||||
| private boolean isFromRemote, isToRemote; | private boolean isFromRemote, isToRemote; | ||||
| private boolean isSftp = false; | private boolean isSftp = false; | ||||
| @@ -111,6 +112,15 @@ public class Scp extends SSHBase { | |||||
| this.isFromRemote = true; | 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 | * Similar to {@link #setTodir setTodir} but explicitly states | ||||
| * that the directory is a local. This is the only way to specify | * 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, | new ScpFromMessage(getVerbose(), session, file, | ||||
| getProject().resolveFile(toPath), | getProject().resolveFile(toPath), | ||||
| fromSshUri.endsWith("*"), | fromSshUri.endsWith("*"), | ||||
| preserveLastModified); | |||||
| preserveLastModified, | |||||
| compressed); | |||||
| } else { | } else { | ||||
| message = | message = | ||||
| new ScpFromMessageBySftp(getVerbose(), session, file, | new ScpFromMessageBySftp(getVerbose(), session, file, | ||||
| @@ -339,7 +350,7 @@ public class Scp extends SSHBase { | |||||
| session = openSession(); | session = openSession(); | ||||
| ScpToMessage message = null; | ScpToMessage message = null; | ||||
| if (!isSftp) { | if (!isSftp) { | ||||
| message = new ScpToMessage(getVerbose(), session, | |||||
| message = new ScpToMessage(getVerbose(), compressed, session, | |||||
| list, file, preserveLastModified); | list, file, preserveLastModified); | ||||
| } else { | } else { | ||||
| message = new ScpToMessageBySftp(getVerbose(), session, | message = new ScpToMessageBySftp(getVerbose(), session, | ||||
| @@ -371,7 +382,7 @@ public class Scp extends SSHBase { | |||||
| ScpToMessage message = null; | ScpToMessage message = null; | ||||
| if (!isSftp) { | if (!isSftp) { | ||||
| message = | message = | ||||
| new ScpToMessage(getVerbose(), session, | |||||
| new ScpToMessage(getVerbose(), compressed, session, | |||||
| getProject().resolveFile(fromPath), file, | getProject().resolveFile(fromPath), file, | ||||
| preserveLastModified); | preserveLastModified); | ||||
| } else { | } else { | ||||
| @@ -115,7 +115,29 @@ public class ScpFromMessage extends AbstractSshMessage { | |||||
| final File aLocalFile, | final File aLocalFile, | ||||
| final boolean recursive, | final boolean recursive, | ||||
| final boolean preserveLastModified) { | 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.remoteFile = aRemoteFile; | ||||
| this.localFile = aLocalFile; | this.localFile = aLocalFile; | ||||
| this.isRecursive = recursive; | this.isRecursive = recursive; | ||||
| @@ -132,6 +154,9 @@ public class ScpFromMessage extends AbstractSshMessage { | |||||
| if (isRecursive) { | if (isRecursive) { | ||||
| command += "-r "; | command += "-r "; | ||||
| } | } | ||||
| if (getCompressed()) { | |||||
| command += "-C "; | |||||
| } | |||||
| command += remoteFile; | command += remoteFile; | ||||
| final Channel channel = openExecChannel(command); | final Channel channel = openExecChannel(command); | ||||
| try { | try { | ||||
| @@ -61,7 +61,18 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
| * @since Ant 1.7 | * @since Ant 1.7 | ||||
| */ | */ | ||||
| public ScpToMessage(final boolean verbose, final Session session) { | 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 File aLocalFile, | ||||
| final String aRemotePath, | final String aRemotePath, | ||||
| final boolean preserveLastModified) { | 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.localFile = aLocalFile; | ||||
| this.preserveLastModified = preserveLastModified; | this.preserveLastModified = preserveLastModified; | ||||
| } | } | ||||
| @@ -97,7 +127,26 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
| final List aDirectoryList, | final List aDirectoryList, | ||||
| final String aRemotePath, | final String aRemotePath, | ||||
| final boolean preserveLastModified) { | 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.directoryList = aDirectoryList; | ||||
| this.preserveLastModified = preserveLastModified; | this.preserveLastModified = preserveLastModified; | ||||
| } | } | ||||
| @@ -142,7 +191,22 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
| private ScpToMessage(final boolean verbose, | private ScpToMessage(final boolean verbose, | ||||
| final Session session, | final Session session, | ||||
| final String aRemotePath) { | 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; | this.remotePath = aRemotePath; | ||||
| } | } | ||||
| @@ -187,7 +251,15 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
| } | } | ||||
| private void doSingleTransfer() throws IOException, JSchException { | 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); | final Channel channel = openExecChannel(cmd); | ||||
| try { | try { | ||||
| @@ -206,10 +278,15 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
| } | } | ||||
| private void doMultipleTransfer() throws IOException, JSchException { | 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 { | try { | ||||
| final OutputStream out = channel.getOutputStream(); | final OutputStream out = channel.getOutputStream(); | ||||
| final InputStream in = channel.getInputStream(); | final InputStream in = channel.getInputStream(); | ||||