Clover icon

Coverage Report

  1. Project Clover database Fri Jun 19 2026 11:35:32 BST
  2. Package jalview.util

File Platform.java

 
checkImportPAEToStructure: Exception importing paefile 'examples/AlphaFold/AF-Q5VSL9...
 

Coverage histogram

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

Code metrics

74
140
41
1
809
411
89
0.64
3.41
41
2.17

Classes

Class Line # Actions
Platform 52 140 89
0.5098039551%
 

Contributing tests

This file is covered by 529 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.awt.Toolkit;
24    import java.awt.event.MouseEvent;
25    import java.io.BufferedInputStream;
26    import java.io.BufferedReader;
27    import java.io.File;
28    import java.io.FileOutputStream;
29    import java.io.FileReader;
30    import java.io.IOException;
31    import java.io.InputStream;
32    import java.io.InputStreamReader;
33    import java.io.Reader;
34    import java.net.URL;
35    import java.nio.charset.Charset;
36    import java.util.Properties;
37    import java.util.zip.GZIPInputStream;
38   
39    import javax.swing.SwingUtilities;
40   
41    import org.json.simple.parser.JSONParser;
42    import org.json.simple.parser.ParseException;
43   
44    import jalview.bin.Console;
45    import jalview.javascript.json.JSON;
46   
47    /**
48    * System platform information used by Applet and Application
49    *
50    * @author Jim Procter
51    */
 
52    public class Platform
53    {
54   
55    private static boolean isJS = /** @j2sNative true || */
56    false;
57   
58    private static Boolean isNoJSMac = null, isNoJSWin = null, isMac = null,
59    isWin = null, isLinux = null;
60   
61    private static Boolean isHeadless = null;
62   
63    // If launched from CLI with launcher script then -DCOLUMNWIDTH is set
64    private static final int CONSOLEWIDTH;
65   
66    private static final String CONSOLEWIDTHPROPERTY = "CONSOLEWIDTH";
67   
 
68  55 toggle static
69    {
70  55 int cw = 80;
71  55 if (System.getProperty(CONSOLEWIDTHPROPERTY) != null
72    && System.getProperty(CONSOLEWIDTHPROPERTY).length() > 0)
73    {
74  0 try
75    {
76  0 cw = Integer.parseInt(System.getProperty(CONSOLEWIDTHPROPERTY));
77    } catch (NumberFormatException e)
78    {
79    }
80    }
81  55 CONSOLEWIDTH = cw;
82    }
83   
84    /**
85    * added to group mouse events into Windows and nonWindows (mac, unix, linux)
86    *
87    * @return
88    */
 
89  891 toggle public static boolean isMac()
90    {
91  891 return (isMac == null
92    ? (isMac = (System.getProperty("os.name").indexOf("Mac") >= 0))
93    : isMac);
94    }
95   
96    /**
97    * added to group mouse events into Windows and nonWindows (mac, unix, linux)
98    *
99    * @return
100    */
 
101  3 toggle public static boolean isWin()
102    {
103  3 return (isWin == null
104    ? (isWin = (System.getProperty("os.name").indexOf("Win") >= 0))
105    : isWin);
106    }
107   
108    /**
109    * added to check LaF for Linux
110    *
111    * @return
112    */
 
113  342 toggle public static boolean isLinux()
114    {
115  342 return (isLinux == null
116    ? (isLinux = (System.getProperty("os.name")
117    .indexOf("Linux") >= 0))
118    : isLinux);
119    }
120   
121    /**
122    *
123    * @return true if HTML5 JavaScript
124    */
 
125  285486 toggle public static boolean isJS()
126    {
127  285486 return isJS;
128    }
129   
130    /**
131    * sorry folks - Macs really are different
132    *
133    * BH: disabled for SwingJS -- will need to check key-press issues
134    *
135    * @return true if we do things in a special way.
136    */
 
137  6955 toggle public static boolean isAMacAndNotJS()
138    {
139  6955 return (isNoJSMac == null ? (isNoJSMac = !isJS && isMac()) : isNoJSMac);
140    }
141   
142    /**
143    * Check if we are on a Microsoft plaform...
144    *
145    * @return true if we have to cope with another platform variation
146    */
 
147  0 toggle public static boolean isWindowsAndNotJS()
148    {
149  0 return (isNoJSWin == null ? (isNoJSWin = !isJS && isWin()) : isNoJSWin);
150    }
151   
152    /**
153    *
154    * @return true if we are running in non-interactive no UI mode
155    */
 
156  1443 toggle public static boolean isHeadless()
157    {
158  1443 if (isHeadless == null)
159    {
160  21 isHeadless = "true".equals(System.getProperty("java.awt.headless"));
161    }
162  1443 return isHeadless;
163    }
164   
165    /**
166    *
167    * @return nominal maximum command line length for this platform
168    */
 
169  0 toggle public static int getMaxCommandLineLength()
170    {
171    // TODO: determine nominal limits for most platforms.
172  0 return 2046; // this is the max length for a windows NT system.
173    }
174   
175    /**
176    * Answers the input with every backslash replaced with a double backslash (an
177    * 'escaped' single backslash)
178    *
179    * @param s
180    * @return
181    */
 
182  101 toggle public static String escapeBackslashes(String s)
183    {
184  101 return s == null ? null : s.replace("\\", "\\\\");
185    }
186   
187    /**
188    * Answers true if the mouse event has Meta-down (Command key on Mac) or
189    * Ctrl-down (on other o/s). Note this answers _false_ if the Ctrl key is
190    * pressed instead of the Meta/Cmd key on Mac. To test for Ctrl-pressed on
191    * Mac, you can use e.isPopupTrigger().
192    *
193    * @param e
194    * @return
195    */
 
196  3 toggle public static boolean isControlDown(MouseEvent e)
197    {
198  3 return isControlDown(e, isMac());
199    }
200   
201    /**
202    * Overloaded version of method (to allow unit testing)
203    *
204    * @param e
205    * @param aMac
206    * @return
207    */
 
208  6 toggle protected static boolean isControlDown(MouseEvent e, boolean aMac)
209    {
210  6 if (!aMac)
211    {
212  6 return e.isControlDown();
213   
214    // Jalview 2.11 code below: above is as amended for JalviewJS
215    // /*
216    // * answer false for right mouse button
217    // */
218    // if (e.isPopupTrigger())
219    // {
220    // return false;
221    // }
222    // return
223    // (jalview.util.ShortcutKeyMaskExWrapper.getMenuShortcutKeyMaskEx() //
224    // .getMenuShortcutKeyMaskEx()
225    // & jalview.util.ShortcutKeyMaskExWrapper
226    // .getModifiersEx(e)) != 0; // getModifiers()) != 0;
227    }
228    // answer false for right mouse button
229    // shortcut key will be META for a Mac
230  0 return !e.isPopupTrigger()
231    && (Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
232    & e.getModifiers()) != 0;
233    // could we use e.isMetaDown() here?
234    }
235   
236    // BH: I don't know about that previous method. Here is what SwingJS uses.
237    // Notice the distinction in mouse events. (BUTTON3_MASK == META)
238    //
239    // private static boolean isPopupTrigger(int id, int mods, boolean isWin) {
240    // boolean rt = ((mods & InputEvent.BUTTON3_MASK) != 0);
241    // if (isWin) {
242    // if (id != MouseEvent.MOUSE_RELEASED)
243    // return false;
244    ////
245    //// // Oddly, Windows returns InputEvent.META_DOWN_MASK on release, though
246    //// // BUTTON3_DOWN_MASK for pressed. So here we just accept both.
247    ////
248    //// actually, we can use XXX_MASK, not XXX_DOWN_MASK and avoid this issue,
249    // because
250    //// J2S adds the appropriate extended (0x3FC0) and simple (0x3F) modifiers.
251    ////
252    // return rt;
253    // } else {
254    // // mac, linux, unix
255    // if (id != MouseEvent.MOUSE_PRESSED)
256    // return false;
257    // boolean lt = ((mods & InputEvent.BUTTON1_MASK) != 0);
258    // boolean ctrl = ((mods & InputEvent.CTRL_MASK) != 0);
259    // return rt || (ctrl && lt);
260    // }
261    // }
262    //
263   
264    /**
265    * Windows (not Mac, Linux, or Unix) and right button to test for the
266    * right-mouse pressed event in Windows that would have opened a menu or a
267    * Mac.
268    *
269    * @param e
270    * @return
271    */
 
272  3 toggle public static boolean isWinRightButton(MouseEvent e)
273    {
274    // was !isAMac(), but that is true also for Linux and Unix and JS,
275   
276  3 return isWin() && SwingUtilities.isRightMouseButton(e);
277    }
278   
279    /**
280    * Windows (not Mac, Linux, or Unix) and middle button -- for mouse wheeling
281    * without pressing the button.
282    *
283    * @param e
284    * @return
285    */
 
286  0 toggle public static boolean isWinMiddleButton(MouseEvent e)
287    {
288    // was !isAMac(), but that is true also for Linux and Unix and JS
289  0 return isWin() && SwingUtilities.isMiddleMouseButton(e);
290    }
291   
 
292  578 toggle public static boolean allowMnemonics()
293    {
294  578 return !isMac();
295    }
296   
297    public final static int TIME_RESET = 0;
298   
299    public final static int TIME_MARK = 1;
300   
301    public static final int TIME_SET = 2;
302   
303    public static final int TIME_GET = 3;
304   
305    public static long time, mark, set, duration;
306   
 
307  0 toggle public static void timeCheck(String msg, int mode)
308    {
309  0 long t = System.currentTimeMillis();
310  0 switch (mode)
311    {
312  0 case TIME_RESET:
313  0 time = mark = t;
314  0 if (msg != null)
315    {
316  0 jalview.bin.Console.errPrintln("Platform: timer reset\t\t\t" + msg);
317    }
318  0 break;
319  0 case TIME_MARK:
320  0 if (set > 0)
321    {
322  0 duration += (t - set);
323    }
324    else
325    {
326  0 if (time == 0)
327    {
328  0 time = mark = t;
329    }
330  0 if (msg != null)
331    {
332  0 jalview.bin.Console.errPrintln(
333    "Platform: timer mark\t" + ((t - time) / 1000f) + "\t"
334    + ((t - mark) / 1000f) + "\t" + msg);
335    }
336  0 mark = t;
337    }
338  0 break;
339  0 case TIME_SET:
340  0 set = t;
341  0 break;
342  0 case TIME_GET:
343  0 if (msg != null)
344    {
345  0 jalview.bin.Console
346    .errPrintln("Platform: timer dur\t" + ((t - time) / 1000f)
347    + "\t" + ((duration) / 1000f) + "\t" + msg);
348    }
349  0 set = 0;
350  0 break;
351    }
352    }
353   
 
354  0 toggle public static void cacheFileData(String path, Object data)
355    {
356  0 if (!isJS() || data == null)
357    {
358  0 return;
359    }
360    /**
361    * @j2sNative
362    *
363    * swingjs.JSUtil.cacheFileData$S$O(path, data);
364    *
365    */
366    }
367   
 
368  0 toggle public static void cacheFileData(File file)
369    {
370  0 byte[] data;
371  0 if (!isJS() || (data = Platform.getFileBytes(file)) == null)
372    {
373  0 return;
374    }
375  0 cacheFileData(file.toString(), data);
376    }
377   
 
378  1698 toggle public static byte[] getFileBytes(File f)
379    {
380  1698 return /** @j2sNative f && swingjs.JSUtil.getFileAsBytes$O(f) || */
381    null;
382    }
383   
 
384  0 toggle public static byte[] getFileAsBytes(String fileStr)
385    {
386  0 byte[] bytes = null;
387    // BH 2018 hack for no support for access-origin
388    /**
389    * @j2sNative bytes = swingjs.JSUtil.getFileAsBytes$O(fileStr)
390    */
391  0 cacheFileData(fileStr, bytes);
392  0 return bytes;
393    }
394   
 
395  0 toggle @SuppressWarnings("unused")
396    public static String getFileAsString(String url)
397    {
398  0 String ret = null;
399    /**
400    * @j2sNative
401    *
402    * ret = swingjs.JSUtil.getFileAsString$S(url);
403    *
404    *
405    */
406  0 cacheFileData(url, ret);
407  0 return ret;
408    }
409   
 
410  4 toggle public static boolean setFileBytes(File f, String urlstring)
411    {
412  4 if (!isJS())
413    {
414  4 return false;
415    }
416  0 @SuppressWarnings("unused")
417    byte[] bytes = getFileAsBytes(urlstring);
418    // TODO temporary doubling of 秘bytes and _bytes;
419    // just remove _bytes when new transpiler has been installed
420    /**
421    * @j2sNative f.\u79d8bytes = f._bytes = bytes;
422    */
423  0 return true;
424    }
425   
 
426  4 toggle public static void addJ2SBinaryType(String ext)
427    {
428    /**
429    * @j2sNative
430    *
431    * J2S._binaryTypes.push("." + ext + "?");
432    *
433    */
434    }
435   
436    /**
437    * Encode the URI using JavaScript encodeURIComponent
438    *
439    * @param value
440    * @return encoded value
441    */
 
442  0 toggle public static String encodeURI(String value)
443    {
444    /**
445    * @j2sNative value = encodeURIComponent(value);
446    */
447  0 return value;
448    }
449   
450    /**
451    * Open the URL using a simple window call if this is JavaScript
452    *
453    * @param url
454    * @return true if window has been opened
455    */
 
456  0 toggle public static boolean openURL(String url)
457    {
458  0 if (!isJS())
459    {
460  0 return false;
461    }
462    /**
463    * @j2sNative
464    *
465    *
466    * window.open(url);
467    */
468  0 return true;
469    }
470   
 
471  0 toggle public static String getUniqueAppletID()
472    {
473    /**
474    * @j2sNative return swingjs.JSUtil.getApplet$()._uniqueId;
475    *
476    */
477  0 return null;
478   
479    }
480   
481    /**
482    * Read the Info block for this applet.
483    *
484    * @param prefix
485    * "jalview_"
486    * @param p
487    * @return unique id for this applet
488    */
 
489  59 toggle public static void readInfoProperties(String prefix, Properties p)
490    {
491  59 if (!isJS())
492    {
493  59 return;
494    }
495  0 String id = getUniqueAppletID();
496  0 String key = "", value = "";
497    /**
498    * @j2sNative var info = swingjs.JSUtil.getApplet$().__Info || {}; for (var
499    * key in info) { if (key.indexOf(prefix) == 0) { value = "" +
500    * info[key];
501    */
502   
503  0 jalview.bin.Console.outPrintln(
504    "Platform id=" + id + " reading Info." + key + " = " + value);
505  0 p.put(id + "_" + key, value);
506   
507    /**
508    * @j2sNative
509    *
510    *
511    * } }
512    */
513    }
514   
 
515  0 toggle public static void setAjaxJSON(URL url)
516    {
517  0 if (isJS())
518    {
519  0 JSON.setAjax(url);
520    }
521    }
522   
 
523  146 toggle public static Object parseJSON(InputStream response)
524    throws IOException, ParseException
525    {
526  146 if (isJS())
527    {
528  0 return JSON.parse(checkForGzipStream(response));
529    }
530   
531  146 BufferedReader br = null;
532  146 try
533    {
534  146 Test failure here br = checkForGzipStream(response,"UTF-8");
535  145 return new JSONParser().parse(br);
536    } finally
537    {
538  145 if (br != null)
539    {
540  145 try
541    {
542  145 br.close();
543    } catch (IOException e)
544    {
545    // ignore
546    }
547    }
548    }
549    }
550   
 
551  141 toggle public static Object parseJSON(String json) throws ParseException
552    {
553  141 return (isJS() ? JSON.parse(json) : new JSONParser().parse(json));
554    }
555   
 
556  53 toggle public static Object parseJSON(Reader r)
557    throws IOException, ParseException
558    {
559  53 if (r == null)
560    {
561  0 return null;
562    }
563   
564  53 if (!isJS())
565    {
566  53 return new JSONParser().parse(r);
567    }
568    // Using a file reader is not currently supported in SwingJS JavaScript
569   
570  0 if (r instanceof FileReader)
571    {
572  0 throw new IOException(
573    "StringJS does not support FileReader parsing for JSON -- but it could...");
574    }
575  0 return JSON.parse(r);
576   
577    }
578   
579   
580    /**
581    * Recognise the 2-byte magic header for gzip streams
582    *
583    * https://recalll.co/ask/v/topic/java-How-to-check-if-InputStream-is-Gzipped/555aadd62bd27354438b90f6
584    *
585    * @param bytes
586    * - at least two bytes
587    * @return
588    * @throws IOException
589    */
 
590  1138 toggle public static boolean isGzipStream(InputStream input) throws IOException
591    {
592  1138 if (!input.markSupported())
593    {
594  1 Console.error(
595    "FileParse.izGzipStream: input stream must support mark/reset");
596  1 return false;
597    }
598  1137 input.mark(4);
599   
600    // get first 2 bytes or return false
601  1137 byte[] bytes = new byte[2];
602  1137 Test failure here int read = input.read(bytes);
603  1136 input.reset();
604  1136 if (read != bytes.length)
605    {
606  0 return false;
607    }
608   
609  1136 int header = (bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
610  1136 return (GZIPInputStream.GZIP_MAGIC == header);
611    }
612   
613    /**
614    * Returns a Reader for the given input after wrapping it in a buffered input
615    * stream, and then checking if it needs to be wrapped by a GZipInputStream
616    *
617    * @param input
618    * @return
619    */
 
620  989 toggle public static BufferedReader checkForGzipStream(InputStream input)
621    throws IOException
622    {
623  989 return checkForGzipStream(input, null);
624    }
625    /**
626    * Returns a Reader for the given input after wrapping it in a buffered input
627    * stream, and then checking if it needs to be wrapped by a GZipInputStream
628    *
629    * @param input
630    * @param encoding - null or specified encoding for reader (e.g. UTF-8)
631    * @return
632    */
 
633  1135 toggle public static BufferedReader checkForGzipStream(InputStream input, String encoding)
634    throws IOException
635    {
636   
637    // NB: stackoverflow
638    // https://stackoverflow.com/questions/4818468/how-to-check-if-inputstream-is-gzipped
639    // could use a PushBackInputStream rather than a BufferedInputStream
640  1135 if (!input.markSupported())
641    {
642  1133 input = new BufferedInputStream(input, 16);
643    }
644  1134 Test failure here if (isGzipStream(input))
645    {
646  9 return getGzipReader(input, encoding);
647    }
648    // return a buffered reader for the stream.
649  1125 InputStreamReader isReader = encoding==null ? new InputStreamReader(input) : new InputStreamReader(input,encoding);
650  1125 BufferedReader toReadFrom = new BufferedReader(isReader);
651  1125 return toReadFrom;
652    }
653   
654    /**
655    * Returns a {@code BufferedReader} which wraps the input stream with a
656    * GZIPInputStream. Throws a {@code ZipException} if a GZIP format error
657    * occurs or the compression method used is unsupported.
658    *
659    * @param inputStream
660    * @return
661    * @throws Exception
662    */
 
663  0 toggle public static BufferedReader getGzipReader(InputStream inputStream)
664    throws IOException
665    {
666  0 return getGzipReader(inputStream, null);
667    }
668   
669    /**
670    * Returns a {@code BufferedReader} which wraps the input stream with a
671    * GZIPInputStream. Throws a {@code ZipException} if a GZIP format error
672    * occurs or the compression method used is unsupported.
673    *
674    * @param inputStream
675    * @param encoding - null or specific encoding for reader
676    * @return
677    * @throws Exception
678    */
 
679  9 toggle public static BufferedReader getGzipReader(InputStream inputStream, String encoding)
680    throws IOException
681    {
682  9 encoding = encoding == null ? Charset.defaultCharset().toString() : encoding;
683  9 BufferedReader inData = new BufferedReader(
684    new InputStreamReader(new GZIPInputStream(inputStream), encoding));
685  9 inData.mark(2048);
686  9 inData.read();
687  9 inData.reset();
688  9 return inData;
689    }
690   
691   
692    /**
693    * Dump the input stream to an output file.
694    *
695    * @param is
696    * @param outFile
697    * @throws IOException
698    * if the file cannot be created or there is a problem reading the
699    * input stream.
700    */
 
701  0 toggle public static void streamToFile(InputStream is, File outFile)
702    throws IOException
703    {
704  0 if (isJS() && /**
705    * @j2sNative outFile.setBytes$O && outFile.setBytes$O(is) &&
706    */
707    true)
708    {
709  0 return;
710    }
711  0 FileOutputStream fio = new FileOutputStream(outFile);
712  0 try
713    {
714  0 byte[] bb = new byte[32 * 1024];
715  0 int l;
716  0 while ((l = is.read(bb)) > 0)
717    {
718  0 fio.write(bb, 0, l);
719    }
720    } finally
721    {
722  0 fio.close();
723    }
724    }
725   
726    /**
727    * Add a known domain that implements access-control-allow-origin:*
728    *
729    * These should be reviewed periodically.
730    *
731    * @param domain
732    * for a service that is not allowing ajax
733    *
734    * @author hansonr@stolaf.edu
735    *
736    */
 
737  249 toggle public static void addJ2SDirectDatabaseCall(String domain)
738    {
739   
740  249 if (isJS())
741    {
742  0 jalview.bin.Console.outPrintln(
743    "Platform adding known access-control-allow-origin * for domain "
744    + domain);
745    /**
746    * @j2sNative
747    *
748    * J2S.addDirectDatabaseCall(domain);
749    */
750    }
751   
752    }
753   
 
754  55 toggle public static void getURLCommandArguments()
755    {
756  55 try
757    {
758    /**
759    * Retrieve the first query field as command arguments to Jalview. Include
760    * only if prior to "?j2s" or "&j2s" or "#". Assign the applet's
761    * __Info.args element to this value.
762    *
763    * @j2sNative var a =
764    * decodeURI((document.location.href.replace("&","?").split("?j2s")[0]
765    * + "?").split("?")[1].split("#")[0]); a &&
766    * (jalview.bin.Console.outPrintln("URL arguments detected were
767    * "+a)) && (J2S.thisApplet.__Info.urlargs = a.split(" "));
768    * (!J2S.thisApplet.__Info.args || J2S.thisApplet.__Info.args
769    * == "" || J2S.thisApplet.__Info.args == "??") &&
770    * (J2S.thisApplet.__Info.args = a) &&
771    * (jalview.bin.Console.outPrintln("URL arguments were passed
772    * to J2S main."));
773    */
774    } catch (Throwable t)
775    {
776    }
777    }
778   
779    /**
780    * A (case sensitive) file path comparator that ignores the difference between
781    * / and \
782    *
783    * @param path1
784    * @param path2
785    * @return
786    */
 
787  19 toggle public static boolean pathEquals(String path1, String path2)
788    {
789  19 if (path1 == null)
790    {
791  2 return path2 == null;
792    }
793  17 if (path2 == null)
794    {
795  1 return false;
796    }
797  16 String p1 = path1.replace('\\', '/');
798  16 String p2 = path2.replace('\\', '/');
799  16 return p1.equals(p2);
800    }
801   
802    /**
803    * If started on command line using launch script, return the console width
804    */
 
805  0 toggle public static int consoleWidth()
806    {
807  0 return CONSOLEWIDTH;
808    }
809    }