2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.common
;
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
;
20 import java
.net
.URISyntaxException
;
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
;
30 import java
.util
.Map
.Entry
;
32 import javax
.net
.ssl
.SSLContext
;
33 import javax
.net
.ssl
.TrustManager
;
34 import javax
.net
.ssl
.X509TrustManager
;
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
;
63 public class UriUtils
{
64 private static final Logger logger
= Logger
.getLogger(UriUtils
.class);
66 protected static final String URI_IS_NOT_ABSOLUTE
= "URI is not absolute (protocol is missing)";
69 public enum HttpMethod
{
75 * see {@link #getInputStream(URI, Map)}
80 * @throws HttpException
82 public static InputStream
getInputStream(URI uri
) throws IOException
, HttpException
{
83 return getInputStream(uri
, null);
87 * Retrieves an {@link InputStream input stream} of the resource located at the given uri.
92 * @throws HttpException
94 public static InputStream
getInputStream(URI uri
, Map
<String
, String
> requestHeaders
) throws IOException
, HttpException
{
96 if(requestHeaders
== null){
97 requestHeaders
= new HashMap
<String
, String
>();
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
);
106 throw new HttpException("HTTP Reponse code is not = 200 (OK): " + UriUtils
.getStatus(response
));
108 }else if (uri
.getScheme().equals("file")){
109 File file
= new File(uri
);
110 return new FileInputStream(file
);
112 throw new RuntimeException("Protocol not handled yet: " + uri
.getScheme());
117 * Retrieves the size of the resource defined by the given uri in bytes
119 * @param uri the resource
120 * @param requestHeaders additional headers. May be <code>null</code>
121 * @return the size of the resource in bytes
123 * @throws ClientProtocolException
124 * @throws IOException
125 * @throws HttpException
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
>();
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");
139 if(contentLengths
== null || contentLengths
.length
== 0){
140 throw new HttpException("Could not retrieve Content-Length");
143 if(contentLengths
.length
> 1){
144 throw new HttpException("Multiple Conten-Length headers sent");
147 Header contentLength
= contentLengths
[0];
148 String value
= contentLength
.getValue();
150 return Long
.valueOf(value
);
153 throw new HttpException("HTTP Reponse code is not = 200 (OK): " + UriUtils
.getStatus(response
));
155 }else if ("file".equals(uri
.getScheme())){
156 File file
= new File(uri
);
157 return file
.length();
159 throw new RuntimeException("Protocol not handled yet: " + uri
.getScheme());
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
168 public static boolean isOk(HttpResponse response
){
169 return response
.getStatusLine().getStatusCode() == HttpStatus
.SC_OK
;
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
178 public static InputStream
getContent(HttpResponse response
) throws IOException
{
179 return response
.getEntity().getContent();
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
187 public static String
getStatus(HttpResponse response
){
188 StatusLine statusLine
= response
.getStatusLine();
189 return "(" + statusLine
.getStatusCode() + ")" + statusLine
.getReasonPhrase();
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
200 public static HttpResponse
getResponse(URI uri
, Map
<String
, String
> requestHeaders
) throws ClientProtocolException
, IOException
{
201 return getResponseByType(uri
, requestHeaders
, HttpMethod
.GET
, null);
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
213 public static HttpResponse
getPostResponse(URI uri
, Map
<String
, String
> requestHeaders
, HttpEntity entity
) throws ClientProtocolException
, IOException
{
214 return getResponseByType(uri
, requestHeaders
, HttpMethod
.POST
, entity
);
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
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();
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
);
244 HttpUriRequest method
;
245 switch (httpMethod
) {
247 method
= new HttpGet(uri
);
250 HttpPost httpPost
= new HttpPost(uri
);
252 httpPost
.setEntity(entity
);
257 method
= new HttpPost(uri
);
261 // configure the connection
262 if(requestHeaders
!= null){
263 for(Entry
<String
, String
> e
: requestHeaders
.entrySet()){
264 method
.addHeader(e
.getKey(), e
.getValue());
268 //TODO method.setFollowRedirects(followRedirects);
270 logger
.debug("sending "+httpMethod
+" request: " + uri
);
272 return client
.execute(method
);
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
283 public static URI
createUri(URL baseUrl
, String subPath
, List
<NameValuePair
> qparams
, String fragment
) throws URISyntaxException
{
285 String path
= baseUrl
.getPath();
288 if(!path
.endsWith("/")){
291 if(subPath
.startsWith("/")){
292 subPath
= subPath
.substring(1);
298 qparams
= new ArrayList
<NameValuePair
>(0);
301 if(! qparams
.isEmpty()){
302 query
= URLEncodedUtils
.format(qparams
, "UTF-8");
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();
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.
321 public static boolean isInternetAvailable(URI firstUriToTest
){
322 boolean result
= false;
323 if (firstUriToTest
!= null && isServiceAvailable(firstUriToTest
)){
327 URI uri
= URI
.create("http://www.cnn.com/");
328 if (isServiceAvailable(uri
)){
331 uri
= URI
.create("http://www.bahn.de/");
332 if (isServiceAvailable(uri
)){
335 uri
= URI
.create("http://www.google.com/");
336 if (isServiceAvailable(uri
)){
339 uri
= URI
.create("http://www.facebook.com/");
340 if (isServiceAvailable(uri
)){
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.
353 public static boolean isServiceAvailable(URI serviceUri
){
354 return isServiceAvailable(serviceUri
, null);
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.
364 public static boolean isServiceAvailable(URI serviceUri
, Integer timeout
){
365 boolean result
= false;
367 if(serviceUri
==null || serviceUri
.getHost()==null || !serviceUri
.isAbsolute()){
372 CloseableHttpClient httpclient
= HttpClients
.createDefault();
373 HttpGet httpget
= new HttpGet(serviceUri
);
378 RequestConfig requestConfig
= RequestConfig
.custom()
379 .setSocketTimeout(timeout
)
380 .setConnectTimeout(timeout
)
381 .setConnectionRequestTimeout(timeout
)
383 httpget
.setConfig(requestConfig
);
387 // Execute the request
388 HttpResponse response
= httpclient
.execute(httpget
);
389 // Examine the response status
390 if (logger
.isDebugEnabled()){
391 logger
.debug(response
.getStatusLine());
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());
403 // When HttpClient instance is no longer needed,
404 // shut down the connection manager to ensure
405 // immediate deallocation of all system resources
407 // client.getConnectionManager().shutdown();
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.
418 public static boolean isRootServerAvailable(String hostNameToResolve
){
420 if (hostNameToResolve
== null){
421 hostNameToResolve
= "cnn.com";
423 InetAddress inetHost
= InetAddress
.getByName(hostNameToResolve
);
424 logger
.debug("The hosts IP address is: " + inetHost
.getHostAddress());
426 } catch(UnknownHostException ex
) {
427 logger
.info("Unrecognized host");
432 //from http://www.javabeginners.de/Netzwerk/File_zu_URL.php
433 public static URL
fileToURL(File file
){
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
) {
446 //from http://blogs.sphinx.at/java/erzeugen-von-javaiofile-aus-javaneturl/
447 public static File
urlToFile(URL url
) {
450 // this is the step that can fail, and so
451 // it should be this step that should be fixed
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
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
);
471 return new File(uri
);
474 public static boolean checkServiceAvailable(String host
, int port
){
475 boolean success
= true;
477 (new Socket(host
, port
)).close();
478 } catch (UnknownHostException e
) {
481 } catch (IOException e
) {
482 // io exception, service probably not running
488 private static TrustManager
[] getTrustingManager() {
489 TrustManager
[] trustAllCerts
= new TrustManager
[] { new X509TrustManager() {
491 public java
.security
.cert
.X509Certificate
[] getAcceptedIssuers() {
496 public void checkClientTrusted(X509Certificate
[] certs
, String authType
) {
501 public void checkServerTrusted(X509Certificate
[] certs
, String authType
) {
506 return trustAllCerts
;