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 |
} |