1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package de.pdark.dsmp;
17
18 import java.io.BufferedOutputStream;
19 import java.io.File;
20 import java.io.FileOutputStream;
21 import java.io.FileReader;
22 import java.io.FileWriter;
23 import java.io.IOException;
24 import java.io.OutputStream;
25 import java.net.URL;
26
27 import org.apache.commons.httpclient.Credentials;
28 import org.apache.commons.httpclient.Header;
29 import org.apache.commons.httpclient.HostConfiguration;
30 import org.apache.commons.httpclient.HttpClient;
31 import org.apache.commons.httpclient.HttpStatus;
32 import org.apache.commons.httpclient.UsernamePasswordCredentials;
33 import org.apache.commons.httpclient.auth.AuthScope;
34 import org.apache.commons.httpclient.methods.GetMethod;
35 import org.apache.log4j.Logger;
36
37 /**
38 * Download a file via a proxy server and store it somewhere.
39 *
40 * @author digulla
41 *
42 */
43 public class ProxyDownload
44 {
45 public static final Logger log = Logger.getLogger(ProxyDownload.class);
46 private final URL url;
47 private final File dest;
48
49 /**
50 * Download <code>url</code> to <code>dest</code>.
51 *
52 * <p>If the directory to store <code>dest</code> doesn't exist,
53 * it will be created.
54 *
55 * @param url The resource to download
56 * @param dest Where to store it.
57 */
58 public ProxyDownload (URL url, File dest)
59 {
60 this.url = url;
61 this.dest = dest;
62 }
63
64 /**
65 * Create the neccessary paths to store the destination file.
66 *
67 * @throws IOException
68 */
69 public void mkdirs () throws IOException
70 {
71 File parent = dest.getParentFile();
72 IOUtils.mkdirs (parent);
73 }
74
75 /**
76 * Do the download.
77 *
78 * @throws IOException
79 * @throws DownloadFailed
80 */
81 public void download () throws IOException, DownloadFailed
82 {
83 if (!Config.isAllowed(url))
84 {
85 throw new DownloadFailed ("HTTP/1.1 "+HttpStatus.SC_FORBIDDEN+" Download denied by rule in DSMP config");
86 }
87
88
89
90
91
92
93 File statusFile = new File (dest.getAbsolutePath()+".status");
94 if (statusFile.exists())
95 {
96 try
97 {
98 FileReader r = new FileReader (statusFile);
99 char[] buffer = new char[(int)statusFile.length()];
100 int len = r.read (buffer);
101 r.close ();
102 String status = new String (buffer, 0, len);
103 throw new DownloadFailed (status);
104 }
105 catch (IOException e)
106 {
107 log.warn ("Error writing 'File not found'-Status to "+statusFile.getAbsolutePath(), e);
108 }
109 }
110
111 mkdirs();
112
113 HttpClient client = new HttpClient();
114
115 String msg = "";
116 if (Config.useProxy(url))
117 {
118 Credentials defaultcreds = new UsernamePasswordCredentials(Config.getProxyUsername(), Config.getProxyPassword());
119 AuthScope scope = new AuthScope(Config.getProxyHost(), Config.getProxyPort(), AuthScope.ANY_REALM);
120 HostConfiguration hc = new HostConfiguration ();
121 hc.setProxy(Config.getProxyHost(), Config.getProxyPort());
122 client.setHostConfiguration(hc);
123 client.getState().setProxyCredentials(scope, defaultcreds);
124 msg = "via proxy ";
125 }
126 log.info("Downloading "+msg+"to "+dest.getAbsolutePath());
127
128 GetMethod get = new GetMethod(url.toString());
129 get.setFollowRedirects(true);
130 try
131 {
132 int status = client.executeMethod( get );
133
134 log.info ("Download status: "+status);
135 if (0 == 1 && log.isDebugEnabled())
136 {
137 Header[] header = get.getResponseHeaders();
138 for (int i=0; i<header.length; i++)
139 log.debug (header[i].toString().trim());
140 }
141
142 log.info ("Content: "+valueOf (get.getResponseHeader("Content-Length"))+" bytes; "
143 +valueOf (get.getResponseHeader("Content-Type")));
144
145 if (status != HttpStatus.SC_OK)
146 {
147
148 if (status == HttpStatus.SC_NOT_FOUND)
149 {
150 try
151 {
152 FileWriter w = new FileWriter (statusFile);
153 w.write (get.getStatusLine().toString());
154 w.close ();
155 }
156 catch (IOException e)
157 {
158 log.warn ("Error writing 'File not found'-Status to "+statusFile.getAbsolutePath(), e);
159 }
160 }
161 throw new DownloadFailed (get);
162 }
163
164 File dl = new File (dest.getAbsolutePath()+".new");
165 OutputStream out = new BufferedOutputStream (new FileOutputStream (dl));
166 IOUtils.copy (get.getResponseBodyAsStream(), out);
167 out.close ();
168
169 File bak = new File (dest.getAbsolutePath()+".bak");
170 if (bak.exists())
171 bak.delete();
172 if (dest.exists())
173 dest.renameTo(bak);
174 dl.renameTo(dest);
175 }
176 finally
177 {
178 get.releaseConnection();
179 }
180 }
181
182 private String valueOf (Header responseHeader)
183 {
184 return responseHeader == null ? "unknown" : responseHeader.getValue();
185 }
186 }