Newsfeed: use a custom HTTP User-Agent
[scilab.git] / scilab / modules / core / src / java / org / scilab / modules / core / Scilab.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2007-2008 - INRIA - Allan CORNET
4  * Copyright (C) 2007-2008 - INRIA - Vincent COUVERT
5  * Copyright (C) 2007-2008 - INRIA - Sylvestre LEDRU
6  * Copyright (C) 2007-2008 - INRIA - Jean-Baptiste SILVY
7  * Copyright (C) 2007-2008 - INRIA - Bruno JOFRET
8  * Copyright (C) 2011 - Calixte DENIZET
9  *
10  * Copyright (C) 2012 - 2016 - Scilab Enterprises
11  *
12  * This file is hereby licensed under the terms of the GNU GPL v2.0,
13  * pursuant to article 5.3.4 of the CeCILL v.2.1.
14  * This file was originally licensed under the terms of the CeCILL v2.1,
15  * and continues to be available under such terms.
16  * For more information, see the COPYING file which you should have received
17  * along with this program.
18  *
19  */
20
21 package org.scilab.modules.core;
22
23 import java.awt.GraphicsEnvironment;
24 import java.awt.Toolkit;
25 import java.util.ArrayList;
26 import java.util.List;
27
28 import javax.swing.JPopupMenu;
29 import javax.swing.SwingUtilities;
30
31 import org.flexdock.docking.DockingConstants;
32 import org.flexdock.docking.DockingManager;
33 import org.scilab.modules.commons.OS;
34 import org.scilab.modules.commons.ScilabCommons;
35 import org.scilab.modules.commons.ScilabCommonsUtils;
36 import org.scilab.modules.commons.ScilabConstants;
37 import org.scilab.modules.commons.xml.XConfiguration;
38 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
39 import org.scilab.modules.graphic_objects.graphicObject.GraphicObject.Type;
40 import org.scilab.modules.graphic_objects.utils.MenuBarBuilder;
41 import org.scilab.modules.gui.SwingView;
42 import org.scilab.modules.gui.bridge.console.SwingScilabConsole;
43 import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel;
44 import org.scilab.modules.gui.bridge.window.SwingScilabWindow;
45 import org.scilab.modules.gui.console.ScilabConsole;
46 import org.scilab.modules.gui.tabfactory.ScilabTabFactory;
47 import org.scilab.modules.gui.utils.ClosingOperationsManager;
48 import org.scilab.modules.gui.utils.ConfigManager;
49 import org.scilab.modules.gui.utils.LookAndFeelManager;
50 import org.scilab.modules.gui.utils.WindowsConfigurationManager;
51
52 /**
53  * Main Class for Scilab
54  * @author Allan CORNET
55  * @author Jean-Baptiste SILVY
56  * @author Vincent COUVERT
57  * @author Sylvestre Ledru
58  * @author Bruno JOFRET
59  * @author Calixte DENIZET
60  */
61 public class Scilab {
62
63     static {
64         System.setProperty("java.protocol.handler.pkgs", "org.scilab.modules.commons");
65         XConfiguration.getXConfigurationDocument();
66     }
67
68     /** Index of windows vista version */
69     private static final double VISTA_VERSION = 6.0;
70
71     private static final String ENABLE_JAVA2D_OPENGL_PIPELINE = "sun.java2d.opengl";
72     private static final String ENABLE = "true";
73     private static final String DISABLE = "false";
74     private static final String DISABLE_DDRAW = "sun.java2d.noddraw";
75     private static final String OSNAME = "os.name";
76     private static final String MACOS = "mac";
77
78     private static boolean success;
79     private static boolean finish;
80     private static boolean exitCalled;
81     private static int mode;
82
83     private static List<Runnable> finalhooks = new ArrayList<Runnable>();
84     private static List<Runnable> initialhooks = new ArrayList<Runnable>();
85
86     /**
87      * WARNING : mainView is directly referenced from a JNI even it's private.
88      * TODO : Better add getter for this variable.
89      */
90     private SwingScilabWindow mainView;
91
92     /**
93      * Constructor Scilab Class.
94      * @param mode Mode Scilab -NW -NWNI -STD -API
95      */
96     public Scilab(int mode) {
97         Scilab.mode = mode;
98         ScilabConstants.setMode(mode);
99
100         DockingManager.setDockableFactory(ScilabTabFactory.getInstance());
101
102         /*
103          * Set Scilab directory. Note that it is done in the constructor
104          * and not as directly when setting the member because we had some
105          * race condition. See bug #4419
106          */
107         try {
108             /*
109              * Set Java directories to Scilab ones
110              */
111             if (mode != 1) {
112                 /* only modify these properties if Scilab is not called by another application */
113                 /* In this case, we let the calling application to use its own properties */
114                 System.setProperty("java.io.tmpdir", ScilabConstants.TMPDIR.getCanonicalPath());
115                 System.setProperty("user.home", ScilabConstants.SCIHOME.getCanonicalPath());
116
117                 /* build a standard User-Agent string */
118                 StringBuilder str = new StringBuilder();
119                 str.append("Scilab/").append(ScilabCommons.getScilabVersionMajor()).append('.').append(ScilabCommons.getScilabVersionMinor()).append('.').append(ScilabCommons.getScilabVersionMaintenance());
120                 str.append(' ');
121                 str.append('(').append(System.getProperty("os.name")).append(' ').append(System.getProperty("os.arch")).append(')');
122                 System.setProperty("http.agent", str.toString());
123             }
124
125         } catch (Exception e) {
126             System.err.println("Cannot retrieve the variable SCI. Please report on http://bugzilla.scilab.org/");
127             System.err.println(e.getLocalizedMessage());
128             System.exit(-1);
129         }
130
131         /*
132          * Set options for JOGL
133          * they must be set before creating GUI
134          */
135         setJOGLFlags();
136         /* Mode GUI */
137         if (mode == 2) {
138             SwingView.registerSwingView();
139         }
140
141         /*
142          * if not API mode
143          * bug 3673 by default in API mode we dont modify look n feel
144          * If SCI_JAVA_ENABLE_HEADLESS is set, do not set the look and feel.
145          * (needed when building the documentation under *ux)
146          */
147         if (mode != 1 && System.getenv("SCI_JAVA_ENABLE_HEADLESS") == null) {
148             /* http://java.sun.com/docs/books/tutorial/uiswing/lookandfeel/plaf.html */
149             try {
150
151                 String scilabLookAndFeel = "javax.swing.plaf.metal.MetalLookAndFeel";
152
153                 if (OS.get() == OS.WINDOWS) {
154                     scilabLookAndFeel = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
155                 } else if (System.getProperty(OSNAME).toLowerCase().indexOf(MACOS) != -1) {
156                     /** OPTION ADDED TO ALLOW DOCKING UNDER MACOSX */
157                     System.setProperty(DockingConstants.HEAVYWEIGHT_DOCKABLES, ENABLE);
158                     scilabLookAndFeel = "apple.laf.AquaLookAndFeel";
159                 } else {
160                     scilabLookAndFeel = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
161
162                     /*
163                      * Linux specific desktop integration
164                      */
165                     if (!GraphicsEnvironment.isHeadless()) {
166                         try {
167                             Toolkit xToolkit = Toolkit.getDefaultToolkit();
168                             java.lang.reflect.Field awtAppClassNameField =
169                                 xToolkit.getClass().getDeclaredField("awtAppClassName");
170                             awtAppClassNameField.setAccessible(true);
171
172                             awtAppClassNameField.set(xToolkit, "Scilab");
173                         } catch (Exception e) {
174                             System.err.println("Unable to set WM_CLASS, please report a bug on http://bugzilla.scilab.org/.");
175                             System.err.println("Error: " + e.getLocalizedMessage());
176                         }
177                     }
178                 }
179
180                 /* Init the LookAndFeelManager all the time since we can
181                  * create windows in the NW mode */
182                 if (!GraphicsEnvironment.isHeadless()) {
183                     LookAndFeelManager lookAndFeel = new LookAndFeelManager();
184
185                     if (lookAndFeel.isSupportedLookAndFeel(scilabLookAndFeel)) {
186                         lookAndFeel.setLookAndFeel(scilabLookAndFeel);
187                     } else {
188                         lookAndFeel.setSystemLookAndFeel();
189                     }
190                 }
191             } catch (java.lang.NoClassDefFoundError exception) {
192                 System.err.println("Could not initialize graphics Environment");
193                 System.err.println("Scilab Graphical option may not be working correctly.");
194                 System.err.println("An error occurred: " + exception.getLocalizedMessage());
195             }
196         }
197
198         if (mode == 2) { /* Mode GUI */
199             // Create a user config file if not already exists
200             ConfigManager.createUserCopy();
201
202             Integer consoleId = GraphicController.getController().askObject(Type.JAVACONSOLE);
203             MenuBarBuilder.buildConsoleMenuBar(consoleId);
204
205             SwingScilabConsole sciConsole = ((SwingScilabConsole) ScilabConsole.getConsole().getAsSimpleConsole());
206             SwingScilabDockablePanel consoleTab = (SwingScilabDockablePanel) sciConsole.getParent();
207
208             WindowsConfigurationManager.restorationFinished(consoleTab);
209
210             mainView = SwingScilabWindow.allScilabWindows.get(consoleTab.getParentWindowId());
211         } else {
212             GraphicController.getController().askObject(Type.CONSOLE);
213         }
214     }
215
216     /**
217      * @return the current mode
218      */
219     public static int getMode() {
220         return mode;
221     }
222
223     /**
224      * Sets the prompt displayed in Scilab console
225      * @param prompt the prompt to be displayed as a String
226      */
227     public void setPrompt(String prompt) {
228         ScilabConsole.getConsole().setPrompt(prompt);
229     }
230
231     /**
232      * Set the command line flags to the JVM
233      */
234     public static void setJOGLFlags() {
235
236         // Must give popUpMenu heavy weight
237         // in case we enable GLCanvas
238         JPopupMenu.setDefaultLightWeightPopupEnabled(false);
239         // Uneash OpenGL power
240         // Not yet
241         //System.setProperty(ENABLE_JAVA2D_OPENGL_PIPELINE, ENABLE_WITH_DEBUG);
242         System.setProperty(ENABLE_JAVA2D_OPENGL_PIPELINE, DISABLE);
243
244         if (OS.get() == OS.WINDOWS) {
245             if ((Double) OS.get().getVersion() >= VISTA_VERSION) {
246                 // don't enable OpenGL because of aero
247                 System.setProperty(ENABLE_JAVA2D_OPENGL_PIPELINE, DISABLE);
248             }
249             // desactivate direct3d and direct draw under windows
250             System.setProperty(DISABLE_DDRAW, ENABLE);
251         }
252     }
253
254     /**
255      * Call from canCloseMainScilabObject (call itself from sci_exit)
256      * @return true if the console is closed
257      */
258     public static boolean canClose() {
259         final Object lock = new Object();
260
261         SwingUtilities.invokeLater(new Runnable() {
262             @Override
263             public void run() {
264                 exitCalled = true;
265                 success = ClosingOperationsManager.startClosingOperationOnRoot();
266                 exitCalled = false;
267
268                 finish = true;
269                 synchronized (lock) {
270                     lock.notify();
271                 }
272             }
273         });
274
275         try {
276             synchronized (lock) {
277                 while (!finish) {
278                     lock.wait();
279                 }
280             }
281         } catch (InterruptedException e) {
282             System.err.println(e);
283         }
284         finish = false;
285
286         return success;
287     }
288
289     /**
290      * Call from forceCloseMainScilabObject (call itself from sci_exit)
291      */
292     public static void forceClose() {
293         final Object lock = new Object();
294
295         SwingUtilities.invokeLater(new Runnable() {
296             @Override
297             public void run() {
298                 exitCalled = true;
299                 ClosingOperationsManager.forceClosingOperationOnRoot();
300                 exitCalled = false;
301
302                 finish = true;
303                 synchronized (lock) {
304                     lock.notify();
305                 }
306             }
307         });
308
309         try {
310             synchronized (lock) {
311                 while (!finish) {
312                     lock.wait();
313                 }
314             }
315         } catch (InterruptedException e) {
316             System.err.println(e);
317         }
318         finish = false;
319     }
320
321     /**
322      * @return true if exit has been called from command line
323      */
324     public static boolean getExitCalled() {
325         return exitCalled;
326     }
327
328     /**
329      * Register a hook to execute just before the JVM shutdown.
330      * A hook should not contain threads, there is no warranty that they will be fully executed.
331      */
332     public static void registerFinalHook(Runnable hook) {
333         finalhooks.add(hook);
334     }
335
336     /**
337      * Remove a hook
338      */
339     public static void removeFinalHook(Runnable hook) {
340         finalhooks.remove(hook);
341     }
342
343     /**
344      * This method should be called from jni (finishMainScilabObject())
345      */
346     public static void executeFinalHooks() {
347         for (Runnable hook : finalhooks) {
348             hook.run();
349         }
350     }
351
352     /**
353      * Register a hook to execute after the Scilab initialization.
354      * A hook should not contain threads, there is no warranty that they will be fully executed.
355      */
356     public static void registerInitialHook(Runnable hook) {
357         initialhooks.add(hook);
358     }
359
360     /**
361      * Remove a hook
362      */
363     public static void removeInitialHook(Runnable hook) {
364         initialhooks.remove(hook);
365     }
366
367     /**
368      * This method should be called from C (realmain)
369      */
370     public static void executeInitialHooks() {
371         ScilabCommonsUtils.registerScilabThread();
372
373         for (final Runnable hook : initialhooks) {
374             hook.run();
375         }
376     }
377 }
378 /*--------------------------------------------------------------------------*/