Project

General

Profile

Download (18.1 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.HttpPost;
46
import org.apache.http.client.methods.HttpUriRequest;
47
import org.apache.http.client.utils.URIBuilder;
48
import org.apache.http.client.utils.URLEncodedUtils;
49
import org.apache.http.conn.scheme.Scheme;
50
import org.apache.http.conn.ssl.SSLSocketFactory;
51
import org.apache.http.impl.client.CloseableHttpClient;
52
import org.apache.http.impl.client.DefaultHttpClient;
53
import org.apache.http.impl.client.HttpClients;
54
import org.apache.log4j.Logger;
55

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

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

    
65
    public enum HttpMethod{
66
        GET,
67
        POST
68
    }
69

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

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

    
82
        if(requestHeaders == null){
83
            requestHeaders = new HashMap<>();
84
        }
85

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

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

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

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

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

    
133
                Header contentLength = contentLengths[0];
134
                String value = contentLength.getValue();
135

    
136
                return Long.valueOf(value);
137

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

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

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

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

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

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

    
203
    /**
204
     * Sends a HTTP request of the given {@link HttpMethod} to the defined URI and returns the {@link HttpResponse}.
205
     * @param uri the URI of this HTTP request
206
     * @param requestHeaders the parameters (name-value pairs) of the connection added to the header of the request
207
     * @param httpMethod defines if method is POST or GET
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 getResponseByType(URI uri, Map<String, String> requestHeaders, HttpMethod httpMethod, HttpEntity entity) throws IOException, ClientProtocolException {
214
        // Create an instance of HttpClient.
215
        HttpClient client = new DefaultHttpClient();
216

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

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

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

    
253
        //TODO  method.setFollowRedirects(followRedirects);
254

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

    
257
        return client.execute(method);
258
    }
259

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

    
270
        String path = baseUrl.getPath();
271

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

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

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

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

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

    
329
        return result;
330
    }
331

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

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

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

    
356
        //Http
357
        CloseableHttpClient httpclient = HttpClients.createDefault();
358
        HttpGet httpget = new HttpGet(serviceUri.getJavaUri());
359

    
360

    
361
        if(timeout!=null){
362

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

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

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

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

    
394
        return result;
395
    }
396

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

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

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

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

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

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

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

    
490
        } };
491
        return trustAllCerts;
492
    }
493
}
(21-21/23)