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

    
10
package eu.etaxonomy.cdm.common;
11

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

    
32
import javax.net.ssl.SSLContext;
33
import javax.net.ssl.TrustManager;
34
import javax.net.ssl.X509TrustManager;
35

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

    
58
/**
59
 * @author n.hoffmann
60
 * @since Sep 23, 2010
61
 * @version 1.0
62
 */
63
public class UriUtils {
64
    private static final Logger logger = Logger.getLogger(UriUtils.class);
65

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

    
68

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

    
74
    /**
75
     * see {@link #getInputStream(URI, Map)}
76
     *
77
     * @param uri
78
     * @return
79
     * @throws IOException
80
     * @throws HttpException
81
     */
82
    public static InputStream getInputStream(URI uri) throws IOException, HttpException{
83
        return getInputStream(uri, null);
84
    }
85

    
86
    /**
87
     * Retrieves an {@link InputStream input stream} of the resource located at the given uri.
88
     *
89
     * @param uri
90
     * @return
91
     * @throws IOException
92
     * @throws HttpException
93
     */
94
    public static InputStream getInputStream(URI uri, Map<String, String> requestHeaders) throws IOException, HttpException{
95

    
96
        if(requestHeaders == null){
97
            requestHeaders = new HashMap<>();
98
        }
99

    
100
        if (uri.getScheme().equals("http") || uri.getScheme().equals("https")){
101
            HttpResponse response = UriUtils.getResponse(uri, requestHeaders);
102
            if(UriUtils.isOk(response)){
103
                InputStream stream = getContent(response);
104
                return stream;
105
            } else {
106
                throw new HttpException("HTTP Reponse code is not = 200 (OK): " + UriUtils.getStatus(response));
107
            }
108
        }else if (uri.getScheme().equals("file")){
109
            File file = new File(uri);
110
            return new FileInputStream(file);
111
        }else{
112
            throw new RuntimeException("Protocol not handled yet: " + uri.getScheme());
113
        }
114
    }
115

    
116
    /**
117
     * Retrieves the size of the resource defined by the given uri in bytes
118
     *
119
     * @param uri the resource
120
     * @param requestHeaders additional headers. May be <code>null</code>
121
     * @return the size of the resource in bytes
122
     *
123
     * @throws ClientProtocolException
124
     * @throws IOException
125
     * @throws HttpException
126
     */
127
    public static long getResourceLength(URI uri, Map<String, String> requestHeaders) throws ClientProtocolException, IOException, HttpException{
128
        if(requestHeaders == null){
129
            requestHeaders = new HashMap<>();
130
        }
131

    
132
        if(! uri.isAbsolute()){
133
        	throw new IOException(URI_IS_NOT_ABSOLUTE);
134
        }else if ("http".equals(uri.getScheme()) || "https".equals(uri.getScheme())){
135
            HttpResponse response = UriUtils.getResponse(uri, requestHeaders);
136
            if(UriUtils.isOk(response)){
137
                Header[] contentLengths = response.getHeaders("Content-Length");
138

    
139
                if(contentLengths == null || contentLengths.length == 0){
140
                    throw new HttpException("Could not retrieve Content-Length");
141
                }
142

    
143
                if(contentLengths.length > 1){
144
                    throw new HttpException("Multiple Content-Length headers sent");
145
                }
146

    
147
                Header contentLength = contentLengths[0];
148
                String value = contentLength.getValue();
149

    
150
                return Long.valueOf(value);
151

    
152
            } else {
153
                throw new HttpException("HTTP Reponse code is not = 200 (OK): " + UriUtils.getStatus(response));
154
            }
155
        }else if ("file".equals(uri.getScheme())){
156
            File file = new File(uri);
157
            return file.length();
158
        }else{
159
            throw new RuntimeException("Protocol not handled yet: " + uri.getScheme());
160
        }
161
    }
162

    
163
    /**
164
     * Checks if the given HTTP return status is OK
165
     * @param response the {@link HttpResponse} to check
166
     * @return <code>true</code> if response is OK, <code>false</code> otherwise
167
     */
168
    public static boolean isOk(HttpResponse response){
169
        return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
170
    }
171

    
172
    /**
173
     * Retrieves the content of an {@link HttpResponse} as an {@link InputStream}
174
     * @param response the HTTPResponse to retrieve the content from
175
     * @return the content as InputStream
176
     * @throws IOException
177
     */
178
    public static InputStream getContent(HttpResponse response) throws IOException{
179
        return response.getEntity().getContent();
180
    }
181

    
182
    /**
183
     * Gets the status of the given {@link HttpResponse} as a string
184
     * @param response the response to get the status for
185
     * @return status as a string
186
     */
187
    public static String getStatus(HttpResponse response){
188
        StatusLine statusLine = response.getStatusLine();
189
        return "(" + statusLine.getStatusCode() + ")" + statusLine.getReasonPhrase();
190
    }
191

    
192
    /**
193
     * Sends a HTTP GET 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
     * @return the {@link HttpResponse} of the request
197
     * @throws IOException
198
     * @throws ClientProtocolException
199
     */
200
    public static HttpResponse getResponse(URI uri, Map<String, String> requestHeaders) throws ClientProtocolException, IOException{
201
        return getResponseByType(uri, requestHeaders, HttpMethod.GET, null);
202
    }
203

    
204
    /**
205
     * Sends a HTTP POST request to the defined URI and returns the {@link HttpResponse}.
206
     * @param uri the URI of this HTTP request
207
     * @param requestHeaders the parameters (name-value pairs) of the connection added to the header of the request
208
     * @param entity the {@link HttpEntity} attached to a HTTP POST request
209
     * @return the {@link HttpResponse} of the request
210
     * @throws IOException
211
     * @throws ClientProtocolException
212
     */
213
    public static HttpResponse getPostResponse(URI uri, Map<String, String> requestHeaders, HttpEntity entity) throws ClientProtocolException, IOException{
214
        return getResponseByType(uri, requestHeaders, HttpMethod.POST, entity);
215
    }
216

    
217
    /**
218
     * Sends a HTTP request of the given {@link HttpMethod} to the defined URI and returns the {@link HttpResponse}.
219
     * @param uri the URI of this HTTP request
220
     * @param requestHeaders the parameters (name-value pairs) of the connection added to the header of the request
221
     * @param httpMethod defines if method is POST or GET
222
     * @param entity the {@link HttpEntity} attached to a HTTP POST request
223
     * @return the {@link HttpResponse} of the request
224
     * @throws IOException
225
     * @throws ClientProtocolException
226
     */
227
    public static HttpResponse getResponseByType(URI uri, Map<String, String> requestHeaders, HttpMethod httpMethod, HttpEntity entity) throws IOException, ClientProtocolException {
228
        // Create an instance of HttpClient.
229
        HttpClient  client = new DefaultHttpClient();
230

    
231
        try {
232
            SSLContext sc = SSLContext.getInstance("SSL");
233
            sc.init(null, getTrustingManager(), new java.security.SecureRandom());
234
            SSLSocketFactory socketFactory = new SSLSocketFactory(sc);
235
            Scheme sch = new Scheme("https", 443, socketFactory);
236
            client.getConnectionManager().getSchemeRegistry().register(sch);
237
        } catch (KeyManagementException e1) {
238
            throw new RuntimeException("Registration of ssl support failed", e1);
239
        } catch (NoSuchAlgorithmException e2) {
240
            throw new RuntimeException("Registration of ssl support failed", e2);
241
        }
242

    
243

    
244
        HttpUriRequest method;
245
        switch (httpMethod) {
246
        case GET:
247
            method = new HttpGet(uri);
248
            break;
249
        case POST:
250
            HttpPost httpPost = new HttpPost(uri);
251
            if(entity!=null){
252
                httpPost.setEntity(entity);
253
            }
254
            method = httpPost;
255
            break;
256
        default:
257
            method = new HttpPost(uri);
258
            break;
259
        }
260

    
261
        // configure the connection
262
        if(requestHeaders != null){
263
            for(Entry<String, String> e : requestHeaders.entrySet()){
264
                method.addHeader(e.getKey(), e.getValue());
265
            }
266
        }
267

    
268
        //TODO  method.setFollowRedirects(followRedirects);
269

    
270
        logger.debug("sending "+httpMethod+" request: " + uri);
271

    
272
        return client.execute(method);
273
    }
274

    
275
    /**
276
     * Creates a {@link URI} based on the baseUrl and the given subPath, qParams and fragment
277
     * @param subPath the sub path of the URI
278
     * @param qparams the parameters added as GET parameters to the URI
279
     * @param fragment the fragment of the URI
280
     * @return a URI consisting of the baseURL, the subPath and qParams
281
     * @throws URISyntaxException
282
     */
283
    public static URI createUri(URL baseUrl, String subPath, List<NameValuePair> qparams, String fragment) throws	URISyntaxException {
284

    
285
        String path = baseUrl.getPath();
286

    
287
        if(subPath != null){
288
            if(!path.endsWith("/")){
289
                path += "/";
290
            }
291
            if(subPath.startsWith("/")){
292
                subPath = subPath.substring(1);
293
            }
294
            path += subPath;
295
        }
296

    
297
        if(qparams == null){
298
            qparams = new ArrayList<NameValuePair>(0);
299
        }
300
        String query = null;
301
        if(! qparams.isEmpty()){
302
            query = URLEncodedUtils.format(qparams, "UTF-8");
303
        }
304

    
305
        URIBuilder uriBuilder = new URIBuilder();
306
        uriBuilder.setScheme(baseUrl.getProtocol());
307
        uriBuilder.setHost(baseUrl.getHost());
308
        uriBuilder.setPort(baseUrl.getPort());
309
        uriBuilder.setPath(path);
310
        uriBuilder.setQuery(query);
311
        uriBuilder.setFragment(fragment);
312
        return uriBuilder.build();
313
    }
314

    
315
    /**
316
     * Tests internet connectivity by testing HEAD request for 4 known URL's.<BR>
317
     * If non of them is available <code>false</code> is returned. Otherwise true.<BR>
318
     * @param firstUriToTest if not <code>null</code> this URI is tested before testing the standard URLs.
319
     * @return true if internetconnectivity is given.
320
     */
321
    public static boolean isInternetAvailable(URI firstUriToTest){
322
        boolean result = false;
323
        if (firstUriToTest != null && isServiceAvailable(firstUriToTest)){
324
            return true;
325
        }
326

    
327
        URI uri = URI.create("http://www.cnn.com/");
328
        if (isServiceAvailable(uri)){
329
            return true;
330
        }
331
        uri = URI.create("http://www.bahn.de/");
332
        if (isServiceAvailable(uri)){
333
            return true;
334
        }
335
        uri = URI.create("http://www.google.com/");
336
        if (isServiceAvailable(uri)){
337
            return true;
338
        }
339
        uri = URI.create("http://www.facebook.com/");
340
        if (isServiceAvailable(uri)){
341
            return true;
342
        }
343

    
344
        return result;
345
    }
346

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

    
357
    /**
358
     * Performs HEAD request for the given URI.<BR>
359
     * If any exception occurs <code>false</code> is returned. Otherwise true. <BR>
360
     * @param serviceUri the URI to test.
361
     * @param timeout the timeout of the request in milliseconds
362
     * @return true if service is available, false otherwise. Also a non-absolute URI will return false.
363
     */
364
    public static boolean isServiceAvailable(URI serviceUri, Integer timeout){
365
        boolean result = false;
366

    
367
        if(serviceUri==null || serviceUri.getHost()==null || !serviceUri.isAbsolute()){
368
            return false;
369
        }
370

    
371
        //Http
372
        CloseableHttpClient httpclient = HttpClients.createDefault();
373
        HttpGet httpget = new HttpGet(serviceUri);
374

    
375

    
376
        if(timeout!=null){
377

    
378
            RequestConfig requestConfig = RequestConfig.custom()
379
                    .setSocketTimeout(timeout)
380
                    .setConnectTimeout(timeout)
381
                    .setConnectionRequestTimeout(timeout)
382
                    .build();
383
            httpget.setConfig(requestConfig);
384
        }
385

    
386
        try {
387
            // Execute the request
388
            HttpResponse response = httpclient.execute(httpget);
389
            // Examine the response status
390
            if (logger.isDebugEnabled()){
391
                logger.debug(response.getStatusLine());
392
            }
393
             result = true;
394

    
395
        } catch (UnknownHostException e1) {
396
            logger.info("Unknown Host: " +e1.getMessage());
397
        } catch (ClientProtocolException e2) {
398
            logger.info("ClientProtocolException: " + e2.getMessage());
399
        } catch (IOException e3) {
400
            logger.info("IOException: " + e3.getMessage());
401
        }
402

    
403
         // When HttpClient instance is no longer needed,
404
         // shut down the connection manager to ensure
405
         // immediate deallocation of all system resources
406
        //needed ?
407
//	     client.getConnectionManager().shutdown();
408

    
409
        return result;
410
    }
411

    
412
    /**
413
     * Tests reachability of a root server by trying to resolve a host name.
414
     * @param hostNameToResolve the host name to resolve. If <code>null</code>
415
     * a default host name is tested.
416
     * @return
417
     */
418
    public static boolean isRootServerAvailable(String hostNameToResolve){
419
        try {
420
            if (hostNameToResolve == null){
421
                hostNameToResolve = "cnn.com";
422
            }
423
            InetAddress inetHost = InetAddress.getByName(hostNameToResolve);
424
            logger.debug("The hosts IP address is: " + inetHost.getHostAddress());
425
            return true;
426
         } catch(UnknownHostException ex) {
427
             logger.info("Unrecognized host");
428
             return false;
429
         }
430
    }
431

    
432
    //from http://www.javabeginners.de/Netzwerk/File_zu_URL.php
433
    public static URL fileToURL(File file){
434
        URL url = null;
435
        try {
436
            // Sonderzeichen (z.B. Leerzeichen) bleiben erhalten
437
            url = new URL("file://" + file.getPath());
438
            // Sonderzeichen (z.B. Leerzeichen) werden codiert
439
            url = file.toURI().toURL();
440
        } catch (MalformedURLException e) {
441
            e.printStackTrace();
442
        }
443
        return url;
444
    }
445

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

    
474
    public static boolean checkServiceAvailable(String host, int port){
475
        boolean success = true;
476
        try {
477
          (new Socket(host, port)).close();
478
        } catch (UnknownHostException e) {
479
          // unknown host
480
          success = false;
481
        } catch (IOException e) {
482
          // io exception, service probably not running
483
          success = false;
484
        }
485
        return success;
486
    }
487

    
488
    private static TrustManager[] getTrustingManager() {
489
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
490
            @Override
491
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
492
                return null;
493
            }
494

    
495
            @Override
496
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
497
                // Do nothing
498
            }
499

    
500
            @Override
501
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
502
                // Do nothing
503
            }
504

    
505
        } };
506
        return trustAllCerts;
507
    }
508
}
(20-20/22)