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 @ 47824

History | View | Annotate | Download (14.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.URL;
9
import java.util.Objects;
10
import java.util.concurrent.Executor;
11
import org.apache.commons.io.IOUtils;
12
import org.apache.commons.lang3.StringUtils;
13
import org.apache.http.Header;
14
import org.apache.http.HttpEntity;
15
import org.apache.http.HttpResponse;
16
import org.apache.http.auth.AuthenticationException;
17
import org.apache.http.client.ClientProtocolException;
18
import org.apache.http.client.ResponseHandler;
19
import org.apache.http.client.methods.HttpDelete;
20
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
21
import org.apache.http.client.methods.HttpGet;
22
import org.apache.http.client.methods.HttpPost;
23
import org.apache.http.client.methods.HttpPut;
24
import org.apache.http.client.methods.HttpRequestBase;
25
import org.apache.http.client.methods.HttpUriRequest;
26
import org.apache.http.entity.ContentType;
27
import org.apache.http.entity.StringEntity;
28
import org.apache.http.impl.client.CloseableHttpClient;
29
import org.apache.http.impl.client.HttpClientBuilder;
30
import org.gvsig.compat.se.net.downloader.se.AbstractSEDownloaderTask;
31
import org.gvsig.compat.se.net.downloader.se.SEDownloader;
32
import org.gvsig.downloader.DownloaderAuthenticationConfig;
33
import org.gvsig.downloader.DownloaderAuthenticationRequester;
34
import org.gvsig.downloader.DownloaderCredentials;
35

    
36
@SuppressWarnings("UseSpecificCatch")
37
final class SEAuthDownloaderTask
38
        extends AbstractSEDownloaderTask
39
        implements Runnable {
40

    
41
    private class DownloaderResponseHandler implements ResponseHandler<Object> {
42
        
43
        private int status;
44
        private HttpResponse response;
45

    
46
        public DownloaderResponseHandler() {
47
            this.status = 200;
48
         }
49
        
50
        @Override
51
        public Object handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
52
            this.status=response.getStatusLine().getStatusCode();
53
            this.response = response;
54
            try {
55
                HttpEntity entity = response.getEntity();
56
                if(entity != null) {
57
                    download(null);
58
                } else {
59
                    InputStream content = entity.getContent();
60
                    download(content);
61
                }
62
                
63
            } catch (IOException ex) {
64
                throw ex;
65
            } catch (Exception ex) {
66
                throw new IOException(ex);
67
            }
68
            return null;
69
        }
70

    
71
        private int getStatus() {
72
            return this.status;
73
        }
74
    }
75

    
76
    private static final String METHOD_PUT = "PUT";
77
    private static final String METHOD_POST = "POST";
78
    private static final String METHOD_GET = "GET";
79
    private static final String METHOD_DELETE = "DELETE";
80
    
81
    public SEAuthDownloaderTask(SEDownloader downloader, URL url, String data, File dstFile, Object groupID) {
82
        super(downloader, url, data, dstFile, groupID);
83
    }
84

    
85
    private DownloaderManagerImpl getDownloader() {
86
        return (DownloaderManagerImpl) this.downloader;
87
    }
88
    
89
    private DownloaderCredentials getCredentials() { 
90
        return this.getDownloader().getCredentials(this.url);
91
    }
92
    
93
    private void addOrReplaceCredentials(DownloaderCredentials credentials) { 
94
        this.getDownloader().addOrReplaceCredentials(credentials);
95
    }
96
    
97
    private DownloaderAuthenticationConfig getServiceAuthorizationConfig() { 
98
        return this.getDownloader().getAuthenticationConfigurationService(this.url.toString());
99
    }
100
    
101
    private void authorize() {
102
        try {
103
            LOGGER.info("AUTHORIZATION REQUIRED");
104
            DownloaderAuthenticationConfig config = this.getServiceAuthorizationConfig();
105
            if( config == null ) {
106
                config = this.getDownloader().requestAutenticationConfig(this.url);
107
                if( config == null ) {
108
                    throw new AuthenticationException("Not service authentication configured for url '"+this.url+"'.");
109
                }
110
            }
111
            DownloaderAuthenticationRequester authorizationRequester = config.create();
112
            if( authorizationRequester == null ) {
113
                throw new AuthenticationException("Can't configure service authentication for url '"+this.url+"'.");
114
            }
115
            LOGGER.info("AUTHORIZATION REQUESTER TYPE: "+authorizationRequester.getProviderName());
116
            if( !authorizationRequester.requestAuthorization(this.getExecutorUI()) ) {
117
                return;
118
            }
119
            DownloaderCredentials credentials = authorizationRequester.getCredentials();
120
            addOrReplaceCredentials(credentials);
121
            LOGGER.info("CREDENTIALS: "+credentials.toString());
122
        } catch (Exception ex) {
123
            LOGGER.warn("Can't authorize", ex);
124
        }
125
    }
126
    
127
    private DownloaderResponseHandler executeRequest(HttpUriRequest request) throws IOException {
128

    
129
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
130
        DownloaderCredentials credentials = this.getCredentials();        
131
        if( credentials==null ) {
132
            DownloaderAuthenticationConfig config = this.getServiceAuthorizationConfig();
133
            if( config!=null ) {
134
                DownloaderAuthenticationRequester authorizationRequester = config.create();
135
                if( authorizationRequester!=null ) {
136
                    if( authorizationRequester.requestAuthorization(this.getExecutorUI()) ) {
137
                        credentials = authorizationRequester.getCredentials();
138
                        addOrReplaceCredentials(credentials);                    
139
                        request.addHeader("Authorization", credentials.getAuthorizationToken());
140
                    }
141
                }
142
            }
143
        } else {
144
            request.addHeader("Authorization", credentials.getAuthorizationToken());
145
        }
146
        DownloaderResponseHandler responseHandler = new DownloaderResponseHandler();
147

    
148
        LOGGER.info("REQUEST "+request.getMethod()+" "+request.getURI().toString());
149
        for (Header header : request.getAllHeaders()) {
150
            LOGGER.info(header.getName()+": "+header.getValue());
151
        }
152
        if( request instanceof HttpEntityEnclosingRequestBase ) {
153
            InputStream content = ((HttpEntityEnclosingRequestBase) request).getEntity().getContent();
154
            LOGGER.info("BODY data "+(StringUtils.join(IOUtils.readLines(content,"utf-8"),"\n")));                
155
        }
156
        httpClient.execute(request,responseHandler);
157
        LOGGER.info("RESPONSE CODE "+responseHandler.getStatus());
158
        
159
        return responseHandler;
160
    }
161

    
162
    public File send(String method) throws IOException {
163
        int status = 500;
164
        try {
165
            int numretries = 3;
166
            for (int retries = 0; retries < numretries; retries++) {    
167
                HttpRequestBase request;
168
                switch (method.toUpperCase()) {
169
                    case METHOD_DELETE:
170
                        request = new HttpDelete(url.toURI());
171
                        break;
172
                    case METHOD_GET:
173
                    default:
174
                        request = new HttpGet(url.toURI());
175
                        break;
176
                }
177
//                request.setHeader("User-Agent","Mozilla/5.0 (gvSIG) like Gecko");
178
                request.setHeader("User-Agent","gvSIG-desktop");
179
                request.setHeader("Referer","http://www.gvsig.com");
180

    
181
                LOGGER.info("RETRY "+retries);
182
                DownloaderResponseHandler responseHandler = executeRequest(request);
183
                status = responseHandler.getStatus();
184
                if(status >= 200 && status < 300) {
185
                    //2xx success
186
                    return this.dstFile;
187
                    
188
                } else if(status >= 300 && status < 400) {
189
                    // 3xx redirection
190
                    throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status);
191
                } else if(status == 401 || status == 403) {
192
                    // "401 Unauthorized" indicates that the request lacks valid authentication credentials
193
                    // "403 Forbidden" the client doesn't have permission to access the requested resource
194
                    // https://www.permit.io/blog/401-vs-403-error-whats-the-difference
195
                    if( retries < numretries-1 ) {
196
                        authorize();
197
                    }
198
                } else if(status >= 400 && status < 500) {
199
                    // 4xx client errors
200
                    throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status);
201
                } else if(status >= 500 && status < 600) {
202
                    // 5xx server errors
203
                    throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status);
204
                } else {
205
                    //Unknown
206
                    throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status);
207
                }
208
            }
209
            throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' too many retries, last status " + status);
210
            
211
        } catch (IOExceptionWithStatus ex) {
212
            throw ex;
213
        } catch (Throwable ex) {
214
            throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' last status " + status, ex);
215
        }
216
    }
217
        
218
    private File send(String method, ContentType contentType, String data) throws IOExceptionWithStatus {
219
        int status = 500;
220
        try {
221
            int numretries = 3;
222
            for (int retries = 0; retries < numretries; retries++) {            
223
                HttpEntityEnclosingRequestBase request;
224
                switch (method.toUpperCase()) {
225
                    case METHOD_PUT:
226
                        request = new HttpPut(url.toURI());
227
                        break;
228
                    case METHOD_POST:
229
                    default:
230
                        request = new HttpPost(url.toURI());
231
                        request.setHeader("SOAPAction", "post");                
232
                        break;
233
                }
234
                request.setEntity(new StringEntity(data, contentType));
235
//                request.setHeader("User-Agent","Mozilla/5.0 (gvSIG) like Gecko");
236
                request.setHeader("User-Agent","gvSIG-desktop");
237
                request.setHeader("Referer","http://www.gvsig.com");
238
                request.setHeader("Content-type", contentType.getMimeType());                
239
                DownloaderResponseHandler responseHandler = executeRequest(request);
240
                status = responseHandler.getStatus();
241
                if(status >= 200 && status < 300) {
242
                    //2xx success
243
                    return this.dstFile;
244
                    
245
                } else if(status >= 300 && status < 400) {
246
                    // 3xx redirection
247
                    throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status);
248
                } else if(status == 401 || status == 403) {
249
                    // "401 Unauthorized" indicates that the request lacks valid authentication credentials
250
                    // "403 Forbidden" the client doesn't have permission to access the requested resource
251
                    // https://www.permit.io/blog/401-vs-403-error-whats-the-difference
252
                    if( retries < numretries-1 ) {
253
                        authorize();
254
                    }
255
                } else if(status >= 400 && status < 500) {
256
                    // 4xx client errors
257
                    throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status);
258
                } else if(status >= 500 && status < 600) {
259
                    // 5xx server errors
260
                    throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status);
261
                } else {
262
                    //Unknown
263
                    throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' HTTPStatus = "+status);
264
                }
265
            }
266
            throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' too many retries, last status " + status);
267
            
268
        } catch (IOExceptionWithStatus ex) {
269
            throw ex;
270
        } catch (Throwable ex) {
271
            throw new IOExceptionWithStatus(status, "Can't call method "+method+" "+Objects.toString(url)+"' last status " + status, ex);
272
        }
273
    }
274
    
275
    
276
    
277
    @Override
278
    public void run() {
279
        
280
        try {
281
            if (data != null) {
282
                send(METHOD_POST, ContentType.TEXT_XML, this.data);
283
            } else {
284
                send(METHOD_GET);
285
            }
286
            postdownload();
287

    
288
        } catch (Exception e) {
289
            exception(e);
290
        }
291

    
292
        
293
        LOGGER.info("downloading '" + url.toString() + "' to: " + dstFile.getAbsolutePath());
294
        if (data != null) {
295
            LOGGER.info("using POST, request = " + data);
296
        }
297
        int timeout = this.getTimeout();
298

    
299
        try {
300
            OutputStreamWriter os = null;
301
            HttpURLConnection connection = null;
302

    
303
            //If the used protocol is HTTPS
304
            if (url.getProtocol().equals("https")) {
305
                disableHttsValidation();
306
            }
307
            connection = (HttpURLConnection) url.openConnection();
308
            connection.setUseCaches(false);
309
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (gvSIG) like Gecko");
310
            connection.setConnectTimeout(timeout);
311
            
312
            //If it uses a HTTP POST
313
            if (data != null) {
314
                connection.setRequestProperty("SOAPAction", "post");
315
                connection.setRequestMethod("POST");
316
                connection.setDoOutput(true);
317
                connection.setRequestProperty("Content-Type", "text/xml; charset=UTF-8");
318
                os = new OutputStreamWriter(connection.getOutputStream());
319
                os.write(data);
320
                os.flush();
321
            }
322
            download(connection.getInputStream());
323

    
324
            if (os != null) {
325
                os.close();
326
            }
327
            
328
            postdownload();
329

    
330
        } catch (Exception e) {
331
            exception(e);
332
        }
333
    }
334

    
335
    private Executor getExecutorUI()  {
336
        return this.downloader.getExecutorUI();
337
    }
338
}