Clover icon

Coverage Report

  1. Project Clover database Thu Dec 4 2025 16:11:35 GMT
  2. Package jalview.util

File HttpUtils.java

 

Coverage histogram

../../img/srcFileCovDistChart5.png
43% of files have more coverage

Code metrics

52
132
14
1
425
308
57
0.43
9.43
14
4.07

Classes

Class Line # Actions
HttpUtils 36 132 57
0.4646464646.5%
 

Contributing tests

This file is covered by 167 tests. .

Source view

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.BufferedInputStream;
24    import java.io.File;
25    import java.io.FileOutputStream;
26    import java.io.IOException;
27    import java.io.InputStream;
28    import java.net.HttpURLConnection;
29    import java.net.MalformedURLException;
30    import java.net.ProtocolException;
31    import java.net.URI;
32    import java.net.URISyntaxException;
33    import java.net.URL;
34    import java.net.URLConnection;
35   
 
36    public class HttpUtils
37    {
38    public final static String JALVIEWSCHEMEPREFIX = "jalview";
39   
 
40  172 toggle public static boolean isPlausibleUri(String s)
41    {
42  172 if (s == null)
43    {
44  0 return false;
45    }
46  172 if (startsWithHttpOrHttps(s) || isJalviewSchemeUri(s))
47    {
48  3 return true;
49    }
50  169 try
51    {
52  169 URI u = new URI(s);
53    // allow file:/home/... as well as file:///home... as java copes
54  169 if (s.startsWith("file:/"))
55    {
56  0 return true;
57    }
58    } catch (URISyntaxException e)
59    {
60  0 return false;
61    }
62  169 return false;
63    }
64   
65    /**
66    * Returns true if it is possible to open an input stream at the given URL,
67    * else false. The input stream is closed.
68    *
69    * @param url
70    * @return
71    */
 
72  0 toggle public static boolean isValidUrl(String url)
73    {
74  0 InputStream is = null;
75  0 try
76    {
77  0 is = HttpUtils.openStream(new URL(url));
78  0 if (is != null)
79    {
80  0 return true;
81    }
82    } catch (IOException x)
83    {
84    // MalformedURLException, FileNotFoundException
85  0 return false;
86    } finally
87    {
88  0 if (is != null)
89    {
90  0 try
91    {
92  0 is.close();
93    } catch (IOException e)
94    {
95    // ignore
96    }
97    }
98    }
99  0 return false;
100    }
101   
 
102  403 toggle public static boolean startsWithHttpOrHttps(String file)
103    {
104  403 return file.startsWith("http://") || file.startsWith("https://");
105    }
106   
107   
108    /**
109    * wrapper to get/post to a URL or check headers
110    * @param url
111    * @param ids
112    * @param readTimeout
113    * @return
114    * @throws IOException
115    * @throws ProtocolException
116    */
 
117  0 toggle public static boolean checkUrlAvailable(URL url,
118    int readTimeout) throws IOException, ProtocolException
119    {
120    // jalview.bin.Console.outPrintln(System.currentTimeMillis() + " " + url);
121   
122  0 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
123  0 connection.setRequestMethod("HEAD");
124  0 connection.setDoInput(true);
125  0 connection.setUseCaches(false);
126  0 connection.setConnectTimeout(300);
127  0 connection.setReadTimeout(readTimeout);
128   
129    // HttpURLConnection doesn't follow redirects from http to https. It should!
130  0 HttpURLConnection conn = followConnection(connection);
131  0 return conn.getResponseCode() == 200;
132    }
133   
134    /**
135    * wrapper to return a new HttpURLConnection to a new URL when there is a
136    * redirect from http to https, otherwise return the unused original
137    * HttpURLConnection
138    *
139    * @param HttpURLConnection
140    * conn0
141    * @return HttpUrlConnection conn
142    */
 
143  12 toggle public static HttpURLConnection followConnection(HttpURLConnection conn0)
144    throws IOException
145    {
146  12 return followConnection(conn0, false);
147    }
148   
 
149  449 toggle public static HttpURLConnection followConnection(HttpURLConnection conn0,
150    boolean followAnyway) throws IOException
151    {
152  449 URL url = conn0.getURL();
153    // we are only checking for a redirect from http to https otherwise the java
154    // connection will follow when called (if not unset)
155  449 if (url == null)
156    {
157  0 return conn0;
158    }
159  449 if (!conn0.getInstanceFollowRedirects())
160    {
161  0 return conn0;
162    }
163  449 if (!"http".equals(url.getProtocol()) && !followAnyway)
164    {
165  289 return conn0;
166    }
167   
168    // check the response code
169  160 HttpURLConnection checkConn = (HttpURLConnection) url.openConnection();
170  160 httpURLConnectionCopyAttributes(conn0, checkConn);
171   
172  160 boolean redirectToHttps = false;
173  160 int response = checkConn.getResponseCode();
174  160 checkConn.disconnect();
175  160 if (response >= 300 && response < 400)
176    {
177    // we are only checking for a redirect from http to https
178  0 URL loc = new URL(conn0.getHeaderField("Location"));
179  0 if (loc != null && "https".equals(loc.getProtocol()))
180    {
181  0 redirectToHttps = true;
182  0 url = loc;
183    }
184    }
185  160 else if (followAnyway)
186    {
187    // checkConn might have followed a https->https redirect
188  0 url = checkConn.getURL();
189    }
190   
191  160 if (!redirectToHttps && !followAnyway)
192    {
193  160 return conn0;
194    }
195   
196    // We want to return an HttpURLConnection to the new (probably https) URL
197    // that is unconnected in case further manipulation of the request is
198    // required.
199  0 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
200  0 httpURLConnectionCopyAttributes(conn0, conn);
201  0 return conn;
202    }
203   
 
204  160 toggle private static void httpURLConnectionCopyAttributes(
205    HttpURLConnection conn0, HttpURLConnection conn1)
206    throws ProtocolException
207    {
208  160 conn1.setRequestMethod(conn0.getRequestMethod());
209  160 conn1.setDoInput(conn0.getDoInput());
210  160 conn1.setUseCaches(conn0.getUseCaches());
211  160 conn1.setConnectTimeout(conn0.getConnectTimeout());
212  160 conn1.setReadTimeout(conn0.getReadTimeout());
213  160 conn1.setInstanceFollowRedirects(conn0.getInstanceFollowRedirects());
214    }
215   
216    /**
217    * wrapper to follow a URL connection ALLOWING redirects from http to https
218    *
219    * @param URL
220    * url
221    * @return HttpUrlConnection conn
222    */
 
223  16 toggle public static URLConnection openConnection(URL url) throws IOException
224    {
225  16 return openConnection(url, false);
226    }
227   
 
228  16 toggle public static URLConnection openConnection(URL url, boolean followAnyway)
229    throws IOException
230    {
231  16 if (url == null)
232    {
233  0 LaunchUtils.syserr(false, true,
234    "HttpUtils.openConnection(url) called with null url");
235  0 return null;
236    }
237  16 LaunchUtils.syserr(false, true,
238    "HttpUtils.openConnection(url) called with url="
239    + url.toString());
240  16 URLConnection conn = null;
241  16 String protocol = url.getProtocol();
242  16 if ("http".equals(protocol) || "https".equals(protocol))
243    {
244  14 HttpURLConnection conn0 = (HttpURLConnection) url.openConnection();
245  14 if (conn0 != null)
246    {
247  14 conn = HttpUtils.followConnection(conn0, followAnyway);
248    }
249    else
250    {
251  0 conn = conn0;
252    }
253    }
254    else
255    {
256  2 conn = url.openConnection();
257    }
258  16 return conn;
259    }
260   
261    /**
262    * wrapper to follow a URL connection ALLOWING redirects from http to https
263    * and return the followed InputStream
264    *
265    * @param URL
266    * url
267    * @return HttpUrlConnection conn
268    */
 
269  591 toggle public static InputStream openStream(URL url) throws IOException
270    {
271  591 return openStream(url, false);
272    }
273   
 
274  591 toggle public static InputStream openStream(URL url, boolean followAnyway)
275    throws IOException
276    {
277  591 if (url == null)
278    {
279  0 return null;
280    }
281  591 InputStream is = null;
282  591 String protocol = url.getProtocol();
283  591 if ("http".equals(protocol) || "https".equals(protocol))
284    {
285  423 HttpURLConnection conn = HttpUtils.followConnection(
286    (HttpURLConnection) url.openConnection(), followAnyway);
287  423 if (conn != null)
288    {
289  423 is = conn.getInputStream();
290    }
291    }
292    else
293    {
294  168 is = url.openStream();
295    }
296  480 return is;
297    }
298   
299    /**
300    * check if a jalview:// scheme URL is given
301    *
302    * @param String
303    * uri
304    * @return boolean
305    */
 
306  341 toggle public static boolean isJalviewSchemeUri(String jalviewUriString)
307    {
308  341 if (jalviewUriString == null)
309    {
310  0 return false;
311    }
312  341 URI jalviewUri;
313  341 try
314    {
315  341 jalviewUri = new URI(jalviewUriString);
316    } catch (URISyntaxException e)
317    {
318  0 return false;
319    }
320  341 String scheme = jalviewUri.getScheme();
321  341 if (scheme == null || !scheme.startsWith(JALVIEWSCHEMEPREFIX))
322    {
323  341 return false;
324    }
325  0 int jspl = JALVIEWSCHEMEPREFIX.length();
326  0 return scheme.length() == jspl // jalview
327    || scheme.length() == jspl + 1 // jalviewX
328    || scheme.substring(jspl).equals("http") // jalviewhttp
329    || scheme.substring(jspl).equals("https"); // jalviewhttps
330    }
331   
332    /**
333    * convert a jalview scheme URI to its equivalent URL or path
334    *
335    * @param String
336    * uri
337    * @return String
338    */
 
339  172 toggle public static String equivalentJalviewUrl(String jalviewUriString)
340    {
341  172 if (!isJalviewSchemeUri(jalviewUriString))
342    {
343    // not a jalviewUriString, hand it back
344  172 return jalviewUriString;
345    }
346  0 URI jalviewUri;
347  0 try
348    {
349  0 jalviewUri = new URI(jalviewUriString);
350    } catch (URISyntaxException e)
351    {
352  0 return null;
353    }
354  0 String scheme = jalviewUri.getScheme();
355  0 String host = jalviewUri.getHost();
356  0 if (host != null && host.length() > 0 || scheme
357    .substring(JALVIEWSCHEMEPREFIX.length()).startsWith("http"))
358    {
359  0 URI newUri;
360  0 try
361    {
362  0 newUri = new URI(
363  0 scheme.equals(JALVIEWSCHEMEPREFIX + "http") ? "http"
364    : "https",
365    jalviewUri.getUserInfo(), host, jalviewUri.getPort(),
366    jalviewUri.getPath(), jalviewUri.getQuery(),
367    jalviewUri.getFragment());
368    // return a URL
369  0 return newUri.toURL().toString();
370    } catch (URISyntaxException | MalformedURLException e)
371    {
372  0 ErrorLog.errPrintln("Trying to convert '" + jalviewUriString
373    + "' to URL failed");
374    }
375    }
376    else
377    {
378    // return a file path (not a file URI)
379  0 return jalviewUri.getPath();
380    }
381  0 return null;
382    }
383    /**
384    * download from given URL and return a pointer to temporary file
385    */
 
386  0 toggle public static File fetchURLToTemp(String url) throws OutOfMemoryError,
387    IOException
388    {
389  0 long time = System.currentTimeMillis();
390  0 URL rcall = new URL(url);
391   
392  0 InputStream is = new BufferedInputStream(rcall.openStream());
393  0 File outFile = null;
394  0 try
395    {
396  0 outFile = File.createTempFile("jalview", ".xml");
397  0 outFile.deleteOnExit();
398  0 if (outFile.length() == 0)
399    {
400  0 outFile.delete();
401  0 return null;
402    }
403    } catch (Exception ex)
404    {
405    }
406   
407  0 if (outFile != null)
408    {
409  0 FileOutputStream fio = new FileOutputStream(outFile);
410  0 byte[] bb = new byte[32 * 1024];
411  0 int l;
412  0 while ((l = is.read(bb)) > 0)
413    {
414  0 fio.write(bb, 0, l);
415    }
416  0 fio.close();
417  0 is.close();
418  0 return outFile;
419    }
420    else
421    {
422  0 return null;
423    }
424    }
425    }