001/*
002 * Copyright 2010-2015 Institut Pasteur.
003 * 
004 * This file is part of Icy.
005 * 
006 * Icy is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 * 
011 * Icy is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 * 
016 * You should have received a copy of the GNU General Public License
017 * along with Icy. If not, see <http://www.gnu.org/licenses/>.
018 */
019package icy.system;
020
021import java.awt.BufferCapabilities;
022import java.awt.Desktop;
023import java.awt.Desktop.Action;
024import java.awt.DisplayMode;
025import java.awt.Event;
026import java.awt.GraphicsConfiguration;
027import java.awt.GraphicsDevice;
028import java.awt.GraphicsEnvironment;
029import java.awt.HeadlessException;
030import java.awt.ImageCapabilities;
031import java.awt.Insets;
032import java.awt.Point;
033import java.awt.Rectangle;
034import java.awt.Toolkit;
035import java.awt.Transparency;
036import java.awt.geom.Rectangle2D;
037import java.awt.image.BufferedImage;
038import java.awt.image.ColorModel;
039import java.awt.image.VolatileImage;
040import java.io.File;
041import java.io.IOException;
042import java.lang.management.ManagementFactory;
043import java.lang.reflect.Field;
044import java.util.ArrayList;
045import java.util.List;
046import java.util.Properties;
047
048import com.sun.management.OperatingSystemMXBean;
049
050import icy.common.Version;
051import icy.file.FileUtil;
052import icy.main.Icy;
053import icy.type.collection.CollectionUtil;
054import icy.util.ReflectionUtil;
055import icy.util.StringUtil;
056
057/**
058 * @author stephane
059 */
060public class SystemUtil
061{
062    public static final String SYSTEM_WINDOWS = "win";
063    public static final String SYSTEM_MAC_OS = "mac";
064    public static final String SYSTEM_UNIX = "unix";
065
066    /**
067     * internals
068     */
069    private static Properties props = System.getProperties();
070
071    private static long lastNano = 0;
072    private static long lastCpu = 0;
073    private static int lastCpuLoad = 0;
074
075    /**
076     * Launch specified jar file.
077     * 
078     * @param jarPath
079     *        jar file path.
080     * @param vmArgs
081     *        arguments for the java virtual machine.
082     * @param appArgs
083     *        arguments for jar application.
084     * @param workDir
085     *        working directory.
086     */
087    public static Process execJAR(String jarPath, String vmArgs, String appArgs, String workDir)
088    {
089        return exec("java " + vmArgs + " -jar " + jarPath + " " + appArgs, workDir);
090    }
091
092    /**
093     * Launch specified jar file.
094     * 
095     * @param jarPath
096     *        jar file path.
097     * @param vmArgs
098     *        arguments for the java virtual machine.
099     * @param appArgs
100     *        arguments for jar application.
101     */
102    public static Process execJAR(String jarPath, String vmArgs, String appArgs)
103    {
104        return exec("java " + vmArgs + " -jar " + jarPath + " " + appArgs);
105    }
106
107    /**
108     * Launch specified jar file.
109     * 
110     * @param jarPath
111     *        jar file path.
112     * @param appArgs
113     *        arguments for jar application.
114     */
115    public static Process execJAR(String jarPath, String appArgs)
116    {
117        return execJAR(jarPath, "", appArgs);
118    }
119
120    /**
121     * Launch specified jar file.
122     * 
123     * @param jarPath
124     *        jar file path.
125     */
126    public static Process execJAR(String jarPath)
127    {
128        return execJAR(jarPath, "", "");
129    }
130
131    /**
132     * Execute a system command and return the attached process.
133     * 
134     * @param cmd
135     *        system command to execute.
136     */
137    public static Process exec(String cmd)
138    {
139        return exec(cmd, ".");
140    }
141
142    /**
143     * Execute a system command and return the attached process.
144     * 
145     * @param cmd
146     *        system command to execute.
147     * @param dir
148     *        the working directory of the subprocess, or null if the subprocess should inherit the
149     *        working directory of the current process.
150     */
151    public static Process exec(String cmd, String dir)
152    {
153        try
154        {
155            return Runtime.getRuntime().exec(cmd, null, new File(dir));
156        }
157        catch (Exception e)
158        {
159            System.err.println("SystemUtil.exec(" + cmd + ") error :");
160            IcyExceptionHandler.showErrorMessage(e, false);
161            return null;
162        }
163    }
164
165    public static BufferedImage createCompatibleImage(int width, int height)
166    {
167        final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration();
168
169        if (defaultGC == null)
170            return new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
171
172        return defaultGC.createCompatibleImage(width, height);
173    }
174
175    public static BufferedImage createCompatibleImage(int width, int height, int transparency)
176    {
177        final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration();
178
179        if (defaultGC == null)
180        {
181            if (transparency == Transparency.OPAQUE)
182                return new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
183
184            return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
185        }
186
187        return defaultGC.createCompatibleImage(width, height, transparency);
188    }
189
190    public static VolatileImage createCompatibleVolatileImage(int width, int height)
191    {
192        final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration();
193
194        if (defaultGC == null)
195            return null;
196
197        return defaultGC.createCompatibleVolatileImage(width, height);
198    }
199
200    public static VolatileImage createCompatibleVolatileImage(int width, int height, int transparency)
201    {
202        final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration();
203
204        if (defaultGC == null)
205            return null;
206
207        return defaultGC.createCompatibleVolatileImage(width, height, transparency);
208    }
209
210    public static Desktop getDesktop()
211    {
212        if (Desktop.isDesktopSupported())
213            return Desktop.getDesktop();
214
215        return null;
216    }
217
218    /**
219     * Launch the system file manager on specified folder (if supported)
220     * 
221     * @throws IOException
222     */
223    public static boolean openFolder(String folder) throws IOException
224    {
225        final Desktop desktop = getDesktop();
226
227        if ((desktop != null) && desktop.isSupported(Action.OPEN))
228        {
229            desktop.open(new File(folder));
230            return true;
231        }
232
233        return false;
234    }
235
236    /**
237     * @see System#getProperty(String)
238     */
239    public static String getProperty(String name)
240    {
241        return props.getProperty(name);
242    }
243
244    /**
245     * @see System#getProperty(String, String)
246     */
247    public static String getProperty(String name, String defaultValue)
248    {
249        return props.getProperty(name, defaultValue);
250    }
251
252    /**
253     * @see System#setProperty(String, String)
254     */
255    public static String setProperty(String name, String value)
256    {
257        return (String) props.setProperty(name, value);
258    }
259
260    /**
261     * @deprecated Use {@link #getMenuCtrlMask()} instead.
262     */
263    @Deprecated
264    public static int getCtrlMask()
265    {
266        return getMenuCtrlMask();
267    }
268
269    /**
270     * Return the CTRL key mask used for Menu shortcut.
271     */
272    public static int getMenuCtrlMask()
273    {
274        try
275        {
276            return Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
277        }
278        catch (HeadlessException e)
279        {
280            // headless mode, use default Ctrl Mask
281            return Event.CTRL_MASK;
282        }
283    }
284
285    /**
286     * @deprecated Use {@link #getMenuCtrlMask()} instead
287     */
288    @Deprecated
289    public static int getSystemCtrlMask()
290    {
291        return getMenuCtrlMask();
292    }
293
294    public static GraphicsEnvironment getLocalGraphicsEnvironment()
295    {
296        return GraphicsEnvironment.getLocalGraphicsEnvironment();
297    }
298
299    /**
300     * Return the default screen device.
301     */
302    public static GraphicsDevice getDefaultScreenDevice()
303    {
304        if (Icy.getMainInterface().isHeadLess())
305            return null;
306
307        return getLocalGraphicsEnvironment().getDefaultScreenDevice();
308    }
309
310    /**
311     * Return the default graphics configuration.
312     */
313    public static GraphicsConfiguration getDefaultGraphicsConfiguration()
314    {
315        final GraphicsDevice screenDevice = getDefaultScreenDevice();
316
317        if (screenDevice != null)
318            return screenDevice.getDefaultConfiguration();
319
320        return null;
321    }
322
323    /**
324     * @deprecated Use {@link #getDefaultGraphicsConfiguration()} instead.
325     */
326    @Deprecated
327    public static GraphicsConfiguration getSystemGraphicsConfiguration()
328    {
329        return getDefaultGraphicsConfiguration();
330    }
331
332    /**
333     * Return all available screen devices.
334     */
335    public static List<GraphicsDevice> getScreenDevices()
336    {
337        final List<GraphicsDevice> result = new ArrayList<GraphicsDevice>();
338
339        if (Icy.getMainInterface().isHeadLess())
340            return result;
341
342        try
343        {
344            return CollectionUtil.asList(getLocalGraphicsEnvironment().getScreenDevices());
345        }
346        catch (HeadlessException e)
347        {
348            return result;
349        }
350    }
351
352    /**
353     * Return the number of screen device.
354     */
355    public static int getScreenDeviceCount()
356    {
357        if (Icy.getMainInterface().isHeadLess())
358            return 0;
359
360        try
361        {
362            return getLocalGraphicsEnvironment().getScreenDevices().length;
363        }
364        catch (HeadlessException e)
365        {
366            return 0;
367        }
368    }
369
370    /**
371     * Return the screen device corresponding to specified index.
372     */
373    public static GraphicsDevice getScreenDevice(int index)
374    {
375        if (Icy.getMainInterface().isHeadLess())
376            return null;
377
378        try
379        {
380            return getLocalGraphicsEnvironment().getScreenDevices()[index];
381        }
382        catch (HeadlessException e)
383        {
384            return null;
385        }
386    }
387
388    /**
389     * Returns all screen device intersecting the given region.<br>
390     * Can return an empty list if given region do not intersect any screen device.
391     */
392    public static List<GraphicsDevice> getScreenDevices(Rectangle region)
393    {
394        final List<GraphicsDevice> result = new ArrayList<GraphicsDevice>();
395
396        if (Icy.getMainInterface().isHeadLess())
397            return result;
398
399        for (GraphicsDevice gd : getLocalGraphicsEnvironment().getScreenDevices())
400            if (getScreenBounds(gd, true).intersects(region))
401                result.add(gd);
402
403        return result;
404    }
405
406    /**
407     * Returns the main screen device corresponding to the given region.<br>
408     * If the given region intersect multiple screen, it return screen containing the largest area.<br>
409     * Can return <code>null</code> if given region do not intersect any screen device.
410     */
411    public static GraphicsDevice getScreenDevice(Rectangle region)
412    {
413        if (Icy.getMainInterface().isHeadLess())
414            return null;
415
416        GraphicsDevice result = null;
417        Rectangle2D largest = null;
418
419        for (GraphicsDevice gd : getLocalGraphicsEnvironment().getScreenDevices())
420        {
421            final Rectangle2D intersection = getScreenBounds(gd, true).createIntersection(region);
422
423            if (!intersection.isEmpty())
424            {
425                // bigger intersection ?
426                if ((largest == null) || ((intersection.getWidth() * intersection.getHeight()) > (largest.getWidth()
427                        * largest.getHeight())))
428                {
429                    largest = intersection;
430                    result = gd;
431                }
432            }
433        }
434
435        return result;
436    }
437
438    /**
439     * Returns the screen device corresponding to the given position.<br>
440     * Can return <code>null</code> if given position is not located in any screen device.
441     */
442    public static GraphicsDevice getScreenDevice(Point position)
443    {
444        if (Icy.getMainInterface().isHeadLess())
445            return null;
446
447        for (GraphicsDevice gd : getLocalGraphicsEnvironment().getScreenDevices())
448            if (getScreenBounds(gd, false).contains(position))
449                return gd;
450
451        return null;
452    }
453
454    /**
455     * Returns true if current system is "head less" (no screen output device).
456     */
457    public static boolean isHeadLess()
458    {
459        return GraphicsEnvironment.isHeadless();
460    }
461
462    public static ClassLoader getContextClassLoader()
463    {
464        return Thread.currentThread().getContextClassLoader();
465    }
466
467    public static ClassLoader getSystemClassLoader()
468    {
469        return ClassLoader.getSystemClassLoader();
470    }
471
472    public static BufferCapabilities getSystemBufferCapabilities()
473    {
474        final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration();
475
476        if (defaultGC == null)
477            return null;
478
479        return defaultGC.getBufferCapabilities();
480    }
481
482    public static ImageCapabilities getSystemImageCapabilities()
483    {
484        final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration();
485
486        if (defaultGC == null)
487            return null;
488
489        return defaultGC.getImageCapabilities();
490    }
491
492    public static ColorModel getSystemColorModel()
493    {
494        final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration();
495
496        if (defaultGC == null)
497            return null;
498
499        return defaultGC.getColorModel();
500    }
501
502    public static ColorModel getSystemColorModel(int transparency)
503    {
504        final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration();
505
506        if (defaultGC == null)
507            return null;
508
509        return defaultGC.getColorModel(transparency);
510    }
511
512    /**
513     * Return bounds for specified screen.
514     * 
515     * @param removeInsets
516     *        remove any existing taskbars and menubars from the result
517     */
518    public static Rectangle getScreenBounds(GraphicsDevice graphicsDevice, boolean removeInsets)
519    {
520        if (graphicsDevice == null)
521            return new Rectangle();
522
523        final GraphicsConfiguration graphicsConfiguration = graphicsDevice.getDefaultConfiguration();
524        final Rectangle bounds = graphicsConfiguration.getBounds();
525        final Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(graphicsConfiguration);
526
527        bounds.x += insets.left;
528        bounds.y += insets.top;
529        bounds.width -= (insets.left + insets.right);
530        bounds.height -= (insets.top + insets.bottom);
531
532        return bounds;
533    }
534
535    /**
536     * Return the entire desktop bounds (take multi screens in account).
537     * 
538     * @param removeInsets
539     *        remove any existing taskbars and menubars from the result
540     */
541    public static Rectangle getDesktopBounds(boolean removeInsets)
542    {
543        Rectangle result = new Rectangle();
544
545        if (Icy.getMainInterface().isHeadLess())
546            return result;
547
548        final GraphicsDevice[] gs = getLocalGraphicsEnvironment().getScreenDevices();
549
550        for (int j = 0; j < gs.length; j++)
551            result = result.union(getScreenBounds(gs[j], removeInsets));
552
553        return result;
554    }
555
556    /**
557     * Return the entire desktop bounds (take multi screens in account)
558     * 
559     * @see #getDesktopBounds(boolean)
560     */
561    public static Rectangle getDesktopBounds()
562    {
563        return getDesktopBounds(true);
564    }
565
566    /**
567     * {@link GraphicsEnvironment#getMaximumWindowBounds()}
568     */
569    public static Rectangle getMaximumWindowBounds()
570    {
571        if (Icy.getMainInterface().isHeadLess())
572            return new Rectangle();
573
574        return getLocalGraphicsEnvironment().getMaximumWindowBounds();
575    }
576
577    /**
578     * {@link GraphicsDevice#getDisplayMode()}
579     */
580    public static DisplayMode getSystemDisplayMode()
581    {
582        final GraphicsDevice screenDevice = getDefaultScreenDevice();
583
584        if (screenDevice != null)
585            return screenDevice.getDisplayMode();
586
587        return null;
588    }
589
590    /**
591     * @deprecated Use {@link #getNumberOfCPUs()} instead
592     */
593    @Deprecated
594    public static int getAvailableProcessors()
595    {
596        return Runtime.getRuntime().availableProcessors();
597    }
598
599    /**
600     * Return total number of processors or cores available to the JVM (same as system)
601     */
602    public static int getNumberOfCPUs()
603    {
604        return Runtime.getRuntime().availableProcessors();
605    }
606
607    /**
608     * Return total amount of free memory available to the JVM (in bytes)
609     */
610    public static long getJavaFreeMemory()
611    {
612        return getJavaMaxMemory() - getJavaUsedMemory();
613    }
614
615    /**
616     * Return maximum amount of memory the JVM will attempt to use (in bytes)
617     */
618    public static long getJavaMaxMemory()
619    {
620        return Runtime.getRuntime().maxMemory();
621    }
622
623    /**
624     * @deprecated Use {@link #getJavaAllocatedMemory()} instead.
625     */
626    @Deprecated
627    public static long getJavaTotalMemory()
628    {
629        return getJavaAllocatedMemory();
630    }
631
632    /**
633     * Return memory currently allocated by the JVM (in bytes)
634     */
635    public static long getJavaAllocatedMemory()
636    {
637        return Runtime.getRuntime().totalMemory();
638    }
639
640    /**
641     * Return actual memory used by the JVM (in bytes)
642     */
643    public static long getJavaUsedMemory()
644    {
645        return getJavaAllocatedMemory() - Runtime.getRuntime().freeMemory();
646    }
647
648    private static OperatingSystemMXBean getOSMXBean()
649    {
650        final java.lang.management.OperatingSystemMXBean bean = ManagementFactory.getOperatingSystemMXBean();
651
652        if (bean instanceof OperatingSystemMXBean)
653            return (OperatingSystemMXBean) bean;
654
655        // for (Method method : bean.getClass().getDeclaredMethods())
656        // {
657        // final int modifiers=method.getModifiers();
658        //
659        // method.setAccessible(true);
660        // if (method.getName().startsWith("get")
661        // && Modifier.isPublic(modifiers)) {
662        // Object value;
663        // try {
664        // value = method.invoke(bean);
665        // } catch (Exception e) {
666        // value = e;
667        // } // try
668        // System.out.println(method.getName() + " = " + value);
669        // } // if
670        // } // for
671
672        return null;
673    }
674
675    /**
676     * Return total physic memory of system (in bytes)
677     */
678    public static long getTotalMemory()
679    {
680        final OperatingSystemMXBean bean = getOSMXBean();
681
682        if (bean != null)
683            return bean.getTotalPhysicalMemorySize();
684
685        return -1L;
686    }
687
688    /**
689     * @deprecated Use {@link #getTotalMemory()} instead
690     */
691    @Deprecated
692    public static long getSystemTotalMemory()
693    {
694        return getTotalMemory();
695    }
696
697    /**
698     * Return free physic memory of system (in bytes)
699     */
700    public static long getFreeMemory()
701    {
702        final OperatingSystemMXBean bean = getOSMXBean();
703
704        if (bean != null)
705            return bean.getFreePhysicalMemorySize();
706
707        return -1L;
708    }
709
710    /**
711     * @deprecated Use {@link #getFreeMemory()} instead
712     */
713    @Deprecated
714    public static long getSystemFreeMemory()
715    {
716        return getFreeMemory();
717    }
718
719    /**
720     * Return system process CPU time
721     */
722    public static long getProcessCpuTime()
723    {
724        final OperatingSystemMXBean bean = getOSMXBean();
725
726        if (bean != null)
727            return bean.getProcessCpuTime();
728
729        return -1L;
730    }
731
732    /**
733     * @deprecated Use {@link #getProcessCpuTime()} instead
734     */
735    @Deprecated
736    public static long getSystemProcessCpuTime()
737    {
738        return getProcessCpuTime();
739    }
740
741    /**
742     * Return average CPU load of the application processes from the last call<br>
743     * (-1 if no available)
744     */
745    public static int getCpuLoad()
746    {
747        final OperatingSystemMXBean bean = getOSMXBean();
748
749        if (bean != null)
750        {
751            // first call
752            if (lastNano == 0)
753            {
754                lastNano = System.nanoTime();
755                lastCpu = bean.getProcessCpuTime();
756            }
757            else
758            {
759                final long nanoAfter = System.nanoTime();
760                final long cpuAfter = bean.getProcessCpuTime();
761
762                final long dNano = nanoAfter - lastNano;
763                final long dCpu = cpuAfter - lastCpu;
764
765                // below 0.5s the reported value isn't very significant
766                if (dNano > 500000000L)
767                {
768                    lastCpuLoad = (int) ((dCpu * 100L) / (dNano * getNumberOfCPUs()));
769                    lastNano = nanoAfter;
770                    lastCpu = cpuAfter;
771                }
772            }
773
774            return lastCpuLoad;
775        }
776
777        return -1;
778    }
779
780    /**
781     * @deprecated Use {@link #getCpuLoad()} instead
782     */
783    @Deprecated
784    public static int getSystemCpuLoad()
785    {
786        return getCpuLoad();
787    }
788
789    /**
790     * Returns the user name.
791     */
792    public static String getUserName()
793    {
794        return getProperty("user.name");
795    }
796
797    /**
798     * Returns the JVM name.
799     */
800    public static String getJavaName()
801    {
802        return getProperty("java.runtime.name");
803    }
804
805    /**
806     * Returns the JVM version.
807     */
808    public static String getJavaVersion()
809    {
810        String result = getProperty("java.runtime.version");
811
812        if (result.equals("unknow"))
813            result = getProperty("java.version");
814
815        return result;
816    }
817
818    /**
819     * Returns the JVM version in number format (ex: 6.091, 7.071, 8.151..)
820     */
821    public static double getJavaVersionAsNumber()
822    {
823        // remove all unwanted characters
824        String version = getJavaVersion().replaceAll("[^\\d.]", "");
825        // find first digit separator
826        int firstSepInd = version.indexOf('.');
827
828        if (firstSepInd >= 0)
829        {
830            // version 1.xxx ?
831            if (version.substring(0, firstSepInd).equals("1"))
832            {
833                // remove "1."
834                version = version.substring(firstSepInd + 1);
835                // get first "." index
836                firstSepInd = version.indexOf('.');
837            }
838
839            int lastSepInd = version.lastIndexOf('.');
840            while (lastSepInd != firstSepInd)
841            {
842                version = version.substring(0, lastSepInd) + version.substring(lastSepInd + 1);
843                lastSepInd = version.lastIndexOf('.');
844            }
845
846            if (version.charAt(firstSepInd + 1) == '0')
847                version = version.substring(0, lastSepInd + 1) + version.substring(lastSepInd + 2);
848        }
849
850        return StringUtil.parseDouble(version, 0);
851    }
852
853    /**
854     * Returns the JVM integer version (ex: 6.0.91, 7.0.71, 8.0.151..)
855     */
856    public static Version getJavaVersionAsVersion()
857    {
858        // replace separators by '.'
859        String version = getJavaVersion().replaceAll("-", ".");
860        version = version.replaceAll("_", ".");
861        // then remove all unwanted characters
862        version = version.replaceAll("[^\\d.]", "");
863
864        int firstSepInd = version.indexOf('.');
865
866        if (firstSepInd >= 0)
867        {
868            // version 1.xxx ?
869            if (version.substring(0, firstSepInd).equals("1"))
870            {
871                // remove "1."
872                version = version.substring(firstSepInd + 1);
873                // get first "." index
874                firstSepInd = version.indexOf('.');
875            }
876        }
877
878        return new Version(version);
879    }
880
881    /**
882     * Returns the JVM data architecture model.
883     */
884    public static int getJavaArchDataModel()
885    {
886        return Integer.parseInt(getProperty("sun.arch.data.model"));
887    }
888
889    /**
890     * Returns the Operating System name.
891     */
892    public static String getOSName()
893    {
894        return getProperty("os.name");
895    }
896
897    /**
898     * Returns the Operating System architecture name.
899     */
900    public static String getOSArch()
901    {
902        return getProperty("os.arch");
903    }
904
905    /**
906     * Returns the Operating System version.
907     */
908    public static String getOSVersion()
909    {
910        return getProperty("os.version");
911    }
912
913    /**
914     * Return an id OS string :<br>
915     * <br>
916     * Windows system return <code>SystemUtil.SYSTEM_WINDOWS</code><br>
917     * MAC OS return <code>SystemUtil.SYSTEM_MAC_OS</code><br>
918     * Unix system return <code>SystemUtil.SYSTEM_UNIX</code><br>
919     * <br>
920     * An empty string is returned is OS is unknown.
921     */
922    public static String getOSNameId()
923    {
924        if (isWindows())
925            return SYSTEM_WINDOWS;
926        if (isMac())
927            return SYSTEM_MAC_OS;
928        if (isUnix())
929            return SYSTEM_UNIX;
930
931        return "";
932    }
933
934    /**
935     * Return an id OS architecture string<br>
936     * example : "win32", "win64", "mac32", "mac64", "unix32"...<br>
937     * The bits number depends only from current installed JVM (32 or 64 bit)
938     * and not directly from host OS.<br>
939     * An empty string is returned if OS is unknown.
940     */
941    public static String getOSArchIdString()
942    {
943        final String javaBit = Integer.toString(getJavaArchDataModel());
944
945        if (isWindows())
946            return SYSTEM_WINDOWS + javaBit;
947        if (isMac())
948            return SYSTEM_MAC_OS + javaBit;
949        if (isUnix())
950            return SYSTEM_UNIX + javaBit;
951
952        return "";
953    }
954
955    /**
956     * Returns true is the operating system support link (symbolic or not).
957     */
958    public static boolean isLinkSupported()
959    {
960        return isMac() || isUnix();
961    }
962
963    /**
964     * Returns true is the JVM is 32 bits.
965     */
966    public static boolean is32bits()
967    {
968        return getJavaArchDataModel() == 32;
969    }
970
971    /**
972     * Returns true is the JVM is 64 bits.
973     */
974    public static boolean is64bits()
975    {
976        return getJavaArchDataModel() == 64;
977    }
978
979    /**
980     * @deprecated Use {@link #isWindows()} instead.
981     */
982    @Deprecated
983    public static boolean isWindow()
984    {
985        return isWindows();
986    }
987
988    /**
989     * Returns true is the Operating System is Windows based.
990     */
991    public static boolean isWindows()
992    {
993        return (getOSName().toLowerCase().indexOf("win") >= 0);
994    }
995
996    /**
997     * Returns true is the Operating System is Mac OS based.
998     */
999    public static boolean isMac()
1000    {
1001        return (getOSName().toLowerCase().indexOf("mac") >= 0);
1002    }
1003
1004    /**
1005     * Returns true is the Operating System is Unix / Linux based.
1006     */
1007    public static boolean isUnix()
1008    {
1009        final String os = getOSName().toLowerCase();
1010        return (os.indexOf("nix") >= 0) || (os.indexOf("nux") >= 0);
1011    }
1012
1013    /**
1014     * Returns true is the Operating System is Windows 64 bits whatever is the JVM installed (32 or 64 bits).
1015     */
1016    public static boolean isWindows64()
1017    {
1018        if (!isWindows())
1019            return false;
1020
1021        final String wow64Arch = System.getenv("PROCESSOR_ARCHITEW6432");
1022        if ((wow64Arch != null) && wow64Arch.endsWith("64"))
1023            return true;
1024
1025        final String arch = System.getenv("PROCESSOR_ARCHITECTURE");
1026        if ((arch != null) && arch.endsWith("64"))
1027            return true;
1028
1029        return false;
1030    }
1031
1032    /**
1033     * Returns default temporary directory.<br>
1034     * ex:<br>
1035     * <code>c:/temp</code><br>
1036     * <code>/tmp</code><br>
1037     * Same as {@link FileUtil#getTempDirectory()}
1038     */
1039    public static String getTempDirectory()
1040    {
1041        return FileUtil.getTempDirectory();
1042    }
1043
1044    /**
1045     * Returns temporary native library path (used to load native libraries from plugin)
1046     */
1047    public static String getTempLibraryDirectory()
1048    {
1049        return FileUtil.getTempDirectory() + "/lib";
1050    }
1051
1052    public static boolean addToJavaLibraryPath(String directories[])
1053    {
1054        try
1055        {
1056            final String path_separator = System.getProperty("path.separator");
1057
1058            // patch user library paths...
1059            final Field pathsField = ReflectionUtil.getField(ClassLoader.class, "usr_paths", true);
1060            // get current user paths
1061            final ArrayList<String> userPaths = CollectionUtil.asArrayList((String[]) pathsField.get(null));
1062            // get current system paths
1063            String sysPaths = System.getProperty("java.library.path");
1064
1065            for (String dir : directories)
1066            {
1067                if (!userPaths.contains(dir))
1068                    userPaths.add(dir);
1069                if (!sysPaths.contains(dir))
1070                    sysPaths += path_separator + dir;
1071            }
1072
1073            // set back user library path
1074            pathsField.set(null, userPaths.toArray(new String[userPaths.size()]));
1075            // set back system library path
1076            System.setProperty("java.library.path", sysPaths);
1077
1078            return true;
1079        }
1080        catch (Exception e)
1081        {
1082            System.err.println(e.getMessage());
1083            System.err.println("Cannot patch Java Library Path.");
1084
1085            return false;
1086        }
1087    }
1088
1089    /**
1090     * Load the specified native library.
1091     * 
1092     * @param dir
1093     *        directory from where we want to load the native library.
1094     * @param name
1095     *        name of the library.<br/>
1096     *        The filename of the library is automatically built depending the operating system.
1097     */
1098    public static void loadLibrary(String dir, String name)
1099    {
1100        final File libPath = new File(dir, System.mapLibraryName(name));
1101
1102        if (libPath.exists())
1103            System.load(libPath.getAbsolutePath());
1104        else
1105            System.loadLibrary(name);
1106    }
1107
1108    /**
1109     * Load the specified native library.
1110     * 
1111     * @param pathname
1112     *        complete path or name of the library we want to load
1113     */
1114    public static void loadLibrary(String pathname)
1115    {
1116        final File file = new File(pathname);
1117
1118        if (file.exists())
1119            System.load(file.getAbsolutePath());
1120        else
1121            System.loadLibrary(pathname);
1122    }
1123}