Project

General

Profile

Download (18 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.URI;
19
import java.net.URISyntaxException;
20
import java.net.URL;
21
import java.net.UnknownHostException;
22
import java.security.KeyManagementException;
23
import java.security.NoSuchAlgorithmException;
24
import java.security.cert.X509Certificate;
25
import java.util.ArrayList;
26
import java.util.HashMap;
27
import java.util.List;
28
import java.util.Map;
29
import java.util.Map.Entry;
30

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

    
35
import org.apache.http.Header;
36
import org.apache.http.HttpEntity;
37
import org.apache.http.HttpException;
38
import org.apache.http.HttpResponse;
39
import org.apache.http.HttpStatus;
40
import org.apache.http.NameValuePair;
41
import org.apache.http.StatusLine;
42
import org.apache.http.client.ClientProtocolException;
43
import org.apache.http.client.HttpClient;
44
import org.apache.http.client.config.RequestConfig;
45
import org.apache.http.client.methods.HttpGet;
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.log4j.Logger;
56

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

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

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

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

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

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

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

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

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

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

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

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

    
137
                return Long.valueOf(value);
138

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

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

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

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

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

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

    
204
    /**
205
     * Sends a HTTP request of the given {@link HttpMethod} 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 httpMethod defines if method is POST or GET
209
     * @param entity the {@link HttpEntity} attached to a HTTP POST request
210
     * @return the {@link HttpResponse} of the request
211
     * @throws IOException
212
     * @throws ClientProtocolException
213
     */
214
    public static HttpResponse getResponseByType(URI uri, Map<String, String> requestHeaders, HttpMethod httpMethod, HttpEntity entity) throws IOException, ClientProtocolException {
215
        // Create an instance of HttpClient.
216
        HttpClient client = new DefaultHttpClient();
217

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

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

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

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

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

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

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

    
271
        String path = baseUrl.getPath();
272

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

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

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

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

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

    
330
        return result;
331
    }
332

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

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

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

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

    
361

    
362
        if(timeout!=null){
363

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

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

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

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

    
395
        return result;
396
    }
397

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

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

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

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

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

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

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

    
491
        } };
492
        return trustAllCerts;
493
    }
494
}
(20-20/22)