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 | 47821 | jjdelcerro | package org.gvsig.downloader.lib.impl; |
---|---|---|---|
2 | 41528 | jjdelcerro | |
3 | import java.io.File; |
||
4 | 47821 | jjdelcerro | import java.io.IOException; |
5 | import java.io.InputStream; |
||
6 | 41528 | jjdelcerro | import java.io.OutputStreamWriter; |
7 | import java.net.HttpURLConnection; |
||
8 | 47826 | fdiaz | import java.net.SocketTimeoutException; |
9 | 41528 | jjdelcerro | import java.net.URL; |
10 | 47821 | jjdelcerro | import java.util.Objects; |
11 | 47824 | fdiaz | import java.util.concurrent.Executor; |
12 | 47821 | jjdelcerro | 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 | 47826 | fdiaz | import org.apache.http.client.config.RequestConfig; |
21 | 47821 | jjdelcerro | 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 | 47826 | fdiaz | import org.apache.http.conn.ConnectTimeoutException; |
29 | 47821 | jjdelcerro | 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 | 47824 | fdiaz | import org.gvsig.compat.se.net.downloader.se.SEDownloader; |
35 | 47821 | jjdelcerro | import org.gvsig.downloader.DownloaderAuthenticationConfig; |
36 | import org.gvsig.downloader.DownloaderAuthenticationRequester; |
||
37 | import org.gvsig.downloader.DownloaderCredentials; |
||
38 | 41528 | jjdelcerro | |
39 | 47821 | jjdelcerro | @SuppressWarnings("UseSpecificCatch") |
40 | final class SEAuthDownloaderTask |
||
41 | extends AbstractSEDownloaderTask
|
||
42 | implements Runnable { |
||
43 | 41528 | jjdelcerro | |
44 | 47821 | jjdelcerro | private class DownloaderResponseHandler implements ResponseHandler<Object> { |
45 | |||
46 | private int status; |
||
47 | private HttpResponse response;
|
||
48 | 41528 | jjdelcerro | |
49 | 47821 | jjdelcerro | public DownloaderResponseHandler() {
|
50 | 47826 | fdiaz | this.status = 0; |
51 | 47821 | jjdelcerro | } |
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 | 47826 | fdiaz | if(entity == null) { |
60 | 47821 | jjdelcerro | download(null);
|
61 | } else {
|
||
62 | InputStream content = entity.getContent();
|
||
63 | download(content); |
||
64 | } |
||
65 | |||
66 | 47826 | fdiaz | } catch (IOExceptionWithStatus ex) {
|
67 | 47821 | jjdelcerro | throw ex;
|
68 | } catch (Exception ex) { |
||
69 | 47826 | fdiaz | throw new IOExceptionWithStatus(this.status, ex.getLocalizedMessage(), ex); |
70 | 47821 | jjdelcerro | } |
71 | return null; |
||
72 | } |
||
73 | |||
74 | private int getStatus() { |
||
75 | return this.status; |
||
76 | } |
||
77 | 41528 | jjdelcerro | } |
78 | |||
79 | 47821 | jjdelcerro | 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 | 47824 | fdiaz | public SEAuthDownloaderTask(SEDownloader downloader, URL url, String data, File dstFile, Object groupID) { |
85 | 47821 | jjdelcerro | super(downloader, url, data, dstFile, groupID);
|
86 | 42140 | jjdelcerro | } |
87 | |||
88 | 47821 | jjdelcerro | private DownloaderManagerImpl getDownloader() {
|
89 | return (DownloaderManagerImpl) this.downloader; |
||
90 | 42140 | jjdelcerro | } |
91 | 47821 | jjdelcerro | |
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 | 47824 | fdiaz | if( !authorizationRequester.requestAuthorization(this.getExecutorUI()) ) { |
120 | 47821 | jjdelcerro | 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 | 42140 | jjdelcerro | |
132 | 47826 | fdiaz | 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 | 47821 | jjdelcerro | DownloaderAuthenticationConfig config = this.getServiceAuthorizationConfig();
|
143 | if( config!=null ) { |
||
144 | DownloaderAuthenticationRequester authorizationRequester = config.create(); |
||
145 | if( authorizationRequester!=null ) { |
||
146 | 47824 | fdiaz | if( authorizationRequester.requestAuthorization(this.getExecutorUI()) ) { |
147 | 47821 | jjdelcerro | 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 | 47826 | fdiaz | LOGGER.info("TIMEOUT "+timeout);
|
160 | 47821 | jjdelcerro | 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 | 47826 | fdiaz | 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 | 47821 | jjdelcerro | 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 | 42140 | jjdelcerro | |
295 | 47821 | jjdelcerro | |
296 | |||
297 | @Override
|
||
298 | 41528 | jjdelcerro | public void run() { |
299 | 47821 | jjdelcerro | |
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 | 47826 | fdiaz | // 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 | 41528 | jjdelcerro | } |
354 | |||
355 | 47824 | fdiaz | private Executor getExecutorUI() { |
356 | return this.downloader.getExecutorUI(); |
||
357 | } |
||
358 | 47821 | jjdelcerro | } |