JAL-1054 Add wrappers for URL.openConnection(), URL.openStream() to allow following...
[jalview.git] / src / jalview / util / HttpUtils.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.util;
22
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.net.HttpURLConnection;
26 import java.net.ProtocolException;
27 import java.net.URL;
28
29 import javax.ws.rs.HttpMethod;
30
31 import jalview.bin.Cache;
32
33 public class HttpUtils
34 {
35
36   /**
37    * Returns true if it is possible to open an input stream at the given URL,
38    * else false. The input stream is closed.
39    * 
40    * @param url
41    * @return
42    */
43   public static boolean isValidUrl(String url)
44   {
45     InputStream is = null;
46     try
47     {
48       is = HttpUtils.openStream(new URL(url));
49       if (is != null)
50       {
51         return true;
52       }
53     } catch (IOException x)
54     {
55       // MalformedURLException, FileNotFoundException
56       return false;
57     } finally
58     {
59       if (is != null)
60       {
61         try
62         {
63           is.close();
64         } catch (IOException e)
65         {
66           // ignore
67         }
68       }
69     }
70     return false;
71   }
72
73   public static boolean startsWithHttpOrHttps(String file)
74   {
75     return file.startsWith("http://") || file.startsWith("https://");
76   }
77
78   /**
79    * wrapper to get/post to a URL or check headers
80    * 
81    * @param url
82    * @param ids
83    * @param readTimeout
84    * @return
85    * @throws IOException
86    * @throws ProtocolException
87    */
88   public static boolean checkUrlAvailable(URL url, int readTimeout)
89           throws IOException, ProtocolException
90   {
91     // jalview.bin.Console.outPrintln(System.currentTimeMillis() + " " + url);
92
93     HttpURLConnection connection = (HttpURLConnection) url.openConnection();
94     connection.setRequestMethod(HttpMethod.HEAD);
95     connection.setDoInput(true);
96     connection.setUseCaches(false);
97     connection.setConnectTimeout(300);
98     connection.setReadTimeout(readTimeout);
99
100     // HttpURLConnection doesn't follow redirects from http to https. It should!
101     HttpURLConnection conn = followConnection(connection);
102     return conn.getResponseCode() == 200;
103   }
104
105   /**
106    * wrapper to follow a URL connection ALLOWING redirects from http to https
107    * 
108    * @param URL
109    *          url
110    * @return HttpUrlConnection conn
111    */
112   public static HttpURLConnection openConnection(URL url) throws IOException
113   {
114     if (url == null)
115     {
116       return null;
117     }
118     HttpURLConnection conn = null;
119     if (url != null && url.getProtocol().startsWith("http"))
120     {
121       HttpURLConnection conn0 = (HttpURLConnection) url.openConnection();
122       if (conn0 != null)
123       {
124         conn = HttpUtils.followConnection(conn0);
125       }
126       else
127       {
128         conn = conn0;
129       }
130     }
131     return conn;
132   }
133
134   /**
135    * wrapper to follow a URL connection ALLOWING redirects from http to https
136    * 
137    * @param HttpURLConnection
138    *          conn0
139    * @return HttpUrlConnection conn
140    */
141   public static HttpURLConnection followConnection(HttpURLConnection conn0)
142           throws IOException
143   {
144     HttpURLConnection newConn = null;
145     URL url = conn0.getURL();
146     if (url == null)
147     {
148       return null;
149     }
150     int response = conn0.getResponseCode();
151     boolean followed = false;
152     if (response >= 300 && response < 400 && conn0.getFollowRedirects())
153     {
154       // we are only checking for a redirect from http to https
155       if ("http".equals(url.getProtocol()))
156       {
157         URL loc = new URL(conn0.getHeaderField("Location"));
158         if (loc != null && "https".equals(loc.getProtocol()))
159         {
160           newConn = (HttpURLConnection) loc.openConnection();
161           newConn.setRequestMethod(conn0.getRequestMethod());
162           newConn.setDoInput(conn0.getDoInput());
163           newConn.setUseCaches(conn0.getUseCaches());
164           newConn.setConnectTimeout(conn0.getConnectTimeout());
165           newConn.setReadTimeout(conn0.getReadTimeout());
166           newConn.setInstanceFollowRedirects(
167                   conn0.getInstanceFollowRedirects());
168           followed = true;
169         }
170       }
171     }
172     return followed ? newConn : conn0;
173   }
174
175   /**
176    * wrapper to follow a URL connection ALLOWING redirects from http to https
177    * and return the followed InputStream
178    * 
179    * @param URL
180    *          url
181    * @return HttpUrlConnection conn
182    */
183   public static InputStream openStream(URL url) throws IOException
184   {
185     InputStream is = null;
186     if (url != null && url.getProtocol().startsWith("http"))
187     {
188       HttpURLConnection conn = HttpUtils
189               .followConnection((HttpURLConnection) url.openConnection());
190       if (conn != null)
191       {
192         is = conn.getInputStream();
193       }
194     }
195     return is;
196   }
197
198   public static String getUserAgent()
199   {
200     return getUserAgent(null);
201   }
202
203   public static String getUserAgent(String className)
204   {
205     StringBuilder sb = new StringBuilder();
206     sb.append("Jalview");
207     sb.append('/');
208     sb.append(Cache.getDefault("VERSION", "Unknown"));
209     sb.append(" (");
210     sb.append(System.getProperty("os.name"));
211     sb.append("; ");
212     sb.append(System.getProperty("os.arch"));
213     sb.append(' ');
214     sb.append(System.getProperty("os.name"));
215     sb.append(' ');
216     sb.append(System.getProperty("os.version"));
217     sb.append("; ");
218     sb.append("java/");
219     sb.append(System.getProperty("java.version"));
220     sb.append("; ");
221     sb.append("jalview/");
222     sb.append(ChannelProperties.getProperty("channel"));
223     if (className != null)
224     {
225       sb.append("; ");
226       sb.append(className);
227     }
228     String installation = Cache.applicationProperties
229             .getProperty("INSTALLATION");
230     if (installation != null)
231     {
232       sb.append("; ");
233       sb.append(installation);
234     }
235     sb.append(')');
236     sb.append(" help@jalview.org");
237     return sb.toString();
238   }
239
240 }