Project

General

Profile

Download (18.2 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.common;
10

    
11
import java.io.File;
12
import java.io.FileInputStream;
13
import java.io.IOException;
14
import java.io.InputStream;
15
import java.net.InetAddress;
16
import java.net.MalformedURLException;
17
import java.net.Socket;
18
import java.net.URISyntaxException;
19
import java.net.URL;
20
import java.net.UnknownHostException;
21
import java.security.KeyManagementException;
22
import java.security.NoSuchAlgorithmException;
23
import java.security.cert.X509Certificate;
24
import java.util.ArrayList;
25
import java.util.HashMap;
26
import java.util.List;
27
import java.util.Map;
28
import java.util.Map.Entry;
29

    
30
import javax.net.ssl.SSLContext;
31
import javax.net.ssl.TrustManager;
32
import javax.net.ssl.X509TrustManager;
33

    
34
import org.apache.http.Header;
35
import org.apache.http.HttpEntity;
36
import org.apache.http.HttpException;
37
import org.apache.http.HttpResponse;
38
import org.apache.http.HttpStatus;
39
import org.apache.http.NameValuePair;
40
import org.apache.http.StatusLine;
41
import org.apache.http.client.ClientProtocolException;
42
import org.apache.http.client.HttpClient;
43
import org.apache.http.client.config.RequestConfig;
44
import org.apache.http.client.methods.HttpGet;
45
import org.apache.http.client.methods.HttpHead;
46
import org.apache.http.client.methods.HttpPost;
47
import org.apache.http.client.methods.HttpUriRequest;
48
import org.apache.http.client.utils.URIBuilder;
49
import org.apache.http.client.utils.URLEncodedUtils;
50
import org.apache.http.conn.scheme.Scheme;
51
import org.apache.http.conn.ssl.SSLSocketFactory;
52
import org.apache.http.impl.client.CloseableHttpClient;
53
import org.apache.http.impl.client.DefaultHttpClient;
54
import org.apache.http.impl.client.HttpClients;
55
import org.apache.logging.log4j.LogManager;
56
import org.apache.logging.log4j.Logger;
57

    
58
/**
59
 * @author n.hoffmann
60
 * @since Sep 23, 2010
61
 */
62
public class UriUtils {
63

    
64
    private static final Logger logger = LogManager.getLogger();
65

    
66
    protected static final String URI_IS_NOT_ABSOLUTE = "URI is not absolute (protocol is missing)";
67

    
68
    public enum HttpMethod{
69
        GET,
70
        POST
71
    }
72

    
73
    /**
74
     * see {@link #getInputStream(URI, Map)}
75
     */
76
    public static InputStream getInputStream(URI uri) throws IOException, HttpException{
77
        return getInputStream(uri, null);
78
    }
79

    
80
    /**
81
     * Retrieves an {@link InputStream input stream} of the resource located at the given uri.
82
     */
83
    public static InputStream getInputStream(URI uri, Map<String, String> requestHeaders) throws IOException, HttpException{
84

    
85
        if(requestHeaders == null){
86
            requestHeaders = new HashMap<>();
87
        }
88

    
89
        if (uri.getScheme().equals("http") || uri.getScheme().equals("https")){
90
            HttpResponse response = UriUtils.getResponse(uri, requestHeaders);
91
            if(UriUtils.isOk(response)){
92
                InputStream stream = getContent(response);
93
                return stream;
94
            } else {
95
                throw new HttpException("HTTP GET response " + UriUtils.getStatus(response) + " for " + uri.toString());
96
            }
97
        }else if (uri.getScheme().equals("file")){
98
            File file = new File(uri.getJavaUri());
99
            return new FileInputStream(file);
100
        }else{
101
            throw new RuntimeException("Protocol not handled yet: " + uri.getScheme());
102
        }
103
    }
104

    
105
    /**
106
     * Retrieves the size of the resource defined by the given uri in bytes
107
     *
108
     * @param uri the resource
109
     * @param requestHeaders additional headers. May be <code>null</code>
110
     * @return the size of the resource in bytes
111
     *
112
     * @throws ClientProtocolException
113
     * @throws IOException
114
     * @throws HttpException
115
     */
116
    public static long getResourceLength(URI uri, Map<String, String> requestHeaders) throws ClientProtocolException, IOException, HttpException{
117
        if(requestHeaders == null){
118
            requestHeaders = new HashMap<>();
119
        }
120

    
121
        if(! uri.isAbsolute()){
122
        	throw new IOException(URI_IS_NOT_ABSOLUTE);
123
        }else if ("http".equals(uri.getScheme()) || "https".equals(uri.getScheme())){
124
            HttpResponse response = UriUtils.getResponse(uri, requestHeaders); // FIXME must use HTTP HEAD!
125
            if(UriUtils.isOk(response)){
126
                Header[] contentLengths = response.getHeaders("Content-Length");
127

    
128
                if(contentLengths == null || contentLengths.length == 0){
129
                    throw new HttpException("Could not retrieve Content-Length");
130
                }
131

    
132
                if(contentLengths.length > 1){
133
                    throw new HttpException("Multiple Content-Length headers sent");
134
                }
135

    
136
                Header contentLength = contentLengths[0];
137
                String value = contentLength.getValue();
138

    
139
                return Long.valueOf(value);
140

    
141
            } else {
142
                throw new HttpException("HTTP Reponse code is not = 200 (OK): " + UriUtils.getStatus(response));
143
            }
144
        }else if ("file".equals(uri.getScheme())){
145
            File file = new File(uri.getJavaUri());
146
            return file.length();
147
        }else{
148
            throw new RuntimeException("Protocol not handled yet: " + uri.getScheme());
149
        }
150
    }
151

    
152
    /**
153
     * Checks if the given HTTP return status is OK
154
     * @param response the {@link HttpResponse} to check
155
     * @return <code>true</code> if response is OK, <code>false</code> otherwise
156
     */
157
    public static boolean isOk(HttpResponse response){
158
        return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
159
    }
160

    
161
    /**
162
     * Retrieves the content of an {@link HttpResponse} as an {@link InputStream}
163
     * @param response the HTTPResponse to retrieve the content from
164
     * @return the content as InputStream
165
     * @throws IOException
166
     */
167
    public static InputStream getContent(HttpResponse response) throws IOException{
168
        return response.getEntity().getContent();
169
    }
170

    
171
    /**
172
     * Gets the status of the given {@link HttpResponse} as a string
173
     * @param response the response to get the status for
174
     * @return status as a string
175
     */
176
    public static String getStatus(HttpResponse response){
177
        StatusLine statusLine = response.getStatusLine();
178
        return "(" + statusLine.getStatusCode() + ")" + statusLine.getReasonPhrase();
179
    }
180

    
181
    /**
182
     * Sends a HTTP GET request to the defined URI and returns the {@link HttpResponse}.
183
     * @param uri the URI of this HTTP request
184
     * @param requestHeaders the parameters (name-value pairs) of the connection added to the header of the request
185
     * @return the {@link HttpResponse} of the request
186
     * @throws IOException
187
     * @throws ClientProtocolException
188
     */
189
    public static HttpResponse getResponse(URI uri, Map<String, String> requestHeaders) throws ClientProtocolException, IOException{
190
        return getResponseByType(uri, requestHeaders, HttpMethod.GET, null);
191
    }
192

    
193
    /**
194
     * Sends a HTTP POST request to the defined URI and returns the {@link HttpResponse}.
195
     * @param uri the URI of this HTTP request
196
     * @param requestHeaders the parameters (name-value pairs) of the connection added to the header of the request
197
     * @param entity the {@link HttpEntity} attached to a HTTP POST request
198
     * @return the {@link HttpResponse} of the request
199
     * @throws IOException
200
     * @throws ClientProtocolException
201
     */
202
    public static HttpResponse getPostResponse(URI uri, Map<String, String> requestHeaders, HttpEntity entity) throws ClientProtocolException, IOException{
203
        return getResponseByType(uri, requestHeaders, HttpMethod.POST, entity);
204
    }
205

    
206
    /**
207
     * Sends a HTTP request of the given {@link HttpMethod} to the defined URI and returns the {@link HttpResponse}.
208
     * @param uri the URI of this HTTP request
209
     * @param requestHeaders the parameters (name-value pairs) of the connection added to the header of the request
210
     * @param httpMethod defines if method is POST or GET
211
     * @param entity the {@link HttpEntity} attached to a HTTP POST request
212
     * @return the {@link HttpResponse} of the request
213
     * @throws IOException
214
     * @throws ClientProtocolException
215
     */
216
    public static HttpResponse getResponseByType(URI uri, Map<String, String> requestHeaders, HttpMethod httpMethod, HttpEntity entity) throws IOException, ClientProtocolException {
217
        // Create an instance of HttpClient.
218
        HttpClient client = new DefaultHttpClient();
219

    
220
        try {
221
            SSLContext sc = SSLContext.getInstance("SSL");
222
            sc.init(null, getTrustingManager(), new java.security.SecureRandom());
223
            SSLSocketFactory socketFactory = new SSLSocketFactory(sc);
224
            Scheme sch = new Scheme("https", 443, socketFactory);
225
            client.getConnectionManager().getSchemeRegistry().register(sch);
226
        } catch (KeyManagementException e1) {
227
            throw new RuntimeException("Registration of ssl support failed", e1);
228
        } catch (NoSuchAlgorithmException e2) {
229
            throw new RuntimeException("Registration of ssl support failed", e2);
230
        }
231

    
232
        HttpUriRequest method;
233
        switch (httpMethod) {
234
        case GET:
235
            method = new HttpGet(uri.getJavaUri());
236
            break;
237
        case POST:
238
            HttpPost httpPost = new HttpPost(uri.getJavaUri());
239
            if(entity!=null){
240
                httpPost.setEntity(entity);
241
            }
242
            method = httpPost;
243
            break;
244
        default:
245
            method = new HttpPost(uri.getJavaUri());
246
            break;
247
        }
248

    
249
        // configure the connection
250
        if(requestHeaders != null){
251
            for(Entry<String, String> e : requestHeaders.entrySet()){
252
                method.addHeader(e.getKey(), e.getValue());
253
            }
254
        }
255

    
256
        //TODO  method.setFollowRedirects(followRedirects);
257

    
258
        if (logger.isDebugEnabled()){logger.debug("sending "+httpMethod+" request: " + uri);}
259

    
260
        return client.execute(method);
261
    }
262

    
263
    /**
264
     * Creates a {@link URI} based on the baseUrl and the given subPath, qParams and fragment
265
     * @param subPath the sub path of the URI
266
     * @param qparams the parameters added as GET parameters to the URI
267
     * @param fragment the fragment of the URI
268
     * @return a URI consisting of the baseURL, the subPath and qParams
269
     * @throws URISyntaxException
270
     */
271
    public static URI createUri(URL baseUrl, String subPath, List<NameValuePair> qparams, String fragment) throws	URISyntaxException {
272

    
273
        String path = baseUrl.getPath();
274

    
275
        if(subPath != null){
276
            if(!path.endsWith("/")){
277
                path += "/";
278
            }
279
            if(subPath.startsWith("/")){
280
                subPath = subPath.substring(1);
281
            }
282
            path += subPath;
283
        }
284

    
285
        if(qparams == null){
286
            qparams = new ArrayList<>(0);
287
        }
288
        String query = null;
289
        if(! qparams.isEmpty()){
290
            query = URLEncodedUtils.format(qparams, "UTF-8");
291
        }
292

    
293
        URIBuilder uriBuilder = new URIBuilder();
294
        uriBuilder.setScheme(baseUrl.getProtocol());
295
        uriBuilder.setHost(baseUrl.getHost());
296
        uriBuilder.setPort(baseUrl.getPort());
297
        uriBuilder.setPath(path);
298
        uriBuilder.setQuery(query);
299
        uriBuilder.setFragment(fragment);
300
        return new URI(uriBuilder.build());
301
    }
302

    
303
    /**
304
     * Tests Internet connectivity by testing HEAD request for 4 known URL's.<BR>
305
     * If non of them is available <code>false</code> is returned. Otherwise true.<BR>
306
     * @param firstUriToTest if not <code>null</code> this URI is tested before testing the standard URLs.
307
     * @return true if Internet connectivity is given.
308
     */
309
    public static boolean isInternetAvailable(URI firstUriToTest){
310
        boolean result = false;
311
        if (firstUriToTest != null && isServiceAvailable(firstUriToTest)){
312
            return true;
313
        }
314

    
315
        URI uri = URI.create("http://www.cnn.com/");
316
        if (isServiceAvailable(uri)){
317
            return true;
318
        }
319
        uri = URI.create("http://www.bahn.de/");
320
        if (isServiceAvailable(uri)){
321
            return true;
322
        }
323
        uri = URI.create("http://www.google.com/");
324
        if (isServiceAvailable(uri)){
325
            return true;
326
        }
327
        uri = URI.create("http://www.facebook.com/");
328
        if (isServiceAvailable(uri)){
329
            return true;
330
        }
331

    
332
        return result;
333
    }
334

    
335
    /**
336
     * Performs HEAD request for the given URI.<BR>
337
     * If any exception occurs <code>false</code> is returned. Otherwise true. <BR>
338
     * @param serviceUri the URI to test.
339
     * @return true if service is available, false otherwise. Also a non-absolute URI will return false.
340
     */
341
    public static boolean isServiceAvailable(URI serviceUri){
342
        return isServiceAvailable(serviceUri, null);
343
    }
344

    
345
    /**
346
     * Performs HEAD request for the given URI.<BR>
347
     * If any exception occurs <code>false</code> is returned. Otherwise true. <BR>
348
     * @param serviceUri the URI to test.
349
     * @param timeout the timeout of the request in milliseconds
350
     * @return true if service is available, false otherwise. Also a non-absolute URI will return false.
351
     */
352
    public static boolean isServiceAvailable(URI serviceUri, Integer timeout){
353
        boolean result = false;
354

    
355
        if(serviceUri==null || serviceUri.getHost()==null || !serviceUri.isAbsolute()){
356
            return false;
357
        }
358

    
359
        //Http
360
        CloseableHttpClient httpclient = HttpClients.createDefault();
361
        HttpHead httpget = new HttpHead(serviceUri.getJavaUri());
362

    
363

    
364
        if(timeout!=null){
365

    
366
            RequestConfig requestConfig = RequestConfig.custom()
367
                    .setSocketTimeout(timeout)
368
                    .setConnectTimeout(timeout)
369
                    .setConnectionRequestTimeout(timeout)
370
                    .build();
371
            httpget.setConfig(requestConfig);
372
        }
373

    
374
        try {
375
            // Execute the request
376
            HttpResponse response = httpclient.execute(httpget);
377
            // Examine the response status
378
            if (logger.isDebugEnabled()){
379
                logger.debug(response.getStatusLine());
380
            }
381
             result = true;
382

    
383
        } catch (UnknownHostException e1) {
384
            logger.info("Unknown Host: " +e1.getMessage());
385
        } catch (ClientProtocolException e2) {
386
            logger.info("ClientProtocolException: " + e2.getMessage());
387
        } catch (IOException e3) {
388
            logger.info("IOException: " + e3.getMessage());
389
        }
390

    
391
         // When HttpClient instance is no longer needed,
392
         // shut down the connection manager to ensure
393
         // immediate deallocation of all system resources
394
        //needed ?
395
//	     client.getConnectionManager().shutdown();
396

    
397
        return result;
398
    }
399

    
400
    /**
401
     * Tests reachability of a root server by trying to resolve a host name.
402
     * @param hostNameToResolve the host name to resolve. If <code>null</code>
403
     * a default host name is tested.
404
     * @return
405
     */
406
    public static boolean isRootServerAvailable(String hostNameToResolve){
407
        try {
408
            if (hostNameToResolve == null){
409
                hostNameToResolve = "cnn.com";
410
            }
411
            InetAddress inetHost = InetAddress.getByName(hostNameToResolve);
412
            logger.debug("The hosts IP address is: " + inetHost.getHostAddress());
413
            return true;
414
         } catch(UnknownHostException ex) {
415
             logger.info("Unrecognized host");
416
             return false;
417
         }
418
    }
419

    
420
    //from http://www.javabeginners.de/Netzwerk/File_zu_URL.php
421
    public static URL fileToURL(File file){
422
        URL url = null;
423
        try {
424
            // Sonderzeichen (z.B. Leerzeichen) bleiben erhalten
425
            url = new URL("file://" + file.getPath());
426
            // Sonderzeichen (z.B. Leerzeichen) werden codiert
427
            url = file.toURI().toURL();
428
        } catch (MalformedURLException e) {
429
            e.printStackTrace();
430
        }
431
        return url;
432
    }
433

    
434
    //from http://blogs.sphinx.at/java/erzeugen-von-javaiofile-aus-javaneturl/
435
    public static File urlToFile(URL url) {
436
        URI uri;
437
        try {
438
            // this is the step that can fail, and so
439
            // it should be this step that should be fixed
440
            uri = new URI(url);
441
        } catch (URISyntaxException e) {
442
            // OK if we are here, then obviously the URL did
443
            // not comply with RFC 2396. This can only
444
            // happen if we have illegal unescaped characters.
445
            // If we have one unescaped character, then
446
            // the only automated fix we can apply, is to assume
447
            // all characters are unescaped.
448
            // If we want to construct a URI from unescaped
449
            // characters, then we have to use the component
450
            // constructors:
451
            try {
452
                uri = new URI(url.getProtocol(), url.getUserInfo(), url
453
                        .getHost(), url.getPort(), url.getPath(), url
454
                        .getQuery(), url.getRef());
455
            } catch (URISyntaxException e1) {
456
                throw new IllegalArgumentException("broken URL: " + url);
457
            }
458
        }
459
        return new File(uri.getJavaUri());
460
    }
461

    
462
    public static boolean checkServiceAvailable(String host, int port){
463
        boolean success = true;
464
        try {
465
          (new Socket(host, port)).close();
466
        } catch (UnknownHostException e) {
467
          // unknown host
468
          success = false;
469
        } catch (IOException e) {
470
          // io exception, service probably not running
471
          success = false;
472
        }
473
        return success;
474
    }
475

    
476
    private static TrustManager[] getTrustingManager() {
477
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
478
            @Override
479
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
480
                return null;
481
            }
482

    
483
            @Override
484
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
485
                // Do nothing
486
            }
487

    
488
            @Override
489
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
490
                // Do nothing
491
            }
492

    
493
        } };
494
        return trustAllCerts;
495
    }
496
}
(24-24/26)