org.moxie.proxy.connection.ProxyDownload.java Source code

Java tutorial

Introduction

Here is the source code for org.moxie.proxy.connection.ProxyDownload.java

Source

/*
 * Copyright 2002-2005 The Apache Software Foundation.
 * Copyright 2012 James Moger
 * 
 * Licensed 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.moxie.proxy.connection;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.util.DateUtil;
import org.moxie.Proxy;
import org.moxie.proxy.ProxyConfig;

/**
 * Download a file via a proxy server and store it somewhere.
 * 
 * @author digulla
 * 
 */
public class ProxyDownload {
    public static final Logger log = Logger.getLogger(ProxyDownload.class.getSimpleName());
    private final ProxyConfig config;
    private final URL url;
    private final File dest;

    /**
     * Download <code>url</code> to <code>dest</code>.
     * 
     * <p>
     * If the directory to store <code>dest</code> doesn't exist, it will be
     * created.
     * 
     * @param url
     *            The resource to download
     * @param dest
     *            Where to store it.
     */
    public ProxyDownload(ProxyConfig config, URL url, File dest) {
        this.config = config;
        this.url = url;
        this.dest = dest;
    }

    /**
     * Do the download.
     * 
     * @throws IOException
     * @throws DownloadFailed
     */
    public void download() throws IOException, DownloadFailed {
        if (!config.isAllowed(url)) {
            throw new DownloadFailed(
                    "HTTP/1.1 " + HttpStatus.SC_FORBIDDEN + " Download denied by rule in Moxie Proxy config");
        }

        HttpClient client = new HttpClient();
        String userAgent = config.getUserAgent();
        if (userAgent != null && userAgent.trim().length() > 0) {
            client.getParams().setParameter(HttpMethodParams.USER_AGENT, userAgent);
        }

        String msg = "";
        if (config.useProxy(url)) {
            Proxy proxy = config.getProxy(url);
            Credentials defaultcreds = new UsernamePasswordCredentials(proxy.username, proxy.password);
            AuthScope scope = new AuthScope(proxy.host, proxy.port, AuthScope.ANY_REALM);
            HostConfiguration hc = new HostConfiguration();
            hc.setProxy(proxy.host, proxy.port);
            client.setHostConfiguration(hc);
            client.getState().setProxyCredentials(scope, defaultcreds);
            msg = "via proxy ";
        }
        log.info("Downloading " + msg + "to " + dest.getAbsolutePath());

        GetMethod get = new GetMethod(url.toString());
        get.setFollowRedirects(true);
        try {
            int status = client.executeMethod(get);

            log.info("Download status: " + status);
            if (status == 1 && log.isLoggable(Level.FINE)) {
                Header[] header = get.getResponseHeaders();
                for (int i = 0; i < header.length; i++)
                    log.fine(header[i].toString().trim());
            }

            log.info("Content: " + valueOf(get.getResponseHeader("Content-Length")) + " bytes; "
                    + valueOf(get.getResponseHeader("Content-Type")));

            if (status != HttpStatus.SC_OK) {
                throw new DownloadFailed(get);
            }

            // Make sure the temporary file is created in
            // the destination folder, otherwise
            // dl.renameTo(dest) might not work
            // for example if you have a separate /tmp partition
            // on Linux
            File destinationFolder = dest.getParentFile();
            dest.getParentFile().mkdirs();
            File dl = File.createTempFile("moxie-", ".tmp", destinationFolder);
            OutputStream out = new BufferedOutputStream(new FileOutputStream(dl));
            copy(get.getResponseBodyAsStream(), out);
            out.close();

            // create folder structure after successful download
            // - no, we create it before the download!
            //dest.getParentFile().mkdirs();

            if (dest.exists()) {
                dest.delete();
            }
            dl.renameTo(dest);

            // preserve last-modified, if possible
            try {
                Header lastModified = get.getResponseHeader("Last-Modified");
                if (lastModified != null) {
                    Date date = DateUtil.parseDate(lastModified.getValue());
                    dest.setLastModified(date.getTime());
                }
            } catch (Exception e) {
                log.log(Level.WARNING, "could not parse \"last-modified\" for " + url, e);
            }
        } finally {
            get.releaseConnection();
        }
    }

    void copy(InputStream in, OutputStream out) throws IOException {
        byte[] buffer = new byte[1024 * 100];
        int len;

        while ((len = in.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
        out.flush();
    }

    private String valueOf(Header responseHeader) {
        return responseHeader == null ? "unknown" : responseHeader.getValue();
    }
}