TAVERNA-893 USe HTTPClient 4 and MessageDigest

Now supports all Java-supported message digests, including
SHA-1 and SHA-256

Local files supported via java.nio Path URIs.

No longer supported are classical URLs
registered with URLConnection, like ftp://


Project: http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/commit/8a82204a
Tree: 
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/tree/8a82204a
Diff: 
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/diff/8a82204a

Branch: refs/heads/master
Commit: 8a82204a930e99c587f5d60c5df2318a2d8290fe
Parents: d6c43d6
Author: Stian Soiland-Reyes <[email protected]>
Authored: Fri Feb 12 17:47:47 2016 +0000
Committer: Stian Soiland-Reyes <[email protected]>
Committed: Fri Feb 12 17:47:47 2016 +0000

----------------------------------------------------------------------
 taverna-download-impl/pom.xml                   |  23 ++-
 .../download/impl/DownloadManagerImpl.java      | 156 +++++++++++++------
 .../download/impl/TestDownloadManagerImpl.java  |  30 +++-
 3 files changed, 147 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/8a82204a/taverna-download-impl/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-download-impl/pom.xml b/taverna-download-impl/pom.xml
index bc50c70..e81a1aa 100644
--- a/taverna-download-impl/pom.xml
+++ b/taverna-download-impl/pom.xml
@@ -16,7 +16,8 @@
     limitations under the License.
 
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
        <modelVersion>4.0.0</modelVersion>
        <parent>
                <groupId>org.apache.taverna.osgi</groupId>
@@ -45,21 +46,33 @@
                        <artifactId>taverna-download-api</artifactId>
                        <version>${project.parent.version}</version>
                </dependency>
-
                <dependency>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                        <version>${log4j.version}</version>
                </dependency>
                <dependency>
-                       <groupId>commons-io</groupId>
-                       <artifactId>commons-io</artifactId>
-                       <version>${commons.io.version}</version>
+                       <groupId>org.apache.httpcomponents</groupId>
+                       <artifactId>httpclient-osgi</artifactId>
+                       <version>${apache.httpclient.version}</version>
+               </dependency>           
+               <dependency>
+                       <!--  Needed by httpclient-osgi -->
+                       <groupId>org.apache.httpcomponents</groupId>
+                       <artifactId>httpcore-osgi</artifactId>
+                       <version>${apache.httpcore.version}</version>
+               </dependency>
+               <dependency>
+                       <!--  Needed by httpclient-osgi -->
+                       <groupId>commons-logging</groupId>
+                       <artifactId>commons-logging</artifactId>
+                       <version>1.2</version>
                </dependency>
                <dependency>
                        <groupId>commons-codec</groupId>
                        <artifactId>commons-codec</artifactId>
                        <version>${commons.codec.version}</version>
                </dependency>
+               
        </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/8a82204a/taverna-download-impl/src/main/java/org/apache/taverna/download/impl/DownloadManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/taverna-download-impl/src/main/java/org/apache/taverna/download/impl/DownloadManagerImpl.java
 
b/taverna-download-impl/src/main/java/org/apache/taverna/download/impl/DownloadManagerImpl.java
index 7292c8e..fa76723 100644
--- 
a/taverna-download-impl/src/main/java/org/apache/taverna/download/impl/DownloadManagerImpl.java
+++ 
b/taverna-download-impl/src/main/java/org/apache/taverna/download/impl/DownloadManagerImpl.java
@@ -16,14 +16,25 @@
  */
 package org.apache.taverna.download.impl;
 
-import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
+import java.io.InputStream;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Locale;
 
+import org.apache.commons.codec.binary.Hex;
 import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.io.FileUtils;
+import org.apache.http.client.fluent.Request;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.VersionInfo;
 import org.apache.log4j.Logger;
 import org.apache.taverna.download.DownloadException;
 import org.apache.taverna.download.DownloadManager;
@@ -33,81 +44,128 @@ import org.apache.taverna.download.DownloadManager;
  */
 public class DownloadManagerImpl implements DownloadManager {
 
+       CloseableHttpClient httpclient = HttpClients.createDefault();
+
        private static final int TIMEOUT = 
Integer.getInteger("taverna.download.timeout.seconds", 30) * 1000;
-       
+
        private static final Logger logger = 
Logger.getLogger(DownloadManagerImpl.class);
 
-       public void download(URL source, File destination) throws 
DownloadException {
+       @Override
+       public void download(URI source, Path destination) throws 
DownloadException {
                download(source, destination, null);
        }
 
-       public void download(URL source, File destination, String 
digestAlgorithm) throws DownloadException {
-               // TODO Use MessageDigest when Java 7 available
-               if (digestAlgorithm != null && !digestAlgorithm.equals("MD5")) {
-                       throw new IllegalArgumentException("Only MD5 
supported");
-               }
-               URL digestSource = null;
+       @Override
+       public void download(URI source, Path destination, String 
digestAlgorithm) throws DownloadException {
+               URI digestSource = null;
                if (digestAlgorithm != null) {
-                       try {
-                               digestSource = new URL(source.toString() + 
mapAlgorithmToFileExtension(digestAlgorithm));
-                       } catch (MalformedURLException e) {
-                               throw new DownloadException("Error creating 
digest URL", e);
-                       }
+                       // Note: Will break with ?download=file.xml kind of URLs
+                       digestSource = source.resolve(source.getPath() + 
mapAlgorithmToFileExtension(digestAlgorithm));
                }
                download(source, destination, digestAlgorithm, digestSource);
        }
 
-       public void download(URL source, File destination, String 
digestAlgorithm, URL digestSource)
+       public String getUserAgent() {
+               Package pack = getClass().getPackage();
+               String httpClientVersion = 
VersionInfo.getUserAgent("Apache-HttpClient", "org.apache.http.client",
+                               Request.class);
+               return "Apache-Taverna-OSGi" + "/" + 
pack.getImplementationVersion() + " (" + httpClientVersion + ")";
+       }
+
+       @Override
+       public void download(URI source, Path destination, String 
digestAlgorithm, URI digestSource)
                        throws DownloadException {
-               // TODO Use MessageDigest when Java 7 available
-               if (digestAlgorithm != null && !digestAlgorithm.equals("MD5")) {
-                       throw new IllegalArgumentException("Only MD5 
supported");
+
+               MessageDigest md = null;
+               if (digestAlgorithm != null) {
+                       try {
+                               md = MessageDigest.getInstance(digestAlgorithm);
+                       } catch (NoSuchAlgorithmException e) {
+                               throw new IllegalArgumentException("Unsupported 
digestAlgorithm: " + digestAlgorithm, e);
+                       }
                }
+
                // download the file
-               File tempFile;
+               Path tempFile;
                try {
-                       tempFile = File.createTempFile("DownloadManager", 
"tmp");
-                       tempFile.deleteOnExit();
-                       logger.info(String.format("Downloading %1$s to %2$s", 
source, tempFile));
-                       FileUtils.copyURLToFile(source, tempFile, TIMEOUT, 
TIMEOUT);
-               } catch (IOException e) {
-                       throw new DownloadException(String.format("Error 
downloading %1$s to %2$s.", source, destination), e);
+                       tempFile = 
Files.createTempFile(destination.getParent(), "." + destination.getFileName(), 
".tmp");
+               } catch (IOException e1) {
+                       // perhaps a permission problem?
+                       throw new DownloadException("Can't create temporary 
file in folder " + destination.getParent(), e1);
                }
+               logger.info(String.format("Downloading %1$s to %2$s", source, 
tempFile));
+               downloadToFile(source, tempFile);
+
                if (digestSource != null) {
                        // download the digest file
-                       File digestFile;
+                       String expectedDigest;
+                       expectedDigest = 
downloadHash(digestSource).trim().toLowerCase(Locale.ROOT);
+                       // check if the digest matches
                        try {
-                               digestFile = 
File.createTempFile("DownloadManager", "tmp");
-                               digestFile.deleteOnExit();
-                               logger.info(String.format("Downloading %1$s to 
%2$s", digestSource, digestFile));
-                               FileUtils.copyURLToFile(digestSource, 
digestFile, TIMEOUT, TIMEOUT);
-                       } catch (IOException e) {
-                               throw new 
DownloadException(String.format("Error checking digest for %1$s.", source), e);
-                       }
-                       // check the digest matches
-                       try {
-                               String digestString1 = DigestUtils.md5Hex(new 
FileInputStream(tempFile));
-                               String digestString2 = 
FileUtils.readFileToString(digestFile);
-                               if (!digestString1.equals(digestString2)) {
-                                       throw new 
DownloadException(String.format(
-                                                       "Error downloading 
file: digsests not equal. (%1$s != %2$s)",
-                                                       digestString1, 
digestString2));
+                               try (InputStream s = 
Files.newInputStream(tempFile)) {
+                                       DigestUtils.updateDigest(md, s);
+                                       String actualDigest = 
Hex.encodeHexString(md.digest());
+                                       if 
(!actualDigest.equals(expectedDigest)) {
+                                               throw new DownloadException(
+                                                               
String.format("Error downloading file: checksum mismatch (%1$s != %2$s)",
+                                                                               
actualDigest, expectedDigest));
+                                       }
                                }
                        } catch (IOException e) {
-                               throw new 
DownloadException(String.format("Error checking digest for %1$s", destination),
-                                               e);
+                               throw new 
DownloadException(String.format("Error checking digest for %1$s", destination), 
e);
                        }
                }
-               // copy file to destination
+               // All fine, move to destination
                try {
                        logger.info(String.format("Copying %1$s to %2$s", 
tempFile, destination));
-                       FileUtils.copyFile(tempFile, destination);
+                       Files.move(tempFile, destination, 
StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
                } catch (IOException e) {
                        throw new DownloadException(String.format("Error 
downloading %1$s to %2$s.", source, destination), e);
                }
 
        }
 
+       private String downloadHash(URI source) throws DownloadException {
+               try {
+                       // We want to handle http/https with HTTPClient
+                       if (source.getScheme().equalsIgnoreCase("http") || 
source.getScheme().equalsIgnoreCase("https")) {
+                               logger.info("Downloading checksum " + source);
+                               return 
Request.Get(source).userAgent(getUserAgent()).connectTimeout(TIMEOUT).socketTimeout(TIMEOUT).execute()
+                                               
.returnContent().asString(StandardCharsets.ISO_8859_1);
+                       } else {
+                               // Try as a supported Path, e.g. file: or 
relative path
+                               try {
+                                       Path path = Paths.get(source);
+                                       return Files.readAllLines(path, 
StandardCharsets.ISO_8859_1).get(0);                            
+                               } catch (FileSystemNotFoundException e) {
+                                       throw new 
DownloadException("Unsupported URL scheme: " + source.getScheme());
+                               }
+                       }
+               } catch (IOException e) {
+                       throw new DownloadException(String.format("Error 
downloading %1$s", source), e);
+               }               
+       }
+       
+       private void downloadToFile(URI source, Path destination) throws 
DownloadException {
+               try {
+                       // We want to handle http/https with HTTPClient
+                       if (source.getScheme().equalsIgnoreCase("http") || 
source.getScheme().equalsIgnoreCase("https")) {
+                               
Request.Get(source).userAgent(getUserAgent()).connectTimeout(TIMEOUT).socketTimeout(TIMEOUT).execute()
+                                               
.saveContent(destination.toFile());
+                       } else {
+                               // Try as a supported Path, e.g. file: or 
relative path
+                               try {
+                                       Path path = Paths.get(source);
+                                       Files.copy(path, destination, 
StandardCopyOption.REPLACE_EXISTING);
+                               } catch (FileSystemNotFoundException e) {
+                                       throw new 
DownloadException("Unsupported URL scheme: " + source.getScheme());
+                               }
+                       }
+               } catch (IOException e) {
+                       throw new DownloadException(String.format("Error 
downloading %1$s to %2$s.", source, destination), e);
+               }
+       }
+
        private String mapAlgorithmToFileExtension(String algorithm) {
                return "." + algorithm.toLowerCase().replaceAll("-", "");
        }

http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/8a82204a/taverna-download-impl/src/test/java/org/apache/taverna/download/impl/TestDownloadManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/taverna-download-impl/src/test/java/org/apache/taverna/download/impl/TestDownloadManagerImpl.java
 
b/taverna-download-impl/src/test/java/org/apache/taverna/download/impl/TestDownloadManagerImpl.java
index a260c59..fbe2dcb 100644
--- 
a/taverna-download-impl/src/test/java/org/apache/taverna/download/impl/TestDownloadManagerImpl.java
+++ 
b/taverna-download-impl/src/test/java/org/apache/taverna/download/impl/TestDownloadManagerImpl.java
@@ -3,7 +3,7 @@ package org.apache.taverna.download.impl;
 import static java.nio.charset.StandardCharsets.US_ASCII;
 import static org.junit.Assert.assertEquals;
 
-import java.net.URL;
+import java.net.URI;
 import java.nio.file.Files;
 import java.nio.file.Path;
 
@@ -15,7 +15,7 @@ public class TestDownloadManagerImpl {
        
        /**
         * This test should remain @Ignored  
-        * as it relies on a third-party web site
+        * as it relies on a web site
         * and should not break the build.
         * 
         * Verifies TAVERNA-893
@@ -28,13 +28,13 @@ public class TestDownloadManagerImpl {
                Path pomFile = Files.createTempFile("test", ".pom");
                // NOTE: The below URL is a Taverna 2 POM - not related to 
                // taverna-plugin-impl
-               URL wrongURL = new 
URL("http://192.185.115.65/~diana/DIANA_plugin_updated/test-plugins/gr/dianatools/diana.services-activity/1.0-SNAPSHOT/diana.services-activity-1.0-SNAPSHOT.pom";);
+               URI wrongURL = 
URI.create("http://192.185.115.65/~diana/DIANA_plugin_updated/test-plugins/gr/dianatools/diana.services-activity/1.0-SNAPSHOT/diana.services-activity-1.0-SNAPSHOT.pom";);
                
                // With this we get an exception - but only because the 
                // 300 erorr page fails the MD5 check
                //dl.download(wrongURL, pomFile.toFile(), "MD5");
                // so we'll try without hashsum
-               dl.download(wrongURL, pomFile.toFile());
+               dl.download(wrongURL, pomFile);
        }
        
        
@@ -47,7 +47,7 @@ public class TestDownloadManagerImpl {
         */
        @Test
        public void downloadLocalFile() throws Exception {
-               Path example = Files.createTempFile("example", ".txt");
+               Path example = Files.createTempFile("test", ".txt");
                Files.write(example, "Hello world".getBytes(US_ASCII)); // No 
newline
                Path exampleMd5 = example.resolveSibling(example.getFileName() 
+ ".md5");
 //             stain@biggie:~$ echo -n "Hello world"|md5sum
@@ -58,11 +58,25 @@ public class TestDownloadManagerImpl {
                
                Path toFile = Files.createTempFile("downloaded", ".txt");
                
-               dl.download(example.toUri().toURL(), toFile.toFile(), "MD5");
+               dl.download(example.toUri(), toFile, "MD5");
                String hello = Files.readAllLines(toFile, US_ASCII).get(0);
                
-               assertEquals("Hello world", hello);
-               
+               assertEquals("Hello world", hello);             
+       }
+
+       /**
+        * This test should remain @Ignored  
+        * as it relies on a web site
+        * and should not break the build.
+        * 
+        */
+       @Ignore
+       @Test
+       public void downloadPomSha1() throws Exception {
+               Path destination = Files.createTempFile("test", "pom");
+               URI source = 
URI.create("https://repo.maven.apache.org/maven2/org/apache/apache/17/apache-17.pom";);
+               DownloadManagerImpl dl = new DownloadManagerImpl();
+               dl.download(source, destination, "SHA-1");
        }
        
 }

Reply via email to