svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.downloader / org.gvsig.downloader.lib / org.gvsig.downloader.lib.impl / src / main / java / org / gvsig / downloader / lib / impl / SEAuthDownloaderTask.java @ 47826
History | View | Annotate | Download (15.6 KB)
1 |
package org.gvsig.downloader.lib.impl; |
---|---|
2 |
|
3 |
import java.io.File; |
4 |
import java.io.IOException; |
5 |
import java.io.InputStream; |
6 |
import java.io.OutputStreamWriter; |
7 |
import java.net.HttpURLConnection; |
8 |
import java.net.SocketTimeoutException; |
9 |
import java.net.URL; |
10 |
import java.util.Objects; |
11 |
import java.util.concurrent.Executor; |
12 |
import org.apache.commons.io.IOUtils; |
13 |
import org.apache.commons.lang3.StringUtils; |
14 |
import org.apache.http.Header; |
15 |
import org.apache.http.HttpEntity; |
16 |
import org.apache.http.HttpResponse; |
17 |
import org.apache.http.auth.AuthenticationException; |
18 |
import org.apache.http.client.ClientProtocolException; |
19 |
import org.apache.http.client.ResponseHandler; |
20 |
import org.apache.http.client.config.RequestConfig; |
21 |
import org.apache.http.client.methods.HttpDelete; |
22 |
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; |
23 |
import org.apache.http.client.methods.HttpGet; |
24 |
import org.apache.http.client.methods.HttpPost; |
25 |
import org.apache.http.client.methods.HttpPut; |
26 |
import org.apache.http.client.methods.HttpRequestBase; |
27 |
import org.apache.http.client.methods.HttpUriRequest; |
28 |
import org.apache.http.conn.ConnectTimeoutException; |
29 |
import org.apache.http.entity.ContentType; |
30 |
import org.apache.http.entity.StringEntity; |
31 |
import org.apache.http.impl.client.CloseableHttpClient; |
32 |
import org.apache.http.impl.client.HttpClientBuilder; |
33 |
import org.gvsig.compat.se.net.downloader.se.AbstractSEDownloaderTask; |
34 |
import org.gvsig.compat.se.net.downloader.se.SEDownloader; |
35 |
import org.gvsig.downloader.DownloaderAuthenticationConfig; |
36 |
import org.gvsig.downloader.DownloaderAuthenticationRequester; |
37 |
import org.gvsig.downloader.DownloaderCredentials; |
38 |
|
39 |
@SuppressWarnings("UseSpecificCatch") |
40 |
final class SEAuthDownloaderTask |
41 |
extends AbstractSEDownloaderTask
|
42 |
implements Runnable { |
43 |
|
44 |
private class DownloaderResponseHandler implements ResponseHandler<Object> { |
45 |
|
46 |
private int status; |
47 |
private HttpResponse response;
|
48 |
|
49 |
public DownloaderResponseHandler() {
|
50 |
this.status = 0; |
51 |
} |
52 |
|
53 |
@Override
|
54 |
public Object handleResponse(HttpResponse response) throws ClientProtocolException, IOException { |
55 |
this.status=response.getStatusLine().getStatusCode();
|
56 |
this.response = response;
|
57 |
try {
|
58 |
HttpEntity entity = response.getEntity(); |
59 |
if(entity == null) { |
60 |
download(null);
|
61 |
} else {
|
62 |
InputStream content = entity.getContent();
|
63 |
download(content); |
64 |
} |
65 |
|
66 |
} catch (IOExceptionWithStatus ex) {
|
67 |
throw ex;
|
68 |
} catch (Exception ex) { |
69 |
throw new IOExceptionWithStatus(this.status, ex.getLocalizedMessage(), ex); |
70 |
} |
71 |
return null; |
72 |
} |
73 |
|
74 |
private int getStatus() { |
75 |
return this.status; |
76 |
} |
77 |
} |
78 |
|
79 |
private static final String METHOD_PUT = "PUT"; |
80 |
private static final String METHOD_POST = "POST"; |
81 |
private static final String METHOD_GET = "GET"; |
82 |
private static final String METHOD_DELETE = "DELETE"; |
83 |
|
84 |
public SEAuthDownloaderTask(SEDownloader downloader, URL url, String data, File dstFile, Object groupID) { |
85 |
super(downloader, url, data, dstFile, groupID);
|
86 |
} |
87 |
|
88 |
private DownloaderManagerImpl getDownloader() {
|
89 |
return (DownloaderManagerImpl) this.downloader; |
90 |
} |
91 |
|
92 |
private DownloaderCredentials getCredentials() {
|
93 |
return this.getDownloader().getCredentials(this.url); |
94 |
} |
95 |
|
96 |
private void addOrReplaceCredentials(DownloaderCredentials credentials) { |
97 |
this.getDownloader().addOrReplaceCredentials(credentials);
|
98 |
} |
99 |
|
100 |
private DownloaderAuthenticationConfig getServiceAuthorizationConfig() {
|
101 |
return this.getDownloader().getAuthenticationConfigurationService(this.url.toString()); |
102 |
} |
103 |
|
104 |
private void authorize() { |
105 |
try {
|
106 |
LOGGER.info("AUTHORIZATION REQUIRED");
|
107 |
DownloaderAuthenticationConfig config = this.getServiceAuthorizationConfig();
|
108 |
if( config == null ) { |
109 |
config = this.getDownloader().requestAutenticationConfig(this.url); |
110 |
if( config == null ) { |
111 |
throw new AuthenticationException("Not service authentication configured for url '"+this.url+"'."); |
112 |
} |
113 |
} |
114 |
DownloaderAuthenticationRequester authorizationRequester = config.create(); |
115 |
if( authorizationRequester == null ) { |
116 |
throw new AuthenticationException("Can't configure service authentication for url '"+this.url+"'."); |
117 |
} |
118 |
LOGGER.info("AUTHORIZATION REQUESTER TYPE: "+authorizationRequester.getProviderName());
|
119 |
if( !authorizationRequester.requestAuthorization(this.getExecutorUI()) ) { |
120 |
return;
|
121 |
} |
122 |
DownloaderCredentials credentials = authorizationRequester.getCredentials(); |
123 |
addOrReplaceCredentials(credentials); |
124 |
LOGGER.info("CREDENTIALS: "+credentials.toString());
|
125 |
} catch (Exception ex) { |
126 |
LOGGER.warn("Can't authorize", ex);
|
127 |
} |
128 |
} |
129 |
|
130 |
private DownloaderResponseHandler executeRequest(HttpUriRequest request) throws IOException { |
131 |
|
132 |
int timeout = getTimeout();
|
133 |
RequestConfig requestConfig = RequestConfig.custom() |
134 |
.setConnectTimeout(timeout) |
135 |
.setConnectionRequestTimeout(timeout) |
136 |
.setSocketTimeout(timeout) |
137 |
.build(); |
138 |
|
139 |
CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build(); |
140 |
DownloaderCredentials credentials = this.getCredentials();
|
141 |
if (credentials==null ) { |
142 |
DownloaderAuthenticationConfig config = this.getServiceAuthorizationConfig();
|
143 |
if( config!=null ) { |
144 |
DownloaderAuthenticationRequester authorizationRequester = config.create(); |
145 |
if( authorizationRequester!=null ) { |
146 |
if( authorizationRequester.requestAuthorization(this.getExecutorUI()) ) { |
147 |
credentials = authorizationRequester.getCredentials(); |
148 |
addOrReplaceCredentials(credentials); |
149 |
request.addHeader("Authorization", credentials.getAuthorizationToken());
|
150 |
} |
151 |
} |
152 |
} |
153 |
} else {
|
154 |
request.addHeader("Authorization", credentials.getAuthorizationToken());
|
155 |
} |
156 |
DownloaderResponseHandler responseHandler = new DownloaderResponseHandler();
|
157 |
|
158 |
LOGGER.info("REQUEST "+request.getMethod()+" "+request.getURI().toString()); |
159 |
LOGGER.info("TIMEOUT "+timeout);
|
160 |
for (Header header : request.getAllHeaders()) {
|
161 |
LOGGER.info(header.getName()+": "+header.getValue());
|
162 |
} |
163 |
if( request instanceof HttpEntityEnclosingRequestBase ) { |
164 |
InputStream content = ((HttpEntityEnclosingRequestBase) request).getEntity().getContent();
|
165 |
LOGGER.info("BODY data "+(StringUtils.join(IOUtils.readLines(content,"utf-8"),"\n"))); |
166 |
} |
167 |
LOGGER.info("DOWNLOAD TO "+Objects.toString(dstFile));
|
168 |
try {
|
169 |
httpClient.execute(request,responseHandler); |
170 |
} catch (SocketTimeoutException|ConnectTimeoutException ex) { |
171 |
LOGGER.info("RESPONSE TIMEOUT");
|
172 |
throw ex;
|
173 |
} catch (Exception ex) { |
174 |
LOGGER.info("RESPONSE ERROR "+ex.getLocalizedMessage());
|
175 |
throw ex;
|
176 |
} |
177 |
LOGGER.info("RESPONSE CODE "+responseHandler.getStatus());
|
178 |
|
179 |
return responseHandler;
|
180 |
} |
181 |
|
182 |
public File send(String method) throws IOException { |
183 |
int status = 500; |
184 |
try {
|
185 |
int numretries = 3; |
186 |
for (int retries = 0; retries < numretries; retries++) { |
187 |
HttpRequestBase request; |
188 |
switch (method.toUpperCase()) {
|
189 |
case METHOD_DELETE:
|
190 |
request = new HttpDelete(url.toURI());
|
191 |
break;
|
192 |
case METHOD_GET:
|
193 |
default:
|
194 |
request = new HttpGet(url.toURI());
|
195 |
break;
|
196 |
} |
197 |
// request.setHeader("User-Agent","Mozilla/5.0 (gvSIG) like Gecko");
|
198 |
request.setHeader("User-Agent","gvSIG-desktop"); |
199 |
request.setHeader("Referer","http://www.gvsig.com"); |
200 |
|
201 |
LOGGER.info("RETRY "+retries);
|
202 |
DownloaderResponseHandler responseHandler = executeRequest(request); |
203 |
status = responseHandler.getStatus(); |
204 |
if(status >= 200 && status < 300) { |
205 |
//2xx success
|
206 |
return this.dstFile; |
207 |
|
208 |
} else if(status >= 300 && status < 400) { |
209 |
// 3xx redirection
|
210 |
throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status); |
211 |
} else if(status == 401 || status == 403) { |
212 |
// "401 Unauthorized" indicates that the request lacks valid authentication credentials
|
213 |
// "403 Forbidden" the client doesn't have permission to access the requested resource
|
214 |
// https://www.permit.io/blog/401-vs-403-error-whats-the-difference
|
215 |
if( retries < numretries-1 ) { |
216 |
authorize(); |
217 |
} |
218 |
} else if(status >= 400 && status < 500) { |
219 |
// 4xx client errors
|
220 |
throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status); |
221 |
} else if(status >= 500 && status < 600) { |
222 |
// 5xx server errors
|
223 |
throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status); |
224 |
} else {
|
225 |
//Unknown
|
226 |
throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status); |
227 |
} |
228 |
} |
229 |
throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' too many retries, last status " + status); |
230 |
|
231 |
} catch (IOExceptionWithStatus ex) {
|
232 |
throw ex;
|
233 |
} catch (Throwable ex) { |
234 |
throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' last status " + status, ex); |
235 |
} |
236 |
} |
237 |
|
238 |
private File send(String method, ContentType contentType, String data) throws IOExceptionWithStatus { |
239 |
int status = 500; |
240 |
try {
|
241 |
int numretries = 3; |
242 |
for (int retries = 0; retries < numretries; retries++) { |
243 |
HttpEntityEnclosingRequestBase request; |
244 |
switch (method.toUpperCase()) {
|
245 |
case METHOD_PUT:
|
246 |
request = new HttpPut(url.toURI());
|
247 |
break;
|
248 |
case METHOD_POST:
|
249 |
default:
|
250 |
request = new HttpPost(url.toURI());
|
251 |
request.setHeader("SOAPAction", "post"); |
252 |
break;
|
253 |
} |
254 |
request.setEntity(new StringEntity(data, contentType));
|
255 |
// request.setHeader("User-Agent","Mozilla/5.0 (gvSIG) like Gecko");
|
256 |
request.setHeader("User-Agent","gvSIG-desktop"); |
257 |
request.setHeader("Referer","http://www.gvsig.com"); |
258 |
request.setHeader("Content-type", contentType.getMimeType());
|
259 |
DownloaderResponseHandler responseHandler = executeRequest(request); |
260 |
status = responseHandler.getStatus(); |
261 |
if(status >= 200 && status < 300) { |
262 |
//2xx success
|
263 |
return this.dstFile; |
264 |
|
265 |
} else if(status >= 300 && status < 400) { |
266 |
// 3xx redirection
|
267 |
throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status); |
268 |
} else if(status == 401 || status == 403) { |
269 |
// "401 Unauthorized" indicates that the request lacks valid authentication credentials
|
270 |
// "403 Forbidden" the client doesn't have permission to access the requested resource
|
271 |
// https://www.permit.io/blog/401-vs-403-error-whats-the-difference
|
272 |
if( retries < numretries-1 ) { |
273 |
authorize(); |
274 |
} |
275 |
} else if(status >= 400 && status < 500) { |
276 |
// 4xx client errors
|
277 |
throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status); |
278 |
} else if(status >= 500 && status < 600) { |
279 |
// 5xx server errors
|
280 |
throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status); |
281 |
} else {
|
282 |
//Unknown
|
283 |
throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status); |
284 |
} |
285 |
} |
286 |
throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' too many retries, last status " + status); |
287 |
|
288 |
} catch (IOExceptionWithStatus ex) {
|
289 |
throw ex;
|
290 |
} catch (Throwable ex) { |
291 |
throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' last status " + status, ex); |
292 |
} |
293 |
} |
294 |
|
295 |
|
296 |
|
297 |
@Override
|
298 |
public void run() { |
299 |
|
300 |
try {
|
301 |
if (data != null) { |
302 |
send(METHOD_POST, ContentType.TEXT_XML, this.data);
|
303 |
} else {
|
304 |
send(METHOD_GET); |
305 |
} |
306 |
postdownload(); |
307 |
|
308 |
} catch (Exception e) { |
309 |
exception(e); |
310 |
} |
311 |
|
312 |
|
313 |
// LOGGER.debug("downloading '" + url.toString() + "' to: " + dstFile.getAbsolutePath());
|
314 |
// if (data != null) {
|
315 |
// LOGGER.debug("using POST, request = " + data);
|
316 |
// }
|
317 |
// int timeout = this.getTimeout();
|
318 |
//
|
319 |
// try {
|
320 |
// OutputStreamWriter os = null;
|
321 |
// HttpURLConnection connection = null;
|
322 |
//
|
323 |
// //If the used protocol is HTTPS
|
324 |
// if (url.getProtocol().equals("https")) {
|
325 |
// disableHttsValidation();
|
326 |
// }
|
327 |
// connection = (HttpURLConnection) url.openConnection();
|
328 |
// connection.setUseCaches(false);
|
329 |
// connection.setRequestProperty("User-Agent", "Mozilla/5.0 (gvSIG) like Gecko");
|
330 |
// connection.setConnectTimeout(timeout);
|
331 |
//
|
332 |
// //If it uses a HTTP POST
|
333 |
// if (data != null) {
|
334 |
// connection.setRequestProperty("SOAPAction", "post");
|
335 |
// connection.setRequestMethod("POST");
|
336 |
// connection.setDoOutput(true);
|
337 |
// connection.setRequestProperty("Content-Type", "text/xml; charset=UTF-8");
|
338 |
// os = new OutputStreamWriter(connection.getOutputStream());
|
339 |
// os.write(data);
|
340 |
// os.flush();
|
341 |
// }
|
342 |
// download(connection.getInputStream());
|
343 |
//
|
344 |
// if (os != null) {
|
345 |
// os.close();
|
346 |
// }
|
347 |
//
|
348 |
// postdownload();
|
349 |
//
|
350 |
// } catch (Exception e) {
|
351 |
// exception(e);
|
352 |
// }
|
353 |
} |
354 |
|
355 |
private Executor getExecutorUI() { |
356 |
return this.downloader.getExecutorUI(); |
357 |
} |
358 |
} |