Project

General

Profile

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

    
11
package eu.etaxonomy.cdm.common;
12

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

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

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

    
58
/**
59
 * @author n.hoffmann
60
 * @created 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<String, String>();
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<String, String>();
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 Conten-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.
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.
363
     */
364
    public static boolean isServiceAvailable(URI serviceUri, Integer timeout){
365
        boolean result = false;
366

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

    
371
        //Http
372
        HttpClient  client = new DefaultHttpClient();
373
        if(timeout!=null){
374
            HttpConnectionParams.setConnectionTimeout(client.getParams(), timeout);
375
        }
376
        HttpUriRequest request = new HttpHead(serviceUri);
377

    
378
        try {
379
            // Execute the request
380
            HttpResponse response = client.execute(request);
381
            // Examine the response status
382
            if (logger.isDebugEnabled()){
383
                logger.debug(response.getStatusLine());
384
            }
385
             result = true;
386

    
387
        } catch (UnknownHostException e1) {
388
            logger.info("Unknown Host: " +e1.getMessage());
389
        } catch (ClientProtocolException e2) {
390
            logger.info("ClientProtocolException: " + e2.getMessage());
391
        } catch (IOException e3) {
392
            logger.info("IOException: " + e3.getMessage());
393
        }
394

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

    
401
        return result;
402
    }
403

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

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

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

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

    
480
    private static TrustManager[] getTrustingManager() {
481
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
482
            @Override
483
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
484
                return null;
485
            }
486

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

    
492
            @Override
493
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
494
                // Do nothing
495
            }
496

    
497
        } };
498
        return trustAllCerts;
499
    }
500
}
(15-15/17)