Statistics
| Revision:

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
}