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
    private static final Logger logger = LogManager.getLogger(UriUtils.class);
64

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

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

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

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

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

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

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

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

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

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

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

    
138
                return Long.valueOf(value);
139

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
272
        String path = baseUrl.getPath();
273

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

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

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

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

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

    
331
        return result;
332
    }
333

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

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

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

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

    
362

    
363
        if(timeout!=null){
364

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

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

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

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

    
396
        return result;
397
    }
398

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

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

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

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

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

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

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

    
492
        } };
493
        return trustAllCerts;
494
    }
495
}
(23-23/25)