Project

General

Profile

Download (16.1 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.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 org.apache.http.Header;
31
import org.apache.http.HttpEntity;
32
import org.apache.http.HttpException;
33
import org.apache.http.HttpResponse;
34
import org.apache.http.HttpStatus;
35
import org.apache.http.NameValuePair;
36
import org.apache.http.StatusLine;
37
import org.apache.http.client.ClientProtocolException;
38
import org.apache.http.client.HttpClient;
39
import org.apache.http.client.methods.HttpGet;
40
import org.apache.http.client.methods.HttpHead;
41
import org.apache.http.client.methods.HttpPost;
42
import org.apache.http.client.methods.HttpUriRequest;
43
import org.apache.http.client.utils.URIBuilder;
44
import org.apache.http.client.utils.URLEncodedUtils;
45
import org.apache.http.impl.client.DefaultHttpClient;
46
import org.apache.http.params.HttpConnectionParams;
47
import org.apache.log4j.Logger;
48

    
49
/**
50
 * @author n.hoffmann
51
 * @created Sep 23, 2010
52
 * @version 1.0
53
 */
54
public class UriUtils {
55
    private static final Logger logger = Logger.getLogger(UriUtils.class);
56

    
57
    protected static final String URI_IS_NOT_ABSOLUTE = "URI is not absolute (protocol is missing)";
58
	
59
    
60
    public enum HttpMethod{
61
        GET,
62
        POST
63
    }
64

    
65
    /**
66
     * see {@link #getInputStream(URI, Map)}
67
     *
68
     * @param uri
69
     * @return
70
     * @throws IOException
71
     * @throws HttpException
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
     * @param uri
81
     * @return
82
     * @throws IOException
83
     * @throws HttpException
84
     */
85
    public static InputStream getInputStream(URI uri, Map<String, String> requestHeaders) throws IOException, HttpException{
86

    
87
        if(requestHeaders == null){
88
            requestHeaders = new HashMap<String, String>();
89
        }
90

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

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

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

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

    
134
                if(contentLengths.length > 1){
135
                    throw new HttpException("Multiple Conten-Length headers sent");
136
                }
137

    
138
                Header contentLength = contentLengths[0];
139
                String value = contentLength.getValue();
140

    
141
                return Long.valueOf(value);
142

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

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

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

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

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

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

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

    
222
        HttpUriRequest method;
223
        switch (httpMethod) {
224
        case GET:
225
            method = new HttpGet(uri);
226
            break;
227
        case POST:
228
            HttpPost httpPost = new HttpPost(uri);
229
            if(entity!=null){
230
                httpPost.setEntity(entity);
231
            }
232
            method = httpPost;
233
            break;
234
        default:
235
            method = new HttpPost(uri);
236
            break;
237
        }
238

    
239
        // configure the connection
240
        if(requestHeaders != null){
241
            for(Entry<String, String> e : requestHeaders.entrySet()){
242
                method.addHeader(e.getKey(), e.getValue());
243
            }
244
        }
245

    
246
        //TODO  method.setFollowRedirects(followRedirects);
247

    
248
        logger.debug("sending "+httpMethod+" request: " + uri);
249

    
250
        return client.execute(method);
251
    }
252

    
253
    /**
254
     * Creates a {@link URI} based on the baseUrl and the given subPath, qParams and fragment
255
     * @param subPath the sub path of the URI
256
     * @param qparams the parameters added as GET parameters to the URI
257
     * @param fragment the fragment of the URI
258
     * @return a URI consisting of the baseURL, the subPath and qParams
259
     * @throws URISyntaxException
260
     */
261
    public static URI createUri(URL baseUrl, String subPath, List<NameValuePair> qparams, String fragment) throws	URISyntaxException {
262

    
263
        String path = baseUrl.getPath();
264

    
265
        if(subPath != null){
266
            if(!path.endsWith("/")){
267
                path += "/";
268
            }
269
            if(subPath.startsWith("/")){
270
                subPath = subPath.substring(1);
271
            }
272
            path += subPath;
273
        }
274

    
275
        if(qparams == null){
276
            qparams = new ArrayList<NameValuePair>(0);
277
        }
278
        String query = null;
279
        if(! qparams.isEmpty()){
280
            query = URLEncodedUtils.format(qparams, "UTF-8");
281
        }
282

    
283
        URIBuilder uriBuilder = new URIBuilder();
284
        uriBuilder.setScheme(baseUrl.getProtocol());
285
        uriBuilder.setHost(baseUrl.getHost());
286
        uriBuilder.setPort(baseUrl.getPort());
287
        uriBuilder.setPath(path);
288
        uriBuilder.setQuery(query);
289
        uriBuilder.setFragment(fragment);
290
        return uriBuilder.build();
291
    }
292

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

    
305
        URI uri = URI.create("http://www.cnn.com/");
306
        if (isServiceAvailable(uri)){
307
            return true;
308
        }
309
        uri = URI.create("http://www.bahn.de/");
310
        if (isServiceAvailable(uri)){
311
            return true;
312
        }
313
        uri = URI.create("http://www.google.com/");
314
        if (isServiceAvailable(uri)){
315
            return true;
316
        }
317
        uri = URI.create("http://www.facebook.com/");
318
        if (isServiceAvailable(uri)){
319
            return true;
320
        }
321

    
322
        return result;
323
    }
324

    
325
    /**
326
     * Performs HEAD request for the given URI.<BR>
327
     * If any exception occurs <code>false</code> is returned. Otherwise true. <BR>
328
     * @param serviceUri the URI to test.
329
     * @return true if service is available.
330
     */
331
    public static boolean isServiceAvailable(URI serviceUri){
332
        return isServiceAvailable(serviceUri, null);
333
    }
334

    
335
    /**
336
     * Performs HEAD request for the given URI.<BR>
337
     * If any exception occurs <code>false</code> is returned. Otherwise true. <BR>
338
     * @param serviceUri the URI to test.
339
     * @param timeout the timeout of the request in milliseconds
340
     * @return true if service is available.
341
     */
342
    public static boolean isServiceAvailable(URI serviceUri, Integer timeout){
343
        boolean result = false;
344

    
345
        //Http
346
        HttpClient  client = new DefaultHttpClient();
347
        if(timeout!=null){
348
            HttpConnectionParams.setConnectionTimeout(client.getParams(), timeout);
349
        }
350
        HttpUriRequest request = new HttpHead(serviceUri);
351

    
352
        try {
353
            // Execute the request
354
            HttpResponse response = client.execute(request);
355
            // Examine the response status
356
            if (logger.isDebugEnabled()){
357
                logger.debug(response.getStatusLine());
358
            }
359
             result = true;
360

    
361
        } catch (UnknownHostException e1) {
362
            logger.info("Unknown Host: " +e1.getMessage());
363
        } catch (ClientProtocolException e2) {
364
            logger.info("ClientProtocolException: " + e2.getMessage());
365
        } catch (IOException e3) {
366
            logger.info("IOException: " + e3.getMessage());
367
        }
368

    
369
         // When HttpClient instance is no longer needed,
370
         // shut down the connection manager to ensure
371
         // immediate deallocation of all system resources
372
        //needed ?
373
//	     client.getConnectionManager().shutdown();
374

    
375
        return result;
376
    }
377

    
378
    /**
379
     * Tests reachability of a root server by trying to resolve a host name.
380
     * @param hostNameToResolve the host name to resolve. If <code>null</code>
381
     * a default host name is tested.
382
     * @return
383
     */
384
    public static boolean isRootServerAvailable(String hostNameToResolve){
385
        try {
386
            if (hostNameToResolve == null){
387
                hostNameToResolve = "cnn.com";
388
            }
389
            InetAddress inetHost = InetAddress.getByName(hostNameToResolve);
390
            logger.debug("The hosts IP address is: " + inetHost.getHostAddress());
391
            return true;
392
         } catch(UnknownHostException ex) {
393
             logger.info("Unrecognized host");
394
             return false;
395
         }
396
    }
397

    
398
    //from http://www.javabeginners.de/Netzwerk/File_zu_URL.php
399
    public static URL fileToURL(File file){
400
        URL url = null;
401
        try {
402
            // Sonderzeichen (z.B. Leerzeichen) bleiben erhalten
403
            url = new URL("file://" + file.getPath());
404
            // Sonderzeichen (z.B. Leerzeichen) werden codiert
405
            url = file.toURI().toURL();
406
        } catch (MalformedURLException e) {
407
            e.printStackTrace();
408
        }
409
        return url;
410
    }
411

    
412
    //from http://blogs.sphinx.at/java/erzeugen-von-javaiofile-aus-javaneturl/
413
    public static File urlToFile(URL url) {
414
        URI uri;
415
        try {
416
            // this is the step that can fail, and so
417
            // it should be this step that should be fixed
418
            uri = url.toURI();
419
        } catch (URISyntaxException e) {
420
            // OK if we are here, then obviously the URL did
421
            // not comply with RFC 2396. This can only
422
            // happen if we have illegal unescaped characters.
423
            // If we have one unescaped character, then
424
            // the only automated fix we can apply, is to assume
425
            // all characters are unescaped.
426
            // If we want to construct a URI from unescaped
427
            // characters, then we have to use the component
428
            // constructors:
429
            try {
430
                uri = new URI(url.getProtocol(), url.getUserInfo(), url
431
                        .getHost(), url.getPort(), url.getPath(), url
432
                        .getQuery(), url.getRef());
433
            } catch (URISyntaxException e1) {
434
                throw new IllegalArgumentException("broken URL: " + url);
435
            }
436
        }
437
        return new File(uri);
438
    }
439

    
440
    public static boolean checkServiceAvailable(String host, int port){
441
        boolean success = true;
442
        try {
443
          (new Socket(host, port)).close();
444
        } catch (UnknownHostException e) {
445
          // unknown host
446
          success = false;
447
        } catch (IOException e) {
448
          // io exception, service probably not running
449
          success = false;
450
        }
451
        return success;
452
    }
453
}
(15-15/17)