OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 156 | Rev 177 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
18 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.erp.config;
15
 
156 ilm 16
import static java.lang.System.getProperty;
17
 
18 ilm 18
import org.openconcerto.erp.action.NouvelleConnexionAction;
19
import org.openconcerto.erp.core.common.ui.PanelFrame;
20
import org.openconcerto.erp.panel.PostgreSQLFrame;
80 ilm 21
import org.openconcerto.erp.panel.UserExitConf;
18 ilm 22
import org.openconcerto.erp.panel.UserExitPanel;
41 ilm 23
import org.openconcerto.erp.preferences.UIPreferencePanel;
73 ilm 24
import org.openconcerto.erp.rights.ComptaTotalUserRight;
18 ilm 25
import org.openconcerto.ftp.updater.UpdateManager;
26
import org.openconcerto.sql.Configuration;
27
import org.openconcerto.sql.PropsConfiguration;
73 ilm 28
import org.openconcerto.sql.RemoteShell;
18 ilm 29
import org.openconcerto.sql.element.UISQLComponent;
19 ilm 30
import org.openconcerto.sql.model.SQLBase;
80 ilm 31
import org.openconcerto.sql.model.SQLDataSource;
18 ilm 32
import org.openconcerto.sql.model.SQLRequestLog;
142 ilm 33
import org.openconcerto.sql.model.SQLRowAccessor;
80 ilm 34
import org.openconcerto.sql.model.SQLSystem;
142 ilm 35
import org.openconcerto.sql.request.BaseFillSQLRequest;
18 ilm 36
import org.openconcerto.sql.request.ComboSQLRequest;
37
import org.openconcerto.sql.sqlobject.ElementComboBox;
80 ilm 38
import org.openconcerto.sql.sqlobject.IComboSelectionItem;
83 ilm 39
import org.openconcerto.sql.ui.SoftwareInfoPanel;
73 ilm 40
import org.openconcerto.sql.users.rights.UserRightsManager;
156 ilm 41
import org.openconcerto.sql.utils.ReOrder;
80 ilm 42
import org.openconcerto.sql.view.EditPanel;
156 ilm 43
import org.openconcerto.sql.view.IListFrame;
18 ilm 44
import org.openconcerto.sql.view.list.IListe;
45
import org.openconcerto.ui.FrameUtil;
80 ilm 46
import org.openconcerto.ui.component.ITextCombo;
18 ilm 47
import org.openconcerto.ui.component.WaitIndeterminatePanel;
41 ilm 48
import org.openconcerto.ui.preferences.EmailProps;
80 ilm 49
import org.openconcerto.utils.CompareUtils;
18 ilm 50
import org.openconcerto.utils.ExceptionHandler;
51
import org.openconcerto.utils.FileUtils;
144 ilm 52
import org.openconcerto.utils.ThrowableHandler;
18 ilm 53
import org.openconcerto.utils.protocol.Helper;
174 ilm 54
import org.openconcerto.xml.FastXMLProperties;
18 ilm 55
 
56
import java.awt.AWTEvent;
57
import java.awt.Component;
156 ilm 58
import java.awt.Desktop;
18 ilm 59
import java.awt.Image;
60
import java.awt.SplashScreen;
61
import java.awt.Toolkit;
62
import java.awt.event.AWTEventListener;
63
import java.awt.event.HierarchyEvent;
64
import java.awt.event.WindowAdapter;
65
import java.awt.event.WindowEvent;
151 ilm 66
import java.beans.PropertyChangeEvent;
67
import java.beans.PropertyChangeListener;
18 ilm 68
import java.io.BufferedReader;
144 ilm 69
import java.io.ByteArrayOutputStream;
18 ilm 70
import java.io.File;
156 ilm 71
import java.io.FileInputStream;
72
import java.io.FileOutputStream;
18 ilm 73
import java.io.IOException;
74
import java.io.InputStreamReader;
144 ilm 75
import java.io.PrintStream;
28 ilm 76
import java.lang.Thread.UncaughtExceptionHandler;
18 ilm 77
import java.net.InetAddress;
78
import java.net.NetworkInterface;
156 ilm 79
import java.net.URI;
73 ilm 80
import java.net.URL;
80 ilm 81
import java.net.UnknownHostException;
73 ilm 82
import java.security.AllPermission;
83
import java.security.Permission;
84
import java.security.PermissionCollection;
85
import java.security.Policy;
86
import java.security.ProtectionDomain;
80 ilm 87
import java.sql.SQLException;
18 ilm 88
import java.util.ArrayList;
89
import java.util.Enumeration;
151 ilm 90
import java.util.HashSet;
18 ilm 91
import java.util.List;
156 ilm 92
import java.util.Properties;
151 ilm 93
import java.util.Set;
18 ilm 94
 
95
import javax.swing.ImageIcon;
96
import javax.swing.JDialog;
97
import javax.swing.JFrame;
80 ilm 98
import javax.swing.JOptionPane;
18 ilm 99
import javax.swing.SwingUtilities;
100
 
101
public class Gestion {
102
 
25 ilm 103
    public static final File MODULES_DIR = new File("Modules");
104
 
20 ilm 105
    /**
106
     * When this system property is set to <code>true</code>, Gestion will hide most of its normal
107
     * UI. E.g. no SOCIETE selection in the login panel, minimalist menu bar, etc.
108
     */
109
    public static final String MINIMAL_PROP = "org.openconcerto.erp.minimal";
110
 
18 ilm 111
    private static List<Image> frameIcon;
112
    // Check that we are on Mac OS X. This is crucial to loading and using the OSXAdapter class.
113
    static final boolean MAC_OS_X = System.getProperty("os.name").toLowerCase().startsWith("mac os x");
114
 
115
    static boolean inWebStart() {
116
        // cannot rely on system properties since they vary from one implementation to another
117
        try {
26 ilm 118
            // ATTN on OpenJDK jnlp classes are in rt.jar, so this doesn't throw
119
            // ClassNotFoundException, we have to check the result
120
            final String[] names = (String[]) Class.forName("javax.jnlp.ServiceManager").getMethod("getServiceNames").invoke(null);
121
            return names != null && names.length > 0;
18 ilm 122
        } catch (Throwable e) {
123
            return false;
124
        }
125
    }
126
 
127
    public static void openPDF(File f) {
128
        try {
129
            FileUtils.openFile(f);
130
        } catch (IOException e) {
132 ilm 131
            JOptionPane.showMessageDialog(null,
132
                    "Impossible d'ouvrir le fichier " + f + ".\nVérifiez qu'un logiciel pour lire les fichiers PDF est installé sur votre ordinateur.\nVoir http://get.adobe.com/fr/reader.",
133
                    "Erreur d'ouverture du PDF", JOptionPane.ERROR_MESSAGE);
18 ilm 134
        }
135
    }
136
 
20 ilm 137
    public static final boolean isMinimalMode() {
138
        return Boolean.getBoolean(MINIMAL_PROP);
139
    }
140
 
73 ilm 141
    static private final PermissionCollection ALL_PERMS;
142
    static {
143
        final AllPermission allPermission = new AllPermission();
144
        ALL_PERMS = allPermission.newPermissionCollection();
145
        ALL_PERMS.add(allPermission);
146
        ALL_PERMS.setReadOnly();
147
    }
148
 
149
    // install a security manager so that we can restrict modules permissions
150
    private static void initSecurity() {
151
        // extensions (like sunjce_provider) need all permissions
152
        final String[] extDirs = System.getProperty("java.ext.dirs").split(File.pathSeparator);
153
        final List<String> canonExtDirs = new ArrayList<String>(extDirs.length);
154
        for (final String extDir : extDirs) {
155
            try {
156
                canonExtDirs.add(new File(extDir).getCanonicalPath());
157
            } catch (IOException e) {
158
                System.err.println("Couldn't add extension dir : " + extDir);
159
                e.printStackTrace();
160
            }
161
        }
162
 
163
        // our class loader gets all permission
164
        final ClassLoader mainLoader = Gestion.class.getClassLoader();
165
        Policy.setPolicy(new Policy() {
166
            private boolean isExt(ProtectionDomain domain) {
167
                final URL location = domain.getCodeSource().getLocation();
168
                if ("file".equals(location.getProtocol())) {
169
                    try {
170
                        final String canonPath = new File(location.toURI()).getCanonicalPath();
171
                        for (final String canonExtDir : canonExtDirs) {
172
                            if (canonPath.startsWith(canonExtDir))
173
                                return true;
174
                        }
175
                    } catch (Exception e) {
176
                        e.printStackTrace();
177
                    }
178
                }
179
                return false;
180
            }
181
 
182
            @Override
183
            public PermissionCollection getPermissions(ProtectionDomain domain) {
184
                if (domain != null && (domain.getClassLoader() == mainLoader || isExt(domain))) {
185
                    return ALL_PERMS;
186
                } else {
187
                    return super.getPermissions(domain);
188
                }
189
            }
190
 
191
            // have to overload since our superclass caches the permissions of the protection domain
192
            // of this instance in initPolicy()
193
            @Override
194
            public boolean implies(ProtectionDomain domain, Permission permission) {
195
                if (domain != null && domain.getClassLoader() == mainLoader) {
196
                    return true;
197
                }
142 ilm 198
                // super caches results (avoid calling expensive isExt())
199
                return super.implies(domain, permission);
200
 
73 ilm 201
            }
202
        });
203
 
204
        System.setSecurityManager(new SecurityManager());
205
    }
206
 
18 ilm 207
    public static void main(String[] args) {
174 ilm 208
        System.setProperty("org.xml.sax.driver", "com.bluecast.xml.Piccolo");
209
        System.setProperty("org.xml.sax.parser", "com.bluecast.xml.Piccolo");
210
        System.setProperty("javax.xml.parsers.SAXParserFactory", "com.bluecast.xml.JAXPSAXParserFactory");
144 ilm 211
        ComptaPropsConfiguration.checkJava();
156 ilm 212
        // Check MacOS Sandbox
213
        String cwd = new File(getProperty("user.dir")).toURI().toString();
214
        if (cwd.startsWith("file:/private/var/folders")) {
215
            JOptionPane.showMessageDialog(null,
216
                    "Vous éxecutez OpenConcerto depuis la sandbox de MacOS.\nVous devez déplacer le logiciel dans votre dossier Application.\n\nSi cela ne fonctionne pas, vous pouvez utiliser la commande : \nsudo xattr -r -d com.apple.quarantine /Applications/OpenConcerto",
217
                    "Sandbox", JOptionPane.ERROR_MESSAGE);
218
            return;
219
        }
220
 
28 ilm 221
        Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
222
 
223
            @Override
224
            public void uncaughtException(Thread t, Throwable e) {
142 ilm 225
                e.printStackTrace();
28 ilm 226
                ExceptionHandler.handle("UncaughtException on thread " + t, e);
227
            }
228
        });
94 ilm 229
        System.out.println("Java version: " + System.getProperty("java.vendor", "??") + " - " + System.getProperty("java.version", "??"));
230
        System.out.println("Runtime: Java " + System.getProperty("java.runtime.version", "??") + " - " + System.getProperty("os.name", "??"));
18 ilm 231
        ExceptionHandler.setForceUI(true);
232
        ExceptionHandler.setForumURL("http://www.openconcerto.org/forum");
156 ilm 233
 
83 ilm 234
        ExceptionHandler.setSoftwareInformations(SoftwareInfoPanel.FACTORY);
132 ilm 235
        ExceptionHandler.setShowProbably(true);
144 ilm 236
        ExceptionHandler.setThrowableHandler(createDefaultThrowableHandler());
237
 
156 ilm 238
        // Guillaume : handle people importing data directly into the DB
239
        ReOrder.setAutoFixNulls(true);
240
 
142 ilm 241
        System.setProperty(SQLRowAccessor.ACCESS_DB_IF_NEEDED_PROP, "true");
28 ilm 242
        System.setProperty(PropsConfiguration.REDIRECT_TO_FILE, "true");
18 ilm 243
        // Mac
244
        // only works with Aqua laf
245
        System.setProperty("apple.laf.useScreenMenuBar", "true");
246
 
41 ilm 247
        // ToolTipManager.sharedInstance().setInitialDelay(0);
18 ilm 248
        // SpeedUp Linux
249
        System.setProperty("sun.java2d.pmoffscreen", "false");
250
 
80 ilm 251
        System.setProperty(EditPanel.NOBORDER, "true");
252
        System.setProperty(EditPanel.ADD_AT_THE_END, "true");
18 ilm 253
        System.setProperty("org.openconcerto.sql.listPanel.deafEditPanel", "true");
93 ilm 254
 
156 ilm 255
        // needed as long as IListFrame title isn't localised
256
        System.setProperty(IListFrame.SHORT_TITLE, "true");
257
 
93 ilm 258
        // Gérer avec le droit SAVE_LIST
259
        System.setProperty("org.openconcerto.sql.canSaveInList", "false");
260
 
18 ilm 261
        System.setProperty("org.openconcerto.ui.addComboButton", "true");
65 ilm 262
        System.setProperty(SQLBase.STRUCTURE_USE_XML, "true");
18 ilm 263
        // don't put any suffix, rely on Animator
264
        System.setProperty(UISQLComponent.REQUIRED_SUFFIX_PROP, "");
265
        System.setProperty(ElementComboBox.CAN_MODIFY, "true");
41 ilm 266
 
18 ilm 267
        System.setProperty("org.openconcerto.ui.removeSwapSearchCheckBox", "true");
19 ilm 268
 
269
        if (System.getProperty("org.openconcerto.oo.useODSViewer") == null) {
18 ilm 270
            System.setProperty("org.openconcerto.oo.useODSViewer", "true");
271
        }
73 ilm 272
        // Workaround for JRE 7 bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7075600
273
        System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
61 ilm 274
 
80 ilm 275
        System.setProperty(ITextCombo.SIMPLE_TRAVERSAL, "true");
276
 
142 ilm 277
        // Disable FOR SHARE lock
278
        BaseFillSQLRequest.setDefaultLockSelect(false);
279
 
80 ilm 280
        ComboSQLRequest.setDefaultItemsOrder(CompareUtils.<IComboSelectionItem> naturalOrder());
18 ilm 281
        // Initialisation du splashScreen
282
        // ne pas oublier en param -splash:image.png
142 ilm 283
        try {
284
            SplashScreen.getSplashScreen();
285
        } catch (Exception e) {
286
            // Can occur on OpenJDK...
287
            System.out.println("SplashScreen failed... " + e.getMessage());
288
        }
18 ilm 289
 
132 ilm 290
        // must be done before creating UserRightsManager (which is done by
291
        // PropsConfiguration.getRoot())
292
        UserRightsManager.DEFAULT_MACRO_RIGHTS.add(new ComptaTotalUserRight());
293
 
18 ilm 294
        // Init des caches
295
        long t1 = System.currentTimeMillis();
296
        final ComptaPropsConfiguration conf = ComptaPropsConfiguration.create(true);
41 ilm 297
 
18 ilm 298
        if (conf == null) {
142 ilm 299
            System.out.println("Unable to create configuration, launching ServerFinderPanel");
18 ilm 300
            ServerFinderPanel.main(new String[0]);
301
            return;
302
        }
142 ilm 303
        // Dump conf directories
304
        try {
305
            System.out.println("Application data folder : " + conf.getBaseDirs().getAppDataFolder().getCanonicalPath());
306
            System.out.println("Application cache folder : " + conf.getBaseDirs().getCacheFolder().getCanonicalPath());
307
            System.out.println("Application preferences folder : " + conf.getBaseDirs().getPreferencesFolder().getCanonicalPath());
308
        } catch (IOException ex2) {
309
            ex2.printStackTrace();
310
        }
311
        System.out.println("Application working directory folder : " + conf.getWD().getAbsolutePath());
18 ilm 312
        if (inWebStart()) {
313
            // needed since our classes aren't loaded by the same loader as the library classes
314
            Helper.setURLStreamHandlerFactory();
315
            // even if we set <all-permissions/> in the jnlp, this only applies to the main jar, not
316
            // to dynamically loaded jars. So to allow OOConnexion to work we need to remove the
317
            // security manager.
318
            System.setSecurityManager(null);
319
        }
320
        Configuration.setInstance(conf);
156 ilm 321
 
322
        ExceptionHandler.setSafeToExit(!conf.getServerIp().contains("file:"));
142 ilm 323
        try {
324
            Configuration.migrateToNewDir(conf.getOldDataDir(), conf.getDataDir());
325
        } catch (IOException ex) {
326
            throw new IllegalStateException("Couldn't migrate data dir", ex);
327
        }
61 ilm 328
 
329
        final boolean logRequests = Boolean.valueOf(conf.getProperty("logRequests", "false"));
330
 
331
        if (logRequests) {
332
            SQLRequestLog.setEnabled(true);
333
        }
334
 
41 ilm 335
        if (Boolean.valueOf(conf.getProperty("minimal", "false"))) {
336
            System.setProperty(MINIMAL_PROP, Boolean.TRUE.toString());
337
        }
65 ilm 338
        if (Boolean.valueOf(conf.getProperty("statelessTable", "false"))) {
339
            System.setProperty(IListe.STATELESS_TABLE_PROP, Boolean.TRUE.toString());
340
        }
341
 
80 ilm 342
        System.setProperty("org.openconcerto.oo.useODSViewer", Boolean.TRUE.toString());
41 ilm 343
        if (conf.getProperty("odsViewer") != null) {
344
            System.setProperty("org.openconcerto.oo.useODSViewer", Boolean.valueOf(conf.getProperty("odsViewer")).toString());
345
        }
346
 
149 ilm 347
        if (conf.getProperty("rwOnDoubleClick") != null) {
348
            System.setProperty("org.openconcerto.sql.listPanel.rwOnDoubleClick", Boolean.valueOf(conf.getProperty("rwOnDoubleClick")).toString());
349
        }
83 ilm 350
 
149 ilm 351
 
132 ilm 352
        RemoteShell.startDefaultInstance(conf.getDirectory(), conf.getRoot());
353
 
41 ilm 354
        // Restore L&F and colors
355
        UIPreferencePanel.initUIFromPreferences();
356
 
357
        UpdateManager.start();
358
 
359
        Toolkit.getDefaultToolkit().setDynamicLayout(true);
360
 
361
        ComboSQLRequest.setDefaultFieldSeparator(" ");
362
 
18 ilm 363
        long t4 = System.currentTimeMillis();
364
        System.out.println("Ip:" + conf.getServerIp());
365
        if (conf.getServerIp().startsWith("127.0.0.1:6543")) {
366
            File f = new File("PostgreSQL/data/postmaster.pid");
367
            if (!f.exists()) {
368
                startDB(conf);
369
            }
370
        }
371
        try {
73 ilm 372
            // test DB connection
373
            conf.getSystemRoot();
67 ilm 374
            // Prefetch undefined
375
            conf.getRoot().getTables().iterator().next().getUndefinedID();
18 ilm 376
        } catch (Exception e) {
377
            System.out.println("Init phase 1 error:" + (System.currentTimeMillis() - t4) + "ms");
80 ilm 378
            if (conf.getSystem() == SQLSystem.H2 && e.getCause() instanceof SQLException) {
379
                final SQLException sqlExn = (SQLException) e.getCause();
380
                final String msg;
381
                if (sqlExn.getErrorCode() == 90020) {
382
                    msg = "Base de donnée déjà ouverte.";
383
                } else if (sqlExn.getSQLState().equals("08000")) {
384
                    msg = "Impossible d'ouvrir la base de donnée. Vérifier les permissions.\n" + conf.getServerIp();
385
                } else {
386
                    msg = null;
387
                }
388
                if (msg != null) {
389
                    try {
390
                        e.printStackTrace();
391
                        SwingUtilities.invokeAndWait(new Runnable() {
392
                            @Override
393
                            public void run() {
394
                                JOptionPane.showMessageDialog(null, msg, "Erreur fatale", JOptionPane.ERROR_MESSAGE);
395
                            }
396
                        });
397
                    } catch (Exception e1) {
398
                        ExceptionHandler.die("Erreur fatale", e1);
399
                    }
400
                    System.exit(1);
401
                }
402
            }
18 ilm 403
            ExceptionHandler.die("Erreur de connexion à la base de données", e);
404
        }
405
        System.out.println("Init phase 1:" + (System.currentTimeMillis() - t1) + "ms");
41 ilm 406
 
156 ilm 407
        // Counter and user agreement
408
        File fTOS = new File(Configuration.getInstance().getConfDir(), "tos.properties");
409
        Properties pTOS = new Properties();
410
        pTOS.setProperty("launchCounter", "1");
411
        pTOS.setProperty("allowDebug", "false");
412
        pTOS.setProperty("hasManual", "false");
413
        pTOS.setProperty("hasCloud", "false");
414
 
415
        if (fTOS.exists()) {
416
            try {
174 ilm 417
                FastXMLProperties.load(pTOS, new FileInputStream(fTOS));
156 ilm 418
            } catch (Exception e1) {
419
                e1.printStackTrace();
420
            }
421
        }
422
        if (ComptaPropsConfiguration.getInstanceCompta().isOnCloud()) {
423
            pTOS.setProperty("hasCloud", "true");
424
        }
425
        final boolean allowDebug = pTOS.getProperty("allowDebug", "false").equals("true");
426
 
427
        ExceptionHandler.setSubmitErrorAutoEnabled(allowDebug);
428
 
429
        final int launchCounter = Integer.parseInt(pTOS.getProperty("launchCounter", "0"));
430
        pTOS.setProperty("launchCounter", String.valueOf(launchCounter + 1));
431
        saveProperties(fTOS, pTOS);
432
        if (!allowDebug && (launchCounter - 2) % 30 == 0) {
433
            SwingUtilities.invokeLater(new Runnable() {
434
                public void run() {
435
                    Object[] options = { "J'accepte", "Non, merci" };
436
                    int n = JOptionPane.showOptionDialog(null,
437
                            "Afin d'améliorer plus rapidement le logiciel, nous avons intégré l'envoi automatique de rapports d'erreur.\nIl contient les informations techniques nécessaires à la corrections de bugs.\nSouhaitez-vous activer l'envoi automatique ?",
438
                            "Rapport d'erreur", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
439
                    if (n == JOptionPane.YES_OPTION) {
440
                        pTOS.setProperty("allowDebug", "true");
441
                        saveProperties(fTOS, pTOS);
442
                        ExceptionHandler.setSubmitErrorAutoEnabled(true);
443
                    }
444
 
445
                }
446
            });
447
        }
448
        final boolean hasManual = pTOS.getProperty("hasManual", "false").equals("true");
449
        if (!hasManual && (launchCounter - 5) % 100 == 0) {
450
            SwingUtilities.invokeLater(new Runnable() {
451
                public void run() {
452
                    Object[] options = { "Je l'ai déjà", "Bonne idée!" };
453
                    int n = JOptionPane.showOptionDialog(null,
454
                            "Afin de maîtriser le logiciel, nous conseillons vivement l'acquisition du manuel.\nSon achat vous permet de soutenir les développements d'OpenConcerto et d'avoir une documentation papier de plus de 250 pages.\nVous pouvez le commmander avec port gratuit depuis le site internet : https://www.openconcerto.org ",
455
                            "Le manuel utilisateur", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[1]);
456
                    if (n == JOptionPane.YES_OPTION) {
457
                        pTOS.setProperty("hasManual", "true");
458
                        saveProperties(fTOS, pTOS);
459
                    } else {
460
                        try {
461
                            Desktop.getDesktop().browse(new URI("https://www.openconcerto.org/fr/documentation.html"));
462
                        } catch (Exception e) {
463
                            e.printStackTrace();
464
                        }
465
                    }
466
                }
467
            });
468
        }
469
        final boolean hasCloud = pTOS.getProperty("hasCloud", "false").equals("true");
470
        if (!hasCloud && (launchCounter - 30) % 100 == 0 && ComptaPropsConfiguration.getInstanceCompta().isServerless()) {
471
            SwingUtilities.invokeLater(new Runnable() {
472
                public void run() {
473
                    JOptionPane.showMessageDialog(null,
474
                            "Vous utilisez actuellement le logiciel en version monoposte.\nLes données sont stockées sur votre ordinateur, ce qui peut poser problème en cas de vol ou de panne.\nNous proposons une offre cloud qui vous permet de travailler à plusieurs et de ne plus avoir à vous soucier de la sauvegarde de vos données.\nVous aurez juste besoin d'une connexion internet.\nPlus d'informations sur https://cloud.openconcerto.org",
475
                            "Cloud", JOptionPane.INFORMATION_MESSAGE);
476
                    try {
477
                        Desktop.getDesktop().browse(new URI("https://cloud.openconcerto.org"));
478
                    } catch (Exception e) {
479
                        e.printStackTrace();
480
                    }
481
 
482
                }
483
            });
484
        }
485
 
41 ilm 486
        // Email props in .java
487
        File fMail2 = new File(Configuration.getInstance().getConfDir(), "Email.properties");
156 ilm 488
        EmailProps.getInstance().setDefaultPropsFileName(fMail2.toString());
41 ilm 489
        EmailProps.getInstance().setPropsFileName(fMail2.toString());
490
 
18 ilm 491
        SwingUtilities.invokeLater(new Runnable() {
492
 
493
            public void run() {
494
                long t1 = System.currentTimeMillis();
495
 
93 ilm 496
                IListe.setForceAlternateCellRenderer(true);
497
 
18 ilm 498
                AWTEventListener awtListener = new AWTEventListener() {
151 ilm 499
                    Set<Integer> frames = new HashSet<Integer>();
500
                    String prefix;
501
 
18 ilm 502
                    @Override
503
                    public final void eventDispatched(final AWTEvent event) {
504
                        assert event != null;
505
                        if (event instanceof HierarchyEvent && event.getID() == HierarchyEvent.HIERARCHY_CHANGED) {
506
                            // This event represents a change in the containment hierarcy.
507
                            // Now let's figure out what kind.
508
                            final HierarchyEvent hevent = (HierarchyEvent) event;
509
                            final Component changed = hevent.getChanged();
510
                            if (changed instanceof JFrame && ((hevent.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) && changed.isDisplayable()) {
151 ilm 511
                                final JFrame frame = (JFrame) changed;
18 ilm 512
                                frame.setIconImages(getFrameIcon());
151 ilm 513
                                if (!frames.contains(frame.hashCode())) {
514
                                    frames.add(frame.hashCode());
515
                                    frame.addPropertyChangeListener(new PropertyChangeListener() {
516
 
517
                                        @Override
518
                                        public void propertyChange(PropertyChangeEvent evt) {
519
                                            if (prefix == null) {
520
                                                if (ComptaPropsConfiguration.getInstance() != null && ComptaPropsConfiguration.getInstanceCompta().getRowSociete() != null) {
521
                                                    prefix = "[" + ComptaPropsConfiguration.getInstanceCompta().getRowSociete().getString("NOM") + "] ";
522
                                                } else {
523
                                                    return;
524
                                                }
525
                                            }
526
                                            String title = frame.getTitle();
527
                                            if (title != null && !title.startsWith(prefix)) {
528
                                                frame.setTitle(prefix + title);
529
                                            }
530
                                        }
531
                                    });
532
                                }
18 ilm 533
                            }
534
                        }
535
                    }
536
                };
537
                final Toolkit toolkit = Toolkit.getDefaultToolkit();
538
                assert toolkit != null;
539
                toolkit.addAWTEventListener(awtListener, AWTEvent.HIERARCHY_EVENT_MASK);
540
                if (logRequests) {
541
                    SQLRequestLog.showFrame();
542
                }
543
 
544
                JFrame f = null;
545
                try {
156 ilm 546
                    f = new NouvelleConnexionAction(conf).createFrame();
18 ilm 547
                    // happens with quick login
548
                    if (f != null) {
549
                        f.pack();
550
                        f.setResizable(false);
551
                        f.addWindowListener(new WindowAdapter() {
552
                            public void windowClosing(WindowEvent e) {
144 ilm 553
                                try {
554
                                    askForExit();
555
                                } catch (Exception ex) {
556
                                    ex.printStackTrace();
557
                                    // Broken state
558
                                    System.exit(2);
559
                                }
18 ilm 560
                            };
561
                        });
562
                        // f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
563
                    }
564
                } catch (Exception e) {
565
                    Thread.dumpStack();
566
                    e.printStackTrace();
567
                    ExceptionHandler.handle("Erreur lors de la tentative de connexion à la base.", e);
568
 
569
                } finally {
570
                    if (f != null) {
571
                        FrameUtil.show(f);
572
                    }
573
                    System.out.println("Init phase 2:" + (System.currentTimeMillis() - t1) + "ms");
574
                }
575
            }
576
        });
19 ilm 577
 
578
        // needed so that we can uninstall modules
579
        System.setProperty(SQLBase.ALLOW_OBJECT_REMOVAL, "true");
156 ilm 580
    }
581
 
582
    private static void saveProperties(File fTOS, Properties pTOS) {
25 ilm 583
        try {
156 ilm 584
            final FileOutputStream outputStream = new FileOutputStream(fTOS);
174 ilm 585
            FastXMLProperties.store(pTOS, outputStream, "tos");
156 ilm 586
            outputStream.close();
587
        } catch (Exception e) {
588
            e.printStackTrace();
25 ilm 589
        }
18 ilm 590
    }
591
 
144 ilm 592
    public static ThrowableHandler createDefaultThrowableHandler() {
593
 
594
        return new ThrowableHandler() {
595
 
596
            @Override
597
            public boolean handle(String message, Throwable throwable) {
598
                if (throwable == null)
599
                    return false;
174 ilm 600
                throwable.printStackTrace();
144 ilm 601
                final ByteArrayOutputStream out = new ByteArrayOutputStream();
602
                throwable.printStackTrace(new PrintStream(out));
603
                String s = new String(out.toByteArray());
604
                if (s.contains("Database may be already in use")) {
605
                    JOptionPane.showMessageDialog(null,
606
                            "Votre base de données est déjà en cours d'utilisation.\nEn version monoposte, vous ne pouvez lancer qu'un seul programme OpenConcerto à la fois.");
607
                    System.exit(1);
608
                    return true;
609
                } else if (s.contains("PSQLException: Connexion") && ComptaPropsConfiguration.getInstanceCompta().isOnCloud()) {
610
                    JOptionPane.showMessageDialog(null, "Suite à une coupure de votre connexion internet, vous avez été déconnecté du Cloud.\nMerci de redémarrer le logiciel.");
611
                    System.exit(1);
612
                    return true;
613
                } else if (s.contains("File corrupted while reading")) {
614
                    JOptionPane.showMessageDialog(null,
615
                            "Votre fichier de base de données est endommagé.\nLes causes possibles sont variées : problème matériel (mémoire, disque dur...), coupure brutale du PC, virus, antivirus, erreur de fichiers...\n\nIl vous faudra restaurer votre base de données depuis une sauvegarde\nou contacter notre service technique pour réparation (voir https://www.openconcerto.org).");
616
                    System.exit(1);
617
                    return true;
156 ilm 618
                } else if (s.contains("h2") && (s.contains("File corrupted while reading") || s.contains("data leaf table"))) {
144 ilm 619
                    JOptionPane.showMessageDialog(null,
620
                            "Votre fichier de base de données est endommagé.\nLes causes possibles sont variées : problème matériel (mémoire, disque dur...), coupure brutale du PC, virus, antivirus, erreur de fichiers...\n\nIl vous faudra restaurer votre base de données depuis une sauvegarde\nou contacter notre service technique pour réparation (voir https://www.openconcerto.org).");
621
                    System.exit(1);
622
                    return true;
623
                } else if (s.contains("/private/var/folders/")) {
624
                    JOptionPane.showMessageDialog(null,
625
                            "Votre installation d'OpenConcerto n'est pas correcte!\nOpenConcerto ne doit pas s'executer dans l'app Sandbox de MacOS.\nVeuillez débloquer l'application.");
626
                    System.exit(1);
627
                    return true;
628
                } else if (s.contains("com.sun.java.swing.plaf.windows.WindowsTableHeaderUI")) {
629
                    // bug connu de Java sur les TableHeader
630
                    return true;
156 ilm 631
                } else if (s.contains("WInputMethod.openCandidateWindow") && s.contains("java.lang.NullPointerException: peer")) {
632
                    // bug windows...
633
                    // Caused by: java.lang.NullPointerException: peer
634
                    // at sun.awt.windows.WInputMethod.openCandidateWindow(Native Method)
635
                    // at sun.awt.windows.WInputMethod.access$400(Unknown Source)
636
                    // at sun.awt.windows.WInputMethod$1.run(Unknown Source)
637
                    // at java.awt.event.InvocationEvent.dispatch(Unknown Source)
638
                    return true;
144 ilm 639
                }
156 ilm 640
 
174 ilm 641
                else if (s.contains("No application is associated with the specified file for this operation") || s.contains("Error message: Package could not be registered")) {
156 ilm 642
                    JOptionPane.showMessageDialog(null, "Merci d'installer LibreOffice ou tout autre application succeptible d'ouvrir ce fichier");
643
                    return true;
644
                } else if (s.contains("java.net.SocketTimeoutException: connect timed out")) {
645
                    JOptionPane.showMessageDialog(null, "Le serveur de base de données n'est pas joignable.\n" + message);
646
                    return true;
647
                } else if (s.contains("java.lang.NoSuchMethodError")) {
648
                    JOptionPane.showMessageDialog(null, "Un de vos modules n'est pas à jour.\n" + message);
649
                    return true;
650
                } else if (s.contains("InvalidTemplateException")) {
651
                    JOptionPane.showMessageDialog(null, "Votre modèle de document n'est pas valide.\n" + message, "Modèle incorrect", JOptionPane.ERROR_MESSAGE);
652
                    return true;
653
                }
144 ilm 654
                return false;
655
            }
656
        };
657
    }
658
 
18 ilm 659
    /**
660
     * Si la base est 127.0.0.1 ou localhost alors on essaye de lancer postgres.
661
     *
662
     * @param conf the configuration to connect to.
663
     */
664
    private static void startDB(PropsConfiguration conf) {
665
 
666
        List<String> l = new ArrayList<String>();
667
        l.add("Lancement de la base de données");
668
        PostgreSQLFrame pgFrame = null;
669
        try {
670
            pgFrame = new PostgreSQLFrame("Démarrage en cours");
671
            pgFrame.setVisible(true);
672
        } catch (Exception e) {
673
            e.printStackTrace();
674
        }
675
        System.err.println("start DB");
676
        final WaitIndeterminatePanel panel = new WaitIndeterminatePanel(l);
677
        final PanelFrame f = new PanelFrame(panel, "Gestion NX");
678
        f.setResizable(false);
679
        f.setLocationRelativeTo(null);
680
        f.setVisible(true);
681
 
682
        // on recupere les properties
683
        final String serverAdr = conf.getProperty("server.ip");
684
        // si la base est en local on relance postgres
685
        if (serverAdr.startsWith("127.0.0.1") || serverAdr.startsWith("localhost")) {
686
 
687
            Runtime runtime = Runtime.getRuntime();
688
            try {
689
                File file = new File(".\\PostgreSQL\\bin\\");
690
                if (!file.canWrite()) {
691
                    ExceptionHandler.die("Vous n'avez pas le droit en écriture sur la base de données.\nImpossible de lancer le logiciel!");
692
                }
693
                final Process p = runtime.exec(new String[] { "cmd.exe", "/C", "launchPostGres.bat" }, null, file);
694
                // Consommation de la sortie standard de l'application externe dans un Thread
695
                // separe
696
                new Thread() {
697
                    public void run() {
698
                        try {
699
                            BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
700
                            String line = "";
701
                            try {
702
                                while ((line = reader.readLine()) != null) {
703
                                    System.out.println(line);
704
                                }
705
                            } finally {
706
                                reader.close();
707
                            }
708
                        } catch (IOException ioe) {
709
                            ioe.printStackTrace();
710
                        }
711
                    }
712
                }.start();
713
 
714
                // Consommation de la sortie d'erreur de l'application externe dans un Thread
715
                // separe
716
                new Thread() {
717
                    public void run() {
718
                        try {
719
                            BufferedReader reader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
720
                            String line = "";
721
                            try {
722
                                while ((line = reader.readLine()) != null) {
723
                                    System.err.println(line);
724
                                }
725
                            } finally {
726
                                reader.close();
727
                            }
728
                        } catch (IOException ioe) {
729
                            ioe.printStackTrace();
730
                        }
731
                    }
732
                }.start();
733
                try {
734
                    p.waitFor();
735
                } catch (InterruptedException e2) {
736
                    e2.printStackTrace();
737
                }
738
            } catch (IOException e1) {
739
                e1.printStackTrace();
740
            }
741
        } else {
742
            System.err.println("L'adresse du serveur n'est pas en local (" + serverAdr + ").");
743
        }
744
 
745
        panel.taskEnded(0);
746
        if (pgFrame != null) {
747
            pgFrame.dispose();
748
        }
749
        f.dispose();
750
        String realIp = "127.0.0.1";
751
        realIp = getIp();
752
        try {
753
            pgFrameStart = new PostgreSQLFrame(realIp + " port " + "6543");
754
            pgFrameStart.setVisible(true);
755
        } catch (Exception e) {
756
            e.printStackTrace();
757
        }
758
 
759
    }
760
 
761
    private static String getIp() {
762
        String realIp = "127.0.0.1";
763
        try {
764
            InetAddress Ip = InetAddress.getLocalHost();
765
            realIp = Ip.getHostAddress();
766
        } catch (Exception e) {
767
            e.printStackTrace();
768
        }
769
        try {
67 ilm 770
            Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
18 ilm 771
            while (e.hasMoreElements()) {
772
                NetworkInterface ni = (NetworkInterface) e.nextElement();
67 ilm 773
                Enumeration<InetAddress> e2 = ni.getInetAddresses();
18 ilm 774
                while (e2.hasMoreElements()) {
775
                    InetAddress ip = (InetAddress) e2.nextElement();
776
                    final String iip = ip.toString().replace('/', ' ').trim();
777
                    if (iip.startsWith("192")) {
778
                        return iip;
779
                    }
780
                }
781
            }
782
        } catch (Exception e) {
783
            e.printStackTrace();
784
        }
785
        return realIp;
786
    }
787
 
788
    public static PostgreSQLFrame pgFrameStart = null;
789
 
790
    private static JDialog frameExit = null;
791
 
80 ilm 792
    static public void askForExit() {
793
        askForExit(UserExitConf.DEFAULT);
794
    }
795
 
796
    static public void askForExit(UserExitConf conf) {
18 ilm 797
        JDialog exitDialog = new JDialog();
798
        exitDialog.setModal(true);
799
 
800
        if (frameExit == null) {
801
            frameExit = new JDialog();
802
            frameExit.setTitle("Quitter");
803
            frameExit.setModal(true);
804
            frameExit.setIconImages(Gestion.getFrameIcon());
805
            frameExit.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
806
        }
807
 
80 ilm 808
        frameExit.setContentPane(new UserExitPanel(conf));
18 ilm 809
        frameExit.pack();
810
        frameExit.setResizable(false);
811
        frameExit.setLocationRelativeTo(null);
812
        frameExit.setAlwaysOnTop(true);
813
        frameExit.setVisible(true);
814
    }
815
 
93 ilm 816
    public static synchronized List<Image> getFrameIcon() {
18 ilm 817
        if (frameIcon == null) {
818
            frameIcon = new ArrayList<Image>();
819
            int[] sizes = { 16, 32, 48, 96 };
820
            for (int i = 0; i < sizes.length; i++) {
821
                int v = sizes[i];
822
                try {
823
                    frameIcon.add(new ImageIcon(Gestion.class.getResource(v + ".png")).getImage());
824
                } catch (Exception e) {
825
                    ExceptionHandler.die("Impossible de charger l'icone de fenetre " + v + ".png");
826
                }
827
            }
828
        }
829
        return frameIcon;
830
    }
831
}