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