org.apache.taverna.download.impl.DownloadManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.taverna.download.impl.DownloadManagerImpl.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.taverna.download.impl;

import java.io.IOException;
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.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;

/**
 *
 */
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);

    @Override
    public void download(URI source, Path destination) throws DownloadException {
        download(source, destination, null);
    }

    @Override
    public void download(URI source, Path destination, String digestAlgorithm) throws DownloadException {
        URI digestSource = null;
        if (digestAlgorithm != null) {
            // Note: Will break with ?download=file.xml kind of URLs
            digestSource = source.resolve(source.getPath() + mapAlgorithmToFileExtension(digestAlgorithm));
        }
        download(source, destination, digestAlgorithm, 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 {

        MessageDigest md = null;
        if (digestAlgorithm != null) {
            try {
                md = MessageDigest.getInstance(digestAlgorithm);
            } catch (NoSuchAlgorithmException e) {
                throw new IllegalArgumentException("Unsupported digestAlgorithm: " + digestAlgorithm, e);
            }
        }

        // download the file
        Path tempFile;
        try {
            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
            String expectedDigest;
            expectedDigest = downloadHash(digestSource).trim().toLowerCase(Locale.ROOT);
            // check if the digest matches
            try {
                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);
            }
        }
        // All fine, move to destination
        try {
            logger.info(String.format("Copying %1$s to %2$s", 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("-", "");
    }

}