Clover icon

Coverage Report

  1. Project Clover database Thu Jan 15 2026 16:11:02 GMT
  2. Package jalview.util

File Platform.java

 

Coverage histogram

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

Code metrics

138
248
64
2
1,233
709
171
0.69
3.88
32
2.67

Classes

Class Line # Actions
Platform 72 220 154
0.4592592745.9%
Platform.PlatformDependentValue 280 28 17
0.4222222342.2%
 

Contributing tests

This file is covered by 844 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.Component;
24    import java.awt.Dimension;
25    import java.awt.GraphicsEnvironment;
26    import java.awt.Toolkit;
27    import java.awt.event.KeyEvent;
28    import java.awt.event.MouseEvent;
29    import java.io.BufferedReader;
30    import java.io.File;
31    import java.io.FileOutputStream;
32    import java.io.FileReader;
33    import java.io.IOException;
34    import java.io.InputStream;
35    import java.io.InputStreamReader;
36    import java.io.Reader;
37    import java.lang.reflect.InvocationTargetException;
38    import java.lang.reflect.Method;
39    import java.net.URL;
40    import java.nio.channels.Channels;
41    import java.nio.channels.ReadableByteChannel;
42    import java.nio.file.Files;
43    import java.nio.file.Path;
44    import java.nio.file.Paths;
45    import java.nio.file.StandardCopyOption;
46    import java.nio.file.attribute.BasicFileAttributes;
47    import java.util.Date;
48    import java.util.Locale;
49    import java.util.Map;
50    import java.util.Objects;
51    import java.util.Properties;
52    import java.util.logging.ConsoleHandler;
53    import java.util.logging.Level;
54    import java.util.logging.Logger;
55   
56    import javax.swing.SwingUtilities;
57   
58    import org.json.simple.parser.JSONParser;
59    import org.json.simple.parser.ParseException;
60   
61    import com.stevesoft.pat.Regex;
62   
63    import jalview.bin.Jalview;
64    import jalview.javascript.json.JSON;
65    import swingjs.api.JSUtilI;
66   
67    /**
68    * System platform information used by Applet and Application
69    *
70    * @author Jim Procter
71    */
 
72    public class Platform
73    {
74   
75    private static boolean isJS = /** @j2sNative true || */
76    false;
77   
78    private static Boolean isNoJSMac = null, isNoJSWin = null, isMac = null,
79    isWin = null, isLinux = null;
80   
81    private static Boolean isHeadless = null;
82   
83    // If launched from CLI with launcher script then -DCOLUMNWIDTH is set
84    private static final int CONSOLEWIDTH;
85   
86    private static final String CONSOLEWIDTHPROPERTY = "CONSOLEWIDTH";
87   
88    private static swingjs.api.JSUtilI jsutil;
89   
90    /**
91    * added to group mouse events into Windows and nonWindows (mac, unix, linux)
92    *
93    * @return
94    */
 
95  853 toggle public static boolean isMac()
96    {
97  853 return (isMac == null
98    ? (isMac = (System.getProperty("os.name").indexOf("Mac") >= 0))
99    : isMac);
100    }
101   
102    public static int SHORTCUT_KEY_MASK = (Platform.isMac()
103    ? KeyEvent.META_DOWN_MASK
104    : KeyEvent.CTRL_DOWN_MASK);
105   
 
106  55 toggle static
107    {
108  55 int cw = 80;
109  55 if (System.getProperty(CONSOLEWIDTHPROPERTY) != null
110    && System.getProperty(CONSOLEWIDTHPROPERTY).length() > 0)
111    {
112  0 try
113    {
114  0 cw = Integer.parseInt(System.getProperty(CONSOLEWIDTHPROPERTY));
115    } catch (NumberFormatException e)
116    {
117    }
118    }
119  55 CONSOLEWIDTH = cw;
120  55 if (isJS)
121    {
122  0 try
123    {
124    // this is ok - it's a highly embedded method in Java; the deprecation
125    // is
126    // really a recommended best practice.
127  0 jsutil = ((JSUtilI) Class.forName("swingjs.JSUtil")
128    .getDeclaredConstructor().newInstance());
129    } catch (InstantiationException | IllegalAccessException
130    | ClassNotFoundException e)
131    {
132  0 e.printStackTrace();
133    } catch (IllegalArgumentException | InvocationTargetException
134    | NoSuchMethodException | SecurityException e)
135    {
136  0 e.printStackTrace();
137    }
138    }
139  55 if (!GraphicsEnvironment.isHeadless())
140    {
141    // Using non-deprecated Extended key mask modifiers, but Java 8 has no
142    // getMenuShortcutKeyMaskEx method
143  19 Toolkit tk = Toolkit.getDefaultToolkit();
144  19 Method method = null;
145  19 try
146    {
147  19 method = tk.getClass().getMethod("getMenuShortcutKeyMaskEx");
148    } catch (Exception e)
149    {
150  0 System.err.println(
151    "Could not find Toolkit method getMenuShortcutKeyMaskEx. Trying getMenuShortcutKeyMask.");
152    }
153  19 if (method == null)
154    {
155  0 try
156    {
157  0 method = tk.getClass().getMethod("getMenuShortcutKeyMask");
158    } catch (Exception e)
159    {
160  0 System.err.println(
161    "Could not find Toolkit method getMenuShortcutKeyMaskEx or getMenuShortcutKeyMask.");
162  0 e.printStackTrace();
163    }
164    }
165  19 if (method != null)
166    {
167  19 try
168    {
169  19 method.setAccessible(true);
170  19 SHORTCUT_KEY_MASK = ((int) method.invoke(tk, new Object[0]));
171    } catch (Exception e)
172    {
173  0 e.printStackTrace();
174    }
175    }
176  19 if (SHORTCUT_KEY_MASK <= 0xF)
177    {
178    // shift this into the extended region (was Java 8)
179  0 SHORTCUT_KEY_MASK = SHORTCUT_KEY_MASK << 6;
180    }
181    }
182    }
183   
184    /**
185    * added to group mouse events into Windows and nonWindows (mac, unix, linux)
186    *
187    * @return
188    */
 
189  22 toggle public static boolean isWin()
190    {
191  22 return (isWin == null
192    ? (isWin = (System.getProperty("os.name").indexOf("Win") >= 0))
193    : isWin);
194    }
195   
196    /**
197    * added to check LaF for Linux
198    *
199    * @return
200    */
 
201  249 toggle public static boolean isLinux()
202    {
203  249 return (isLinux == null
204    ? (isLinux = (System.getProperty("os.name")
205    .indexOf("Linux") >= 0))
206    : isLinux);
207    }
208   
209    /**
210    *
211    * @return true if HTML5 JavaScript
212    */
 
213  2640481 toggle public static boolean isJS()
214    {
215  2640482 return isJS;
216    }
217   
218    /**
219    * sorry folks - Macs really are different
220    *
221    * BH: disabled for SwingJS -- will need to check key-press issues
222    *
223    * @return true if we do things in a special way.
224    */
 
225  4971 toggle public static boolean isAMacAndNotJS()
226    {
227  4971 return (isNoJSMac == null ? (isNoJSMac = !isJS && isMac()) : isNoJSMac);
228    }
229   
230    /**
231    * Check if we are on a Microsoft platform...
232    *
233    * @return true if we have to cope with another platform variation
234    */
 
235  11 toggle public static boolean isWindowsAndNotJS()
236    {
237  11 return (isNoJSWin == null ? (isNoJSWin = !isJS && isWin()) : isNoJSWin);
238    }
239   
240    /**
241    *
242    * @return true if we are running in non-interactive no UI mode
243    */
 
244  991 toggle public static boolean isHeadless()
245    {
246  991 if (isHeadless == null)
247    {
248  21 isHeadless = "true".equals(System.getProperty("java.awt.headless"));
249    }
250  991 return isHeadless;
251    }
252   
253    /**
254    * Construct the value that depends on the system architecture. The methods
255    * setting the value for subsequent platforms are chained after this call and
256    * finalized with a {@link PlatformDependentValue#value() value()} call.
257    *
258    * Example: {@code
259    * Platform.forArch(120).forMac(114).forWin(112).forLinux(115).value();
260    * }
261    *
262    * @param <T>
263    * type of the value
264    * @param defaultValue
265    * default value used if platform not determined
266    * @return platform dependent value wrapper object
267    */
 
268  1 toggle public static <T> PlatformDependentValue<T> forArch(T defaultValue)
269    {
270  1 return new PlatformDependentValue<T>(defaultValue);
271    }
272   
273    /**
274    *
275    * @author mmwarowny
276    *
277    * @param <T>
278    * type of the value
279    */
 
280    public static class PlatformDependentValue<T>
281    {
282    private T defaultValue = null;
283   
284    private T macValue = null;
285   
286    private T winValue = null;
287   
288    private T linuxValue = null;
289   
290    private T jsValue = null;
291   
292    private T headlessValue = null;
293   
 
294  1 toggle private PlatformDependentValue(T value)
295    {
296  1 Objects.requireNonNull(value);
297  1 defaultValue = value;
298    }
299   
300    /**
301    * Set the value used on Mac platform.
302    *
303    * @param value
304    * parameter value
305    * @return
306    */
 
307  0 toggle public PlatformDependentValue<T> forMac(T value)
308    {
309  0 Objects.requireNonNull(value);
310  0 macValue = value;
311  0 return this;
312    }
313   
314    /**
315    * Set the value used on Windows platform.
316    *
317    * @param value
318    * parameter value
319    * @return
320    */
 
321  1 toggle public PlatformDependentValue<T> forWin(T value)
322    {
323  1 Objects.requireNonNull(value);
324  1 winValue = value;
325  1 return this;
326    }
327   
328    /**
329    * Set the value used on Linux platform.
330    *
331    * @param value
332    * parameter value
333    * @return
334    */
 
335  0 toggle public PlatformDependentValue<T> forLinux(T value)
336    {
337  0 Objects.requireNonNull(value);
338  0 linuxValue = value;
339  0 return this;
340    }
341   
342    /**
343    * Set the value used on JS platform.
344    *
345    * @param value
346    * parameter value
347    * @return
348    */
 
349  0 toggle public PlatformDependentValue<T> forJS(T value)
350    {
351  0 Objects.requireNonNull(value);
352  0 jsValue = value;
353  0 return this;
354    }
355   
356    /**
357    * Set the value used on headless platform. The headless value takes
358    * precedence over other platforms if set.
359    *
360    * @param value
361    * parameter value
362    * @return
363    */
 
364  0 toggle public PlatformDependentValue<T> forHeadless(T value)
365    {
366  0 Objects.requireNonNull(value);
367  0 headlessValue = value;
368  0 return this;
369    }
370   
371    /**
372    * Get the value of the parameter respecting the platform. The headless
373    * platform takes precedence over any other platform if it has the value
374    * set.
375    *
376    * @return parameter value depending on the platform
377    */
 
378  1 toggle public T value()
379    {
380  1 if (headlessValue != null && isHeadless())
381  0 return headlessValue;
382  1 if (macValue != null && isMac())
383  0 return macValue;
384  1 if (winValue != null && isWin())
385  0 return winValue;
386  1 if (linuxValue != null && isLinux())
387  0 return linuxValue;
388  1 if (jsValue != null && isJS)
389  0 return jsValue;
390  1 return defaultValue;
391    }
392    }
393   
394    /**
395    *
396    * @return nominal maximum command line length for this platform
397    */
 
398  0 toggle public static int getMaxCommandLineLength()
399    {
400    // TODO: determine nominal limits for most platforms.
401  0 return 2046; // this is the max length for a windows NT system.
402    }
403   
404    /**
405    * Answers the input with every backslash replaced with a double backslash (an
406    * 'escaped' single backslash)
407    *
408    * @param s
409    * @return
410    */
 
411  90 toggle public static String escapeBackslashes(String s)
412    {
413  90 return s == null ? null : s.replace("\\", "\\\\");
414    }
415   
416    /**
417    * Answers true if the mouse event has Meta-down (Command key on Mac) or
418    * Ctrl-down (on other o/s). Note this answers _false_ if the Ctrl key is
419    * pressed instead of the Meta/Cmd key on Mac. To test for Ctrl-pressed on
420    * Mac, you can use e.isPopupTrigger().
421    *
422    * @param e
423    * @return
424    */
 
425  3 toggle public static boolean isControlDown(MouseEvent e)
426    {
427  3 return isControlDown(e, isMac());
428    }
429   
430    /**
431    * Overloaded version of method (to allow unit testing)
432    *
433    * @param e
434    * @param aMac
435    * @return
436    */
 
437  6 toggle protected static boolean isControlDown(MouseEvent e, boolean aMac)
438    {
439    //
440    // System.out.println(e.isPopupTrigger()
441    // + " " + ((SHORTCUT_KEY_MASK & e.getModifiersEx()) != 0)
442    // + " " + e.isControlDown());
443  6 return (aMac
444    ? !e.isPopupTrigger()
445    && (SHORTCUT_KEY_MASK & e.getModifiersEx()) != 0
446    : e.isControlDown());
447    }
448   
449    // BH: I don't know about that previous method. Here is what SwingJS uses.
450    // Notice the distinction in mouse events. (BUTTON3_MASK == META)
451    //
452    // private static boolean isPopupTrigger(int id, int mods, boolean isWin) {
453    // boolean rt = ((mods & InputEvent.BUTTON3_MASK) != 0);
454    // if (isWin) {
455    // if (id != MouseEvent.MOUSE_RELEASED)
456    // return false;
457    ////
458    //// // Oddly, Windows returns InputEvent.META_DOWN_MASK on release, though
459    //// // BUTTON3_DOWN_MASK for pressed. So here we just accept both.
460    ////
461    //// actually, we can use XXX_MASK, not XXX_DOWN_MASK and avoid this issue,
462    // because
463    //// J2S adds the appropriate extended (0x3FC0) and simple (0x3F) modifiers.
464    ////
465    // return rt;
466    // } else {
467    // // mac, linux, unix
468    // if (id != MouseEvent.MOUSE_PRESSED)
469    // return false;
470    // boolean lt = ((mods & InputEvent.BUTTON1_MASK) != 0);
471    // boolean ctrl = ((mods & InputEvent.CTRL_MASK) != 0);
472    // return rt || (ctrl && lt);
473    // }
474    // }
475    //
476   
477    /**
478    * Windows (not Mac, Linux, or Unix) and right button to test for the
479    * right-mouse pressed event in Windows that would have opened a menu or a
480    * Mac.
481    *
482    * @param e
483    * @return
484    */
 
485  3 toggle public static boolean isWinRightButton(MouseEvent e)
486    {
487    // was !isAMac(), but that is true also for Linux and Unix and JS,
488   
489  3 return isWin() && SwingUtilities.isRightMouseButton(e);
490    }
491   
492    /**
493    * Windows (not Mac, Linux, or Unix) and middle button -- for mouse wheeling
494    * without pressing the button.
495    *
496    * @param e
497    * @return
498    */
 
499  0 toggle public static boolean isWinMiddleButton(MouseEvent e)
500    {
501    // was !isAMac(), but that is true also for Linux and Unix and JS
502  0 return isWin() && SwingUtilities.isMiddleMouseButton(e);
503    }
504   
 
505  498 toggle public static boolean allowMnemonics()
506    {
507  498 return !isMac();
508    }
509   
510    public final static int TIME_RESET = 0;
511   
512    public final static int TIME_MARK = 1;
513   
514    public static final int TIME_SET = 2;
515   
516    public static final int TIME_GET = 3;
517   
518    public static long time, mark, set, duration;
519   
520    /**
521    * typical usage:
522    *
523    * Platform.timeCheck(null, Platform.TIME_MARK);
524    *
525    * ...
526    *
527    * Platform.timeCheck("some message", Platform.TIME_MARK);
528    *
529    * reset...[set/mark]n...get
530    *
531    * @param msg
532    * @param mode
533    */
 
534  0 toggle public static void timeCheck(String msg, int mode)
535    {
536  0 long t = System.currentTimeMillis();
537  0 switch (mode)
538    {
539  0 case TIME_RESET:
540  0 time = mark = t;
541  0 duration = 0;
542  0 if (msg != null)
543    {
544  0 jalview.bin.Console.errPrintln("Platform: timer reset\t\t\t" + msg);
545    }
546  0 break;
547  0 case TIME_MARK:
548  0 if (set > 0)
549    {
550    // total time between set/mark points
551  0 duration += (t - set);
552    }
553    else
554    {
555  0 if (time == 0)
556    {
557  0 time = mark = t;
558    }
559  0 if (msg != null)
560    {
561  0 jalview.bin.Console.errPrintln(
562    "Platform: timer mark\t" + ((t - time) / 1000f) + "\t"
563    + ((t - mark) / 1000f) + "\t" + msg);
564    }
565  0 mark = t;
566    }
567  0 break;
568  0 case TIME_SET:
569  0 set = t;
570  0 break;
571  0 case TIME_GET:
572  0 if (msg != null)
573    {
574  0 jalview.bin.Console
575    .errPrintln("Platform: timer dur\t" + ((t - time) / 1000f)
576    + "\t" + ((duration) / 1000f) + "\t" + msg);
577    }
578  0 set = 0;
579  0 break;
580    }
581    }
582   
 
583  0 toggle public static void cacheFileData(String path, Object data)
584    {
585  0 if (isJS && data != null)
586    {
587  0 jsutil.cachePathData(path, data);
588    }
589    }
590   
 
591  0 toggle public static void cacheFileData(File file)
592    {
593  0 if (isJS)
594    {
595  0 byte[] data = Platform.getFileBytes(file);
596    {
597  0 if (data != null)
598    {
599  0 cacheFileData(file.toString(), data);
600    }
601    }
602    }
603    }
604   
 
605  1568 toggle public static byte[] getFileBytes(File f)
606    {
607  1568 return (isJS && f != null ? jsutil.getBytes(f) : null);
608    }
609   
 
610  0 toggle public static byte[] getFileAsBytes(String fileStr)
611    {
612  0 if (isJS && fileStr != null)
613    {
614  0 byte[] bytes = (byte[]) jsutil.getFile(fileStr, false);
615  0 cacheFileData(fileStr, bytes);
616  0 return bytes;
617    }
618  0 return null;
619    }
620   
 
621  0 toggle public static String getFileAsString(String url)
622    {
623  0 if (isJS && url != null)
624    {
625  0 String ret = (String) jsutil.getFile(url, true);
626  0 cacheFileData(url, ret);
627  0 return ret;
628    }
629  0 return null;
630    }
631   
 
632  33 toggle public static boolean setFileBytes(File f, String urlstring)
633    {
634  33 if (isJS && f != null && urlstring != null)
635    {
636  0 @SuppressWarnings("unused")
637    byte[] bytes = getFileAsBytes(urlstring);
638  0 jsutil.setFileBytes(f, bytes);
639  0 return true;
640    }
641  33 return false;
642    }
643   
 
644  4 toggle public static void addJ2SBinaryType(String ext)
645    {
646  4 if (isJS)
647    {
648  0 jsutil.addBinaryFileType(ext);
649    }
650    }
651   
652    /**
653    * Encode the URI using JavaScript encodeURIComponent
654    *
655    * @param value
656    * @return encoded value
657    */
 
658  0 toggle public static String encodeURI(String value)
659    {
660    /**
661    * @j2sNative value = encodeURIComponent(value);
662    */
663  0 return value;
664    }
665   
666    /**
667    * Open the URL using a simple window call if this is JavaScript
668    *
669    * @param url
670    * @return true if window has been opened
671    */
 
672  0 toggle public static boolean openURL(String url) throws IOException
673    {
674  0 if (!isJS)
675    {
676  0 return false;
677    }
678    /**
679    * @j2sNative
680    *
681    *
682    * window.open(url);
683    */
684  0 return true;
685    }
686   
 
687  0 toggle public static String getUniqueAppletID()
688    {
689  0 return (isJS ? (String) jsutil.getAppletAttribute("_uniqueId") : null);
690   
691    }
692   
693    /**
694    * Read the Info block for this applet.
695    *
696    * @param prefix
697    * "jalview_"
698    * @param p
699    * @return unique id for this applet
700    */
 
701  49 toggle public static void readInfoProperties(String prefix, Properties p)
702    {
703  49 if (!isJS)
704    {
705  49 return;
706    }
707  0 String id = getUniqueAppletID();
708  0 String key = "", value = "";
709    /**
710    * @j2sNative var info = swingjs.JSUtil.getApplet$().__Info || {}; for (var
711    * key in info) { if (key.indexOf(prefix) == 0) { value = "" +
712    * info[key];
713    */
714   
715  0 jalview.bin.Console.outPrintln(
716    "Platform id=" + id + " reading Info." + key + " = " + value);
717  0 p.put(id + "_" + key, value);
718   
719    /**
720    * @j2sNative
721    *
722    * } }
723    */
724    }
725   
 
726  0 toggle public static void setAjaxJSON(URL url)
727    {
728  0 if (isJS)
729    {
730  0 JSON.setAjax(url);
731    }
732    }
733   
 
734  56 toggle public static Object parseJSON(InputStream response)
735    throws IOException, ParseException
736    {
737  56 if (isJS)
738    {
739  0 return JSON.parse(response);
740    }
741   
742  56 BufferedReader br = null;
743  56 try
744    {
745  56 br = new BufferedReader(new InputStreamReader(response, "UTF-8"));
746  56 return new JSONParser().parse(br);
747    } finally
748    {
749  56 if (br != null)
750    {
751  56 try
752    {
753  56 br.close();
754    } catch (IOException e)
755    {
756    // ignore
757    }
758    }
759    }
760    }
761   
 
762  140 toggle public static Object parseJSON(String json) throws ParseException
763    {
764  140 return (isJS ? JSON.parse(json) : new JSONParser().parse(json));
765    }
766   
 
767  54 toggle public static Object parseJSON(Reader r)
768    throws IOException, ParseException
769    {
770  54 if (r == null)
771    {
772  0 return null;
773    }
774   
775  54 if (!isJS)
776    {
777  54 return new JSONParser().parse(r);
778    }
779    // Using a file reader is not currently supported in SwingJS JavaScript
780   
781  0 if (r instanceof FileReader)
782    {
783  0 throw new IOException(
784    "StringJS does not support FileReader parsing for JSON -- but it could...");
785    }
786  0 return JSON.parse(r);
787   
788    }
789   
790    /**
791    * Dump the input stream to an output file.
792    *
793    * @param is
794    * @param outFile
795    * @throws IOException
796    * if the file cannot be created or there is a problem reading the
797    * input stream.
798    */
 
799  0 toggle public static void streamToFile(InputStream is, File outFile)
800    throws IOException
801    {
802  0 if (isJS)
803    {
804  0 jsutil.setFileBytes(outFile, is);
805  0 return;
806    }
807  0 FileOutputStream fio = new FileOutputStream(outFile);
808  0 try
809    {
810  0 byte[] bb = new byte[32 * 1024];
811  0 int l;
812  0 while ((l = is.read(bb)) > 0)
813    {
814  0 fio.write(bb, 0, l);
815    }
816    } finally
817    {
818  0 fio.close();
819    }
820    }
821   
822    /**
823    * Add a known domain that implements access-control-allow-origin:*
824    *
825    * These should be reviewed periodically.
826    *
827    * @param domain
828    * for a service that is not allowing ajax
829    *
830    * @author hansonr@stolaf.edu
831    *
832    */
 
833  249 toggle public static void addJ2SDirectDatabaseCall(String domain)
834    {
835   
836  249 if (isJS)
837    {
838  0 jsutil.addDirectDatabaseCall(domain);
839  0 jalview.bin.Console.outPrintln(
840    "Platform adding known access-control-allow-origin * for domain "
841    + domain);
842    /**
843    * @j2sNative
844    *
845    * J2S.addDirectDatabaseCall(domain);
846    */
847    }
848   
849    }
850   
851    /**
852    * Allow for URL-line command arguments. Untested.
853    *
854    */
 
855  55 toggle public static void getURLCommandArguments()
856    {
857  55 try
858    {
859    /**
860    * Retrieve the first query field as command arguments to Jalview. Include
861    * only if prior to "?j2s" or "&j2s" or "#". Assign the applet's
862    * __Info.args element to this value.
863    *
864    * @j2sNative var a =
865    * decodeURI((document.location.href.replace("&","?").split("?j2s")[0]
866    * + "?").split("?")[1].split("#")[0]); a &&
867    * (jalview.bin.Console.outPrintln("URL arguments detected were
868    * "+a)) && (J2S.thisApplet.__Info.urlargs = a.split(" "));
869    * (!J2S.thisApplet.__Info.args || J2S.thisApplet.__Info.args
870    * == "" || J2S.thisApplet.__Info.args == "??") &&
871    * (J2S.thisApplet.__Info.args = a) &&
872    * (jalview.bin.Console.outPrintln("URL arguments were passed
873    * to J2S main."));
874    */
875    } catch (Throwable t)
876    {
877    }
878    }
879   
880    /**
881    * A (case sensitive) file path comparator that ignores the difference between
882    * / and \
883    *
884    * @param path1
885    * @param path2
886    * @return
887    */
 
888  19 toggle public static boolean pathEquals(String path1, String path2)
889    {
890  19 if (path1 == null)
891    {
892  2 return path2 == null;
893    }
894  17 if (path2 == null)
895    {
896  1 return false;
897    }
898  16 String p1 = path1.replace('\\', '/');
899  16 String p2 = path2.replace('\\', '/');
900  16 return p1.equals(p2);
901    }
902   
903    /**
904    * If started on command line using launch script, return the console width
905    */
 
906  0 toggle public static int consoleWidth()
907    {
908  0 return CONSOLEWIDTH;
909    }
910    ///////////// JAL-3253 Applet additions //////////////
911   
912    /**
913    * Retrieve the object's embedded size from a div's style on a page if
914    * embedded in SwingJS.
915    *
916    * @param frame
917    * JFrame or JInternalFrame
918    * @param defaultWidth
919    * use -1 to return null (no default size)
920    * @param defaultHeight
921    * @return the embedded dimensions or null (no default size or not embedded)
922    */
 
923  927 toggle public static Dimension getDimIfEmbedded(Component frame,
924    int defaultWidth, int defaultHeight)
925    {
926  927 Dimension d = null;
927  927 if (isJS)
928    {
929  0 d = (Dimension) getEmbeddedAttribute(frame, "dim");
930    }
931  927 return (d == null && defaultWidth >= 0
932    ? new Dimension(defaultWidth, defaultHeight)
933    : d);
934   
935    }
936   
 
937  85 toggle public static Regex newRegex(String regex)
938    {
939  85 return newRegex(regex, null);
940    }
941   
 
942  1691 toggle public static Regex newRegex(String searchString, String replaceString)
943    {
944  1691 ensureRegex();
945  1691 return (replaceString == null ? new Regex(searchString)
946    : new Regex(searchString, replaceString));
947    }
948   
 
949  378 toggle public static Regex newRegexPerl(String code)
950    {
951  378 ensureRegex();
952  378 return Regex.perlCode(code);
953    }
954   
955    /**
956    * Initialize Java debug logging. A representative sample -- adapt as desired.
957    */
 
958  0 toggle public static void startJavaLogging()
959    {
960    /**
961    * @j2sIgnore
962    */
963    {
964  0 logClass("java.awt.EventDispatchThread", "java.awt.EventQueue",
965    "java.awt.Component", "java.awt.focus.Component",
966    "java.awt.event.Component",
967    "java.awt.focus.DefaultKeyboardFocusManager");
968    }
969    }
970   
971    /**
972    * Initiate Java logging for a given class. Only for Java, not JavaScript;
973    * Allows debugging of complex event processing.
974    *
975    * @param className
976    */
 
977  0 toggle public static void logClass(String... classNames)
978    {
979    /**
980    * @j2sIgnore
981    *
982    *
983    */
984    {
985  0 Logger rootLogger = Logger.getLogger("");
986  0 rootLogger.setLevel(Level.ALL);
987  0 ConsoleHandler consoleHandler = new ConsoleHandler();
988  0 consoleHandler.setLevel(Level.ALL);
989  0 for (int i = classNames.length; --i >= 0;)
990    {
991  0 Logger logger = Logger.getLogger(classNames[i]);
992  0 logger.setLevel(Level.ALL);
993  0 logger.addHandler(consoleHandler);
994    }
995    }
996    }
997   
998    /**
999    * load a resource -- probably a core file -- if and only if a particular
1000    * class has not been instantialized. We use a String here because if we used
1001    * a .class object, that reference itself would simply load the class, and we
1002    * want the core package to include that as well.
1003    *
1004    * @param resourcePath
1005    * @param className
1006    */
 
1007  5 toggle public static void loadStaticResource(String resourcePath,
1008    String className)
1009    {
1010  5 if (isJS)
1011    {
1012  0 jsutil.loadResourceIfClassUnknown(resourcePath, className);
1013    }
1014    }
1015   
 
1016  2092 toggle public static void ensureRegex()
1017    {
1018  2092 if (isJS)
1019    {
1020  0 loadStaticResource("core/core_stevesoft.z.js",
1021    "com.stevesoft.pat.Regex");
1022    }
1023    }
1024   
1025    /**
1026    * Set the "app" property of the HTML5 applet object, for example,
1027    * "testApplet.app", to point to the Jalview instance. This will be the object
1028    * that page developers use that is similar to the original Java applet object
1029    * that was accessed via LiveConnect.
1030    *
1031    * @param j
1032    */
 
1033  0 toggle public static void setAppClass(Object j)
1034    {
1035  0 if (isJS)
1036    {
1037  0 jsutil.setAppClass(j);
1038    }
1039    }
1040   
1041    /**
1042    *
1043    * If this frame is embedded in a web page, return a known type.
1044    *
1045    * @param frame
1046    * a JFrame or JInternalFrame
1047    * @param type
1048    * "name", "node", "init", "dim", or any DOM attribute, such as "id"
1049    * @return null if frame is not embedded.
1050    */
 
1051  569 toggle public static Object getEmbeddedAttribute(Component frame, String type)
1052    {
1053  569 return (isJS ? jsutil.getEmbeddedAttribute(frame, type) : null);
1054    }
1055   
 
1056  0 toggle public static void stackTrace()
1057    {
1058  0 try
1059    {
1060  0 throw new NullPointerException();
1061    } catch (Exception e)
1062    {
1063  0 e.printStackTrace();
1064    }
1065   
1066    }
1067   
 
1068  0 toggle public static URL getDocumentBase()
1069    {
1070  0 return (isJS ? jsutil.getDocumentBase() : null);
1071    }
1072   
 
1073  0 toggle public static URL getCodeBase()
1074    {
1075  0 return (isJS ? jsutil.getCodeBase() : null);
1076    }
1077   
 
1078  204 toggle public static String getUserPath(String subpath)
1079    {
1080  204 char sep = File.separatorChar;
1081  204 return System.getProperty("user.home") + sep
1082    + subpath.replace('/', sep);
1083    }
1084   
1085    /**
1086    * This method enables checking if a cached file has exceeded a certain
1087    * threshold(in days)
1088    *
1089    * @param file
1090    * the cached file
1091    * @param noOfDays
1092    * the threshold in days
1093    * @return
1094    */
 
1095  0 toggle public static boolean isFileOlderThanThreshold(File file, int noOfDays)
1096    {
1097  0 if (isJS)
1098    {
1099    // not meaningful in SwingJS -- this is a session-specific temp file. It
1100    // doesn't have a timestamp.
1101  0 return false;
1102    }
1103  0 Path filePath = file.toPath();
1104  0 BasicFileAttributes attr;
1105  0 int diffInDays = 0;
1106  0 try
1107    {
1108  0 attr = Files.readAttributes(filePath, BasicFileAttributes.class);
1109  0 diffInDays = (int) ((new Date().getTime()
1110    - attr.lastModifiedTime().toMillis())
1111    / (1000 * 60 * 60 * 24));
1112    // System.out.println("Diff in days : " + diffInDays);
1113    } catch (IOException e)
1114    {
1115  0 e.printStackTrace();
1116    }
1117  0 return noOfDays <= diffInDays;
1118    }
1119   
1120    /**
1121    * Get the leading integer part of a string that begins with an integer.
1122    *
1123    * @param input
1124    * - the string input to process
1125    * @param failValue
1126    * - value returned if unsuccessful
1127    * @return
1128    */
 
1129  6 toggle public static int getLeadingIntegerValue(String input, int failValue)
1130    {
1131  6 if (input == null)
1132    {
1133  0 return failValue;
1134    }
1135  6 if (isJS)
1136    {
1137  0 int val = /** @j2sNative 1 ? parseInt(input) : */
1138    0;
1139  0 return (val == val + 0 ? val : failValue);
1140    }
1141    // JavaScript does not support Regex ? lookahead
1142  6 String[] parts = input.split("(?=\\D)(?<=\\d)");
1143  6 if (parts != null && parts.length > 0 && parts[0].matches("[0-9]+"))
1144    {
1145  2 return Integer.valueOf(parts[0]);
1146    }
1147  4 return failValue;
1148    }
1149   
 
1150  0 toggle public static Map<String, Object> getAppletInfoAsMap()
1151    {
1152  0 return (isJS ? jsutil.getAppletInfoAsMap() : null);
1153    }
1154   
1155    /**
1156    * Get the SwingJS applet ID and combine that with the frameType
1157    *
1158    * @param frameType
1159    * "alignment", "desktop", etc., or null
1160    * @return
1161    */
 
1162  611 toggle public static String getAppID(String frameType)
1163    {
1164   
1165  611 String id = Jalview.getInstance().j2sAppletID;
1166  611 if (id == null)
1167    {
1168  54 Jalview.getInstance().j2sAppletID = id = (isJS
1169    ? (String) jsutil.getAppletAttribute("_id")
1170    : "jalview");
1171    }
1172  611 return id + (frameType == null ? "" : "-" + frameType);
1173    }
1174   
1175    /**
1176    * Option to avoid unnecessary seeking of nonexistent resources in JavaScript.
1177    * Works in Java as well.
1178    *
1179    * @param loc
1180    * @return
1181    */
 
1182  54 toggle public static Locale getLocaleOrNone(Locale loc)
1183    {
1184  54 return (isJS && loc.getLanguage() == "en" ? new Locale("") : loc);
1185    }
1186   
1187    /**
1188    * From UrlDownloadClient; trivial in JavaScript; painful in Java.
1189    *
1190    * @param urlstring
1191    * @param outfile
1192    * @throws IOException
1193    */
 
1194  44 toggle public static void download(String urlstring, String outfile)
1195    throws IOException
1196    {
1197  44 Path temp = null;
1198  44 try (InputStream is = new URL(urlstring).openStream())
1199    {
1200  8 if (isJS)
1201    { // so much easier!
1202  0 streamToFile(is, new File(outfile));
1203  0 return;
1204    }
1205  8 temp = Files.createTempFile(".jalview_", ".tmp");
1206  8 try (FileOutputStream fos = new FileOutputStream(temp.toString());
1207  8 ReadableByteChannel rbc = Channels.newChannel(is))
1208    {
1209  8 fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
1210    // copy tempfile to outfile once our download completes
1211    // incase something goes wrong
1212  8 Files.copy(temp, Paths.get(outfile),
1213    StandardCopyOption.REPLACE_EXISTING);
1214    }
1215    } catch (IOException e)
1216    {
1217  36 throw e;
1218    } finally
1219    {
1220  44 try
1221    {
1222  44 if (temp != null)
1223    {
1224  8 Files.deleteIfExists(temp);
1225    }
1226    } catch (IOException e)
1227    {
1228  0 System.out.println("Exception while deleting download temp file: "
1229    + e.getMessage());
1230    }
1231    }
1232    }
1233    }