Hi,

The attached patch consolidates the Get and Copy tasks.
This lets the Get task user take advantage of the 
features that Copy provides - like filterset, etc.

The copy task recognizes a valid URL as a legal value to 
the file attribute.  If this patch is committed,
perhaps, the Get task can be deprecated?

Magesh
 
Index: Copy.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Copy.java,v
retrieving revision 1.22
diff -w -u -r1.22 Copy.java
--- Copy.java   2001/10/28 21:26:29     1.22
+++ Copy.java   2001/10/29 00:49:44
@@ -70,6 +70,9 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.MalformedURLException;
 import java.util.Vector;
 import java.util.Hashtable;
 import java.util.Enumeration;
@@ -80,6 +83,8 @@
  * than the destination file, or when the destination file does not 
  * exist.  It is possible to explicitly overwrite existing files.</p>
  *
+ * <p>The file attribute can take as its value a valid URL also.</p>
+ *
  * <p>This implementation is based on Arnout Kuiper's initial design
  * document, the following mailing list discussions, and the 
  * copyfile/copydir tasks.</p>
@@ -90,15 +95,20 @@
  * @author <a href="mailto:[EMAIL PROTECTED]">Magesh Umasankar</a>
  */
 public class Copy extends Task {
+    protected String fileStr = null; // the source file string
+    protected URL url = null;        // the source url
     protected File file = null;     // the source file 
     protected File destFile = null; // the destination file 
     protected File destDir = null;  // the destination directory
     protected Vector filesets = new Vector();
+    private String username = null;
+    private String password = null;
 
     protected boolean filtering = false;
     protected boolean preserveLastModified = false;
     protected boolean forceOverwrite = false;
     protected boolean flatten = false;
+    protected boolean isURLAllowed = false;
     protected int verbosity = Project.MSG_VERBOSE;
     protected boolean includeEmpty = true;
 
@@ -111,6 +121,7 @@
     
     public Copy() {
         fileUtils = FileUtils.newFileUtils();
+        isURLAllowed = true;
     }
 
     protected FileUtils getFileUtils() {return fileUtils;}
@@ -118,8 +129,8 @@
     /**
      * Sets a single source file to copy.
      */
-    public void setFile(File file) {
-        this.file = file;
+    public void setFile(String file) {
+        fileStr = file;
     }
 
     /**
@@ -224,6 +235,24 @@
     }
 
     /**
+     * Username for basic auth.
+     *
+     * @param username username for authentication
+     */
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    /**
+     * password for the basic auth.
+     *
+     * @param password password for authentication
+     */
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    /**
      * Performs the copy operation.
      */
     public void execute() throws BuildException {
@@ -250,6 +279,37 @@
                 log(message);
                 throw new BuildException(message);
             }
+        } else if (url != null) {
+            if (destFile == null) {
+                String fileName = url.getFile();
+                if (fileName.endsWith("/")) {
+                    throw new BuildException(
+                        "Unable to form destination file name. " +
+                        "Use tofile instead.");
+                }
+                destFile = new File(destDir, fileName);
+                if (!destFile.isFile()) {
+                    throw new BuildException(
+                        "Destination file name represents a directory");
+                }
+            }
+            try {
+                URLConnection urlconn = url.openConnection();
+                if (urlconn != null &&
+                       (forceOverwrite ||
+                       !destFile.exists() ||
+                       urlconn.getLastModified() == 0 ||
+                       urlconn.getLastModified() > destFile.lastModified())) {
+                    fileCopyMap.put(url.toString(), 
destFile.getAbsolutePath());
+                } else {
+                    log(url + " omitted as " + destFile + " is up to date.",
+                        Project.MSG_VERBOSE);
+                }
+            } catch (IOException ioe) {
+                String message = ioe.getMessage();
+                log(message);
+                throw new BuildException(message);
+            }
         }
 
         // deal with the filesets
@@ -284,9 +344,24 @@
      * of attributes.
      */
     protected void validateAttributes() throws BuildException {
+        if (fileStr != null) {
+            try {
+                this.url = new URL(fileStr);
+            } catch (MalformedURLException e) {
+                this.file = project.resolveFile(fileStr);
+            }
+        }
+
         if (file == null && filesets.size() == 0) {
-            throw new BuildException("Specify at least one source - a file or 
a fileset.");
+            String message = "Specify at least one source - a file or a 
fileset.";
+            if (isURLAllowed) {
+                if (url == null) {
+                    throw new BuildException(message);
         }
+            } else {
+                throw new BuildException(message);
+            }
+        }
 
         if (destFile != null && destDir != null) {
             throw new BuildException("Only one of destfile and destdir may be 
set.");
@@ -327,7 +402,6 @@
         if (destFile != null) {
             destDir = new File(destFile.getParent());   // be 1.1 friendly
         }
-
     }
 
     /**
@@ -407,7 +481,8 @@
                         
executionFilters.addFilterSet((FilterSet)filterEnum.nextElement());
                     }
                     fileUtils.copyFile(fromFile, toFile, executionFilters,
-                                       forceOverwrite, preserveLastModified);
+                                       forceOverwrite, preserveLastModified,
+                                       username, password);
                 } catch (IOException ioe) {
                     String msg = "Failed to copy " + fromFile + " to " + toFile
                         + " due to " + ioe.getMessage();
@@ -438,5 +513,4 @@
             }
         }
     }
-
 }







cvs diff -w -u Move.java 
Index: Move.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Move.java,v
retrieving revision 1.9
diff -w -u -r1.9 Move.java
--- Move.java   2001/10/28 21:26:29     1.9
+++ Move.java   2001/10/29 00:52:29
@@ -87,6 +87,7 @@
     public Move() {
         super();
         forceOverwrite = true;
+        isURLAllowed = false;
     }
 
 //************************************************************************








Index: FileUtils.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/util/FileUtils.java,v
retrieving revision 1.7
diff -w -u -r1.7 FileUtils.java
--- FileUtils.java      2001/10/28 21:27:20     1.7
+++ FileUtils.java      2001/10/29 00:48:43
@@ -60,9 +60,17 @@
 import java.io.FileReader;
 import java.io.BufferedWriter;
 import java.io.FileWriter;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
 import java.util.StringTokenizer;
 import java.util.Stack;
 
@@ -74,17 +82,18 @@
  * This class also encapsulates methods which allow Files to be
  * refered to using abstract path names which are translated to native
  * system file paths at runtime as well as copying files or setting
- * there last modification time.
+ * their last modification time.
  *
  * @author [EMAIL PROTECTED]
  * @author <a href="mailto:[EMAIL PROTECTED]">Conor MacNeill</a>
  * @author <a href="mailto:[EMAIL PROTECTED]">Stefan Bodewig</a> 
+ * @author <a href="mailto:[EMAIL PROTECTED]">Magesh Umasankar</a>
  */
  
 public class FileUtils {
     private static Object lockReflection = new Object();
     private static java.lang.reflect.Method setLastModified = null;
-
+    private static final int BUFFER_SIZE = 64512; //63 * 1024
     /**
      * Factory method.
      */
@@ -144,9 +153,32 @@
     public void copyFile(String sourceFile, String destFile, 
FilterSetCollection filters,
                          boolean overwrite, boolean preserveLastModified)
         throws IOException {
+        copyFile(sourceFile, destFile, filters, overwrite,
+            preserveLastModified, null, null);
+        }
+
+     /**
+     * Convienence method to copy a file from a source to a
+     * destination specifying if token filtering must be used, if
+     * source files may overwrite newer destination files and the
+     * last modified time of <code>destFile</code> file should be made equal
+     * to the last modified time of <code>sourceFile</code>.
+     *
+     * @throws IOException
+     */
+    public void copyFile(String sourceFile, String destFile, 
FilterSetCollection filters,
+                         boolean overwrite, boolean preserveLastModified,
+                         String username, String password)
+        throws IOException {
+        try {
+            URL srcUrl = new URL(sourceFile);
+            copyURL(srcUrl, new File(destFile), filters,
+                     overwrite, preserveLastModified, username, password);
+        } catch (MalformedURLException e) {
         copyFile(new File(sourceFile), new File(destFile), filters, 
                  overwrite, preserveLastModified);
     }
+    }
 
     /**
      * Convienence method to copy a file from a source to a destination.
@@ -196,23 +228,101 @@
         
         if (overwrite || !destFile.exists() ||
             destFile.lastModified() < sourceFile.lastModified()) {
-
             if (destFile.exists() && destFile.isFile()) {
                 destFile.delete();
             }
+            // ensure that parent dir of dest file exists!
+            // not using getParentFile method to stay 1.1 compat
+            File parent = new File(destFile.getParent());
+            if (!parent.exists()) {
+                parent.mkdirs();
+            }
+            FileInputStream sourceStream = new FileInputStream(sourceFile);
+            FileOutputStream destStream = new FileOutputStream(destFile);
+            copyStream(sourceStream, destStream, filters, sourceFile.length());
+            if (preserveLastModified) {
+                setFileLastModified(destFile, sourceFile.lastModified());
+            }
+            sourceStream.close();
+            destStream.close();
+        }
+    }
+
+    public void copyURL(URL sourceURL, File destFile,
+                         FilterSetCollection filters, boolean overwrite,
+                         boolean preserveLastModified, String username,
+                         String password)
+        throws IOException {
 
+        URLConnection conn;
+        conn = sourceURL.openConnection();
+        conn.setDoInput(true);
+        conn.setDoOutput(false);
+        conn.setUseCaches(false);
+        conn.setAllowUserInteraction(false);
+        if (username != null || password != null) {
+            String up = username + ":" + password;
+            String encoding;
+            // check to see if sun's Base64 encoder is available.
+            try {
+                sun.misc.BASE64Encoder encoder = (sun.misc.BASE64Encoder)
+                    Class.forName("sun.misc.BASE64Encoder").newInstance();
+                encoding = encoder.encode(up.getBytes());
+            } catch (Exception ex) { // sun's base64 encoder isn't available
+                Base64Converter encoder = new Base64Converter();
+                encoding = encoder.encode(up.getBytes());
+            }
+            conn.setRequestProperty ("Authorization", "Basic " + encoding);
+        }
+        conn.connect();
+        if(conn instanceof HttpURLConnection)  {
+            HttpURLConnection httpConnection=(HttpURLConnection) conn;
+            // test for 401 result (HTTP only)
+            if(httpConnection.getResponseCode() ==
+                    HttpURLConnection.HTTP_UNAUTHORIZED)  {
+                throw new IOException("Not authorized.");
+            }
+        }
+        long length = conn.getContentLength();
+        long lastModified = conn.getLastModified();
+        if (overwrite || !destFile.exists() ||
+            lastModified == 0 ||
+            destFile.lastModified() < lastModified) {
+            if (destFile.exists() && destFile.isFile()) {
+                destFile.delete();
+            }
             // ensure that parent dir of dest file exists!
             // not using getParentFile method to stay 1.1 compat
             File parent = new File(destFile.getParent());
             if (!parent.exists()) {
                 parent.mkdirs();
             }
+            InputStream sourceStream = conn.getInputStream();
+            FileOutputStream destStream = new FileOutputStream(destFile);
+            copyStream(sourceStream, destStream, filters, length);
+            if (preserveLastModified && lastModified != 0) {
+                setFileLastModified(destFile, lastModified);
+            }
+            sourceStream.close();
+            destStream.close();
+        }
+    }
 
+    public void copyStream(InputStream sourceStream, OutputStream destStream,
+                         FilterSetCollection filters)
+        throws IOException {
+            copyStream(sourceStream, destStream, filters, -1);
+    }
+
+    public void copyStream(InputStream sourceStream, OutputStream destStream,
+                         FilterSetCollection filters, long length)
+        throws IOException {
             if (filters != null && filters.hasFilters()) {
-                BufferedReader in = new BufferedReader(new 
FileReader(sourceFile));
-                BufferedWriter out = new BufferedWriter(new 
FileWriter(destFile));
+            BufferedReader in = new BufferedReader(
+                                    new InputStreamReader(sourceStream));
+            BufferedWriter out = new BufferedWriter(
+                                    new OutputStreamWriter(destStream));
 
-                int length;
                 String newline = null;
                 String line = in.readLine();
                 while (line != null) {
@@ -225,28 +335,62 @@
                     }
                     line = in.readLine();
                 }
-
                 out.close();
                 in.close();
             } else {
-                FileInputStream in = new FileInputStream(sourceFile);
-                FileOutputStream out = new FileOutputStream(destFile);
-
-                byte[] buffer = new byte[8 * 1024];
-                int count = 0;
-                do {
-                    out.write(buffer, 0, count);
-                    count = in.read(buffer, 0, buffer.length);
-                } while (count != -1);
-
-                in.close();
-                out.close();
+            byte[] buffer = null;
+            if (length <= 0) {
+                int chunkSize = BUFFER_SIZE;
+                buffer = new byte[chunkSize];
+                while (true) {
+                    int bytesRead = readChunk(sourceStream, buffer, 0,
+                                              chunkSize);
+                    if (bytesRead > 0) {
+                        destStream.write(buffer, 0, bytesRead);
+                    } else {
+                        break;
             }
+                }
+            } else {
+                int chunkSize = (int) Math.min(BUFFER_SIZE, length);
+                long chunks = length/chunkSize;
+                int lastChunkSize = (int) (length%chunkSize);
+                buffer = new byte[chunkSize];
+                for (long chunkNo = 0; chunkNo < chunks; chunkNo++) {
+                    int bytesRead = readChunk(sourceStream, buffer, 0,
+                                              chunkSize);
+                    if (bytesRead != chunkSize) {
+                        throw new IOException(
+                            "Unable to read expected number of bytes");
+                    }
+                    destStream.write(buffer);
+                }
+                if (lastChunkSize > 0) {
+                    int bytesRead = readChunk(sourceStream, buffer, 0,
+                                              lastChunkSize);
+                    if (bytesRead != lastChunkSize) {
+                        throw new IOException(
+                            "Unable to read expected number of bytes");
+                    }
+                    destStream.write(buffer, 0, lastChunkSize);
+                }
+            }
+        }
+    }
 
-            if (preserveLastModified) {
-                setFileLastModified(destFile, sourceFile.lastModified());
+    protected int readChunk(InputStream sourceStream, byte[] buffer,
+                            int offset, int length) throws IOException {
+        int totalBytesRead = 0;
+        while (totalBytesRead < length) {
+            int bytesRead = sourceStream.read(buffer,
+                                              offset + totalBytesRead,
+                                              length - totalBytesRead);
+            if (bytesRead < 0) {
+                break;
             }
+            totalBytesRead += bytesRead;
         }
+        return totalBytesRead;
     }
 
     /**
@@ -466,6 +610,76 @@
             path = path.replace('/', '\\');
         }
         return new File(path);
+    }
+
+    class  Base64Converter {
+
+        public final char [ ]  alphabet = {
+        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',   //  0 to  7
+        'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',   //  8 to 15
+        'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',   // 16 to 23
+        'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',   // 24 to 31
+        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',   // 32 to 39
+        'o', 'p', 'q', 'r', 's', 't', 'u', 'v',   // 40 to 47
+        'w', 'x', 'y', 'z', '0', '1', '2', '3',   // 48 to 55
+        '4', '5', '6', '7', '8', '9', '+', '/' }; // 56 to 63
+
+        public String  encode ( String  s ) {
+            return encode ( s.getBytes ( ) );
+        }
+
+        public String  encode ( byte [ ]  octetString ) {
+            int  bits24;
+            int  bits6;
+
+            char [ ]  out
+                = new char [ ( ( octetString.length - 1 ) / 3 + 1 ) * 4 ];
+
+            int outIndex = 0;
+            int i        = 0;
+
+            while ( ( i + 3 ) <= octetString.length ) {
+                // store the octets
+                bits24=( octetString [ i++ ] & 0xFF ) << 16;
+                bits24 |=( octetString [ i++ ] & 0xFF ) << 8;
+
+                bits6=( bits24 & 0x00FC0000 )>> 18;
+                out [ outIndex++ ] = alphabet [ bits6 ];
+                bits6 = ( bits24 & 0x0003F000 ) >> 12;
+                out [ outIndex++ ] = alphabet [ bits6 ];
+                bits6 = ( bits24 & 0x00000FC0 ) >> 6;
+                out [ outIndex++ ] = alphabet [ bits6 ];
+                bits6 = ( bits24 & 0x0000003F );
+                out [ outIndex++ ] = alphabet [ bits6 ];
+            }
+
+            if ( octetString.length - i == 2 ) {
+                // store the octets
+                bits24  = ( octetString [ i     ] & 0xFF ) << 16;
+                bits24 |=( octetString [ i + 1 ] & 0xFF ) << 8;
+                bits6=( bits24 & 0x00FC0000 )>> 18;
+                out [ outIndex++ ] = alphabet [ bits6 ];
+                bits6 = ( bits24 & 0x0003F000 ) >> 12;
+                out [ outIndex++ ] = alphabet [ bits6 ];
+                bits6 = ( bits24 & 0x00000FC0 ) >> 6;
+                out [ outIndex++ ] = alphabet [ bits6 ];
+
+                // padding
+                out [ outIndex++ ] = '=';
+            } else if ( octetString.length - i == 1 ) {
+                // store the octets
+                bits24 = ( octetString [ i ] & 0xFF ) << 16;
+                bits6=( bits24 & 0x00FC0000 )>> 18;
+                out [ outIndex++ ] = alphabet [ bits6 ];
+                bits6 = ( bits24 & 0x0003F000 ) >> 12;
+                out [ outIndex++ ] = alphabet [ bits6 ];
+
+                // padding
+                out [ outIndex++ ] = '=';
+                out [ outIndex++ ] = '=';
+            }
+            return new String ( out );
+        }
     }
 }
 






Index: copy.html
===================================================================
RCS file: /home/cvspublic/jakarta-ant/docs/manual/CoreTasks/copy.html,v
retrieving revision 1.4
diff -w -u -r1.4 copy.html
--- copy.html   2001/10/12 08:19:40     1.4
+++ copy.html   2001/10/29 00:47:25
@@ -24,7 +24,7 @@
   </tr>
   <tr>
     <td valign="top">file</td>
-    <td valign="top">The file to copy.</td>
+    <td valign="top">The file to copy (URLs allowed).</td>
     <td valign="top" align="center">One of either <var>file</var> or 
     at least one nested fileset element.</td>
   </tr>
@@ -74,6 +74,16 @@
           Defaults to &quot;yes&quot;.</td>
         <td valign="top" align="center">No</td>
   </tr>
+  <tr>
+    <td valign="top">username</td>
+    <td valign="top">Username for basic authentication.  Used if file 
attribute is a URL.</td>
+    <td valign="top" align="center">No</td>
+  </tr>
+  <tr>
+    <td valign="top">password</td>
+    <td valign="top">Password for basic authentication.  Used if file 
attribute is a URL.</td>
+    <td valign="top" align="center">No</td>
+  </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
  
@@ -97,6 +107,10 @@
 <pre>
   &lt;copy file=&quot;myfile.txt&quot; tofile=&quot;mycopy.txt&quot;/&gt;
 </pre>
+<p><b>Copy a single file using a url</b></p>
+<pre>
+  &lt;copy file=&quot;ftp://ftp.keystealth.org/pub/gnu/README&quot; 
tofile=&quot;README.txt&quot;/&gt;
+</pre>
 <p><b>Copy a file to a directory</b></p>
 <pre>
   &lt;copy file=&quot;myfile.txt&quot; todir=&quot;../some/dir/tree&quot;/&gt;
@@ -135,6 +149,15 @@
     &lt;fileset dir=&quot;src_dir&quot; /&gt;
     &lt;filterset&gt;
       &lt;filter token=&quot;TITLE&quot; value=&quot;Foo Bar&quot; /&gt;
+    &lt;/filterset&gt;
+  &lt;/copy&gt;
+</pre>
+
+<p><b>Copy a single file using a http url</b></p>
+<pre>
+  &lt;copy file=&quot;http://jakarta.apache.org/index.html&quot; 
todir=&quot;/tmp&quot;&gt;
+    &lt;filterset begintoken=&quot;#&quot; endtoken=&quot;6&quot;&gt;
+      &lt;filter token=&quot;525D7&quot; value=&quot;#CCCCCC&quot; /&gt;
     &lt;/filterset&gt;
   &lt;/copy&gt;
 </pre>


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to