OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 174 | 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;
177 ilm 53
import org.openconcerto.utils.i18n.TranslationManager;
18 ilm 54
import org.openconcerto.utils.protocol.Helper;
174 ilm 55
import org.openconcerto.xml.FastXMLProperties;
18 ilm 56
 
57
import java.awt.AWTEvent;
58
import java.awt.Component;
156 ilm 59
import java.awt.Desktop;
18 ilm 60
import java.awt.Image;
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);
177 ilm 248
        if (false) {
249
            // TODO : regarder si ne pas le forcer fix le bug de carré noir
250
            // SpeedUp Linux
251
            System.setProperty("sun.java2d.pmoffscreen", "false");
18 ilm 252
 
177 ilm 253
        }
80 ilm 254
        System.setProperty(EditPanel.NOBORDER, "true");
255
        System.setProperty(EditPanel.ADD_AT_THE_END, "true");
18 ilm 256
        System.setProperty("org.openconcerto.sql.listPanel.deafEditPanel", "true");
93 ilm 257
 
156 ilm 258
        // needed as long as IListFrame title isn't localised
259
        System.setProperty(IListFrame.SHORT_TITLE, "true");
260
 
93 ilm 261
        // Gérer avec le droit SAVE_LIST
262
        System.setProperty("org.openconcerto.sql.canSaveInList", "false");
263
 
18 ilm 264
        System.setProperty("org.openconcerto.ui.addComboButton", "true");
65 ilm 265
        System.setProperty(SQLBase.STRUCTURE_USE_XML, "true");
18 ilm 266
        // don't put any suffix, rely on Animator
267
        System.setProperty(UISQLComponent.REQUIRED_SUFFIX_PROP, "");
268
        System.setProperty(ElementComboBox.CAN_MODIFY, "true");
41 ilm 269
 
18 ilm 270
        System.setProperty("org.openconcerto.ui.removeSwapSearchCheckBox", "true");
19 ilm 271
 
272
        if (System.getProperty("org.openconcerto.oo.useODSViewer") == null) {
18 ilm 273
            System.setProperty("org.openconcerto.oo.useODSViewer", "true");
274
        }
73 ilm 275
        // Workaround for JRE 7 bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7075600
276
        System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
61 ilm 277
 
80 ilm 278
        System.setProperty(ITextCombo.SIMPLE_TRAVERSAL, "true");
279
 
177 ilm 280
        // Must be called before createDefaultInstance()
281
        TranslationManager.addTranslationStreamFromClass(Gestion.class);
282
 
142 ilm 283
        // Disable FOR SHARE lock
284
        BaseFillSQLRequest.setDefaultLockSelect(false);
285
 
80 ilm 286
        ComboSQLRequest.setDefaultItemsOrder(CompareUtils.<IComboSelectionItem> naturalOrder());
18 ilm 287
        // Initialisation du splashScreen
288
        // ne pas oublier en param -splash:image.png
142 ilm 289
        try {
177 ilm 290
            // Ne fonctionne pas sur certains Linux
291
            java.awt.SplashScreen.getSplashScreen();
292
        } catch (Throwable e) {
142 ilm 293
            // Can occur on OpenJDK...
294
            System.out.println("SplashScreen failed... " + e.getMessage());
295
        }
18 ilm 296
 
132 ilm 297
        // must be done before creating UserRightsManager (which is done by
298
        // PropsConfiguration.getRoot())
299
        UserRightsManager.DEFAULT_MACRO_RIGHTS.add(new ComptaTotalUserRight());
300
 
18 ilm 301
        // Init des caches
302
        long t1 = System.currentTimeMillis();
303
        final ComptaPropsConfiguration conf = ComptaPropsConfiguration.create(true);
41 ilm 304
 
18 ilm 305
        if (conf == null) {
142 ilm 306
            System.out.println("Unable to create configuration, launching ServerFinderPanel");
18 ilm 307
            ServerFinderPanel.main(new String[0]);
308
            return;
309
        }
142 ilm 310
        // Dump conf directories
311
        try {
312
            System.out.println("Application data folder : " + conf.getBaseDirs().getAppDataFolder().getCanonicalPath());
313
            System.out.println("Application cache folder : " + conf.getBaseDirs().getCacheFolder().getCanonicalPath());
314
            System.out.println("Application preferences folder : " + conf.getBaseDirs().getPreferencesFolder().getCanonicalPath());
315
        } catch (IOException ex2) {
316
            ex2.printStackTrace();
317
        }
318
        System.out.println("Application working directory folder : " + conf.getWD().getAbsolutePath());
18 ilm 319
        if (inWebStart()) {
320
            // needed since our classes aren't loaded by the same loader as the library classes
321
            Helper.setURLStreamHandlerFactory();
322
            // even if we set <all-permissions/> in the jnlp, this only applies to the main jar, not
323
            // to dynamically loaded jars. So to allow OOConnexion to work we need to remove the
324
            // security manager.
325
            System.setSecurityManager(null);
326
        }
327
        Configuration.setInstance(conf);
156 ilm 328
 
329
        ExceptionHandler.setSafeToExit(!conf.getServerIp().contains("file:"));
142 ilm 330
        try {
331
            Configuration.migrateToNewDir(conf.getOldDataDir(), conf.getDataDir());
332
        } catch (IOException ex) {
333
            throw new IllegalStateException("Couldn't migrate data dir", ex);
334
        }
61 ilm 335
 
336
        final boolean logRequests = Boolean.valueOf(conf.getProperty("logRequests", "false"));
337
 
338
        if (logRequests) {
339
            SQLRequestLog.setEnabled(true);
340
        }
341
 
41 ilm 342
        if (Boolean.valueOf(conf.getProperty("minimal", "false"))) {
343
            System.setProperty(MINIMAL_PROP, Boolean.TRUE.toString());
344
        }
65 ilm 345
        if (Boolean.valueOf(conf.getProperty("statelessTable", "false"))) {
346
            System.setProperty(IListe.STATELESS_TABLE_PROP, Boolean.TRUE.toString());
347
        }
348
 
80 ilm 349
        System.setProperty("org.openconcerto.oo.useODSViewer", Boolean.TRUE.toString());
41 ilm 350
        if (conf.getProperty("odsViewer") != null) {
351
            System.setProperty("org.openconcerto.oo.useODSViewer", Boolean.valueOf(conf.getProperty("odsViewer")).toString());
352
        }
353
 
149 ilm 354
        if (conf.getProperty("rwOnDoubleClick") != null) {
355
            System.setProperty("org.openconcerto.sql.listPanel.rwOnDoubleClick", Boolean.valueOf(conf.getProperty("rwOnDoubleClick")).toString());
356
        }
83 ilm 357
 
149 ilm 358
 
132 ilm 359
        RemoteShell.startDefaultInstance(conf.getDirectory(), conf.getRoot());
360
 
41 ilm 361
        // Restore L&F and colors
362
        UIPreferencePanel.initUIFromPreferences();
363
 
364
        UpdateManager.start();
365
 
366
        Toolkit.getDefaultToolkit().setDynamicLayout(true);
367
 
368
        ComboSQLRequest.setDefaultFieldSeparator(" ");
369
 
18 ilm 370
        long t4 = System.currentTimeMillis();
371
        System.out.println("Ip:" + conf.getServerIp());
372
        if (conf.getServerIp().startsWith("127.0.0.1:6543")) {
373
            File f = new File("PostgreSQL/data/postmaster.pid");
374
            if (!f.exists()) {
375
                startDB(conf);
376
            }
377
        }
378
        try {
73 ilm 379
            // test DB connection
380
            conf.getSystemRoot();
67 ilm 381
            // Prefetch undefined
382
            conf.getRoot().getTables().iterator().next().getUndefinedID();
18 ilm 383
        } catch (Exception e) {
384
            System.out.println("Init phase 1 error:" + (System.currentTimeMillis() - t4) + "ms");
80 ilm 385
            if (conf.getSystem() == SQLSystem.H2 && e.getCause() instanceof SQLException) {
386
                final SQLException sqlExn = (SQLException) e.getCause();
387
                final String msg;
388
                if (sqlExn.getErrorCode() == 90020) {
389
                    msg = "Base de donnée déjà ouverte.";
390
                } else if (sqlExn.getSQLState().equals("08000")) {
391
                    msg = "Impossible d'ouvrir la base de donnée. Vérifier les permissions.\n" + conf.getServerIp();
392
                } else {
393
                    msg = null;
394
                }
395
                if (msg != null) {
396
                    try {
397
                        e.printStackTrace();
398
                        SwingUtilities.invokeAndWait(new Runnable() {
399
                            @Override
400
                            public void run() {
401
                                JOptionPane.showMessageDialog(null, msg, "Erreur fatale", JOptionPane.ERROR_MESSAGE);
402
                            }
403
                        });
404
                    } catch (Exception e1) {
405
                        ExceptionHandler.die("Erreur fatale", e1);
406
                    }
407
                    System.exit(1);
408
                }
409
            }
18 ilm 410
            ExceptionHandler.die("Erreur de connexion à la base de données", e);
411
        }
412
        System.out.println("Init phase 1:" + (System.currentTimeMillis() - t1) + "ms");
41 ilm 413
 
156 ilm 414
        // Counter and user agreement
415
        File fTOS = new File(Configuration.getInstance().getConfDir(), "tos.properties");
416
        Properties pTOS = new Properties();
417
        pTOS.setProperty("launchCounter", "1");
418
        pTOS.setProperty("allowDebug", "false");
419
        pTOS.setProperty("hasManual", "false");
420
        pTOS.setProperty("hasCloud", "false");
421
 
422
        if (fTOS.exists()) {
423
            try {
174 ilm 424
                FastXMLProperties.load(pTOS, new FileInputStream(fTOS));
156 ilm 425
            } catch (Exception e1) {
426
                e1.printStackTrace();
427
            }
428
        }
429
        if (ComptaPropsConfiguration.getInstanceCompta().isOnCloud()) {
430
            pTOS.setProperty("hasCloud", "true");
431
        }
432
        final boolean allowDebug = pTOS.getProperty("allowDebug", "false").equals("true");
433
 
434
        ExceptionHandler.setSubmitErrorAutoEnabled(allowDebug);
435
 
436
        final int launchCounter = Integer.parseInt(pTOS.getProperty("launchCounter", "0"));
437
        pTOS.setProperty("launchCounter", String.valueOf(launchCounter + 1));
438
        saveProperties(fTOS, pTOS);
439
        if (!allowDebug && (launchCounter - 2) % 30 == 0) {
440
            SwingUtilities.invokeLater(new Runnable() {
441
                public void run() {
442
                    Object[] options = { "J'accepte", "Non, merci" };
443
                    int n = JOptionPane.showOptionDialog(null,
444
                            "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 ?",
445
                            "Rapport d'erreur", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
446
                    if (n == JOptionPane.YES_OPTION) {
447
                        pTOS.setProperty("allowDebug", "true");
448
                        saveProperties(fTOS, pTOS);
449
                        ExceptionHandler.setSubmitErrorAutoEnabled(true);
450
                    }
451
 
452
                }
453
            });
454
        }
455
        final boolean hasManual = pTOS.getProperty("hasManual", "false").equals("true");
456
        if (!hasManual && (launchCounter - 5) % 100 == 0) {
457
            SwingUtilities.invokeLater(new Runnable() {
458
                public void run() {
459
                    Object[] options = { "Je l'ai déjà", "Bonne idée!" };
460
                    int n = JOptionPane.showOptionDialog(null,
461
                            "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 ",
462
                            "Le manuel utilisateur", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[1]);
463
                    if (n == JOptionPane.YES_OPTION) {
464
                        pTOS.setProperty("hasManual", "true");
465
                        saveProperties(fTOS, pTOS);
466
                    } else {
467
                        try {
468
                            Desktop.getDesktop().browse(new URI("https://www.openconcerto.org/fr/documentation.html"));
469
                        } catch (Exception e) {
470
                            e.printStackTrace();
471
                        }
472
                    }
473
                }
474
            });
475
        }
476
        final boolean hasCloud = pTOS.getProperty("hasCloud", "false").equals("true");
477
        if (!hasCloud && (launchCounter - 30) % 100 == 0 && ComptaPropsConfiguration.getInstanceCompta().isServerless()) {
478
            SwingUtilities.invokeLater(new Runnable() {
479
                public void run() {
480
                    JOptionPane.showMessageDialog(null,
481
                            "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",
482
                            "Cloud", JOptionPane.INFORMATION_MESSAGE);
483
                    try {
484
                        Desktop.getDesktop().browse(new URI("https://cloud.openconcerto.org"));
485
                    } catch (Exception e) {
486
                        e.printStackTrace();
487
                    }
488
 
489
                }
490
            });
491
        }
492
 
41 ilm 493
        // Email props in .java
494
        File fMail2 = new File(Configuration.getInstance().getConfDir(), "Email.properties");
156 ilm 495
        EmailProps.getInstance().setDefaultPropsFileName(fMail2.toString());
41 ilm 496
        EmailProps.getInstance().setPropsFileName(fMail2.toString());
497
 
18 ilm 498
        SwingUtilities.invokeLater(new Runnable() {
499
 
500
            public void run() {
501
                long t1 = System.currentTimeMillis();
502
 
93 ilm 503
                IListe.setForceAlternateCellRenderer(true);
504
 
18 ilm 505
                AWTEventListener awtListener = new AWTEventListener() {
151 ilm 506
                    Set<Integer> frames = new HashSet<Integer>();
507
                    String prefix;
508
 
18 ilm 509
                    @Override
510
                    public final void eventDispatched(final AWTEvent event) {
511
                        assert event != null;
512
                        if (event instanceof HierarchyEvent && event.getID() == HierarchyEvent.HIERARCHY_CHANGED) {
513
                            // This event represents a change in the containment hierarcy.
514
                            // Now let's figure out what kind.
515
                            final HierarchyEvent hevent = (HierarchyEvent) event;
516
                            final Component changed = hevent.getChanged();
517
                            if (changed instanceof JFrame && ((hevent.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) && changed.isDisplayable()) {
151 ilm 518
                                final JFrame frame = (JFrame) changed;
18 ilm 519
                                frame.setIconImages(getFrameIcon());
151 ilm 520
                                if (!frames.contains(frame.hashCode())) {
521
                                    frames.add(frame.hashCode());
522
                                    frame.addPropertyChangeListener(new PropertyChangeListener() {
523
 
524
                                        @Override
525
                                        public void propertyChange(PropertyChangeEvent evt) {
526
                                            if (prefix == null) {
527
                                                if (ComptaPropsConfiguration.getInstance() != null && ComptaPropsConfiguration.getInstanceCompta().getRowSociete() != null) {
528
                                                    prefix = "[" + ComptaPropsConfiguration.getInstanceCompta().getRowSociete().getString("NOM") + "] ";
529
                                                } else {
530
                                                    return;
531
                                                }
532
                                            }
533
                                            String title = frame.getTitle();
534
                                            if (title != null && !title.startsWith(prefix)) {
535
                                                frame.setTitle(prefix + title);
536
                                            }
537
                                        }
538
                                    });
539
                                }
18 ilm 540
                            }
541
                        }
542
                    }
543
                };
544
                final Toolkit toolkit = Toolkit.getDefaultToolkit();
545
                assert toolkit != null;
546
                toolkit.addAWTEventListener(awtListener, AWTEvent.HIERARCHY_EVENT_MASK);
547
                if (logRequests) {
548
                    SQLRequestLog.showFrame();
549
                }
550
 
551
                JFrame f = null;
552
                try {
156 ilm 553
                    f = new NouvelleConnexionAction(conf).createFrame();
18 ilm 554
                    // happens with quick login
555
                    if (f != null) {
556
                        f.pack();
557
                        f.setResizable(false);
558
                        f.addWindowListener(new WindowAdapter() {
559
                            public void windowClosing(WindowEvent e) {
144 ilm 560
                                try {
561
                                    askForExit();
562
                                } catch (Exception ex) {
563
                                    ex.printStackTrace();
564
                                    // Broken state
565
                                    System.exit(2);
566
                                }
18 ilm 567
                            };
568
                        });
569
                        // f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
570
                    }
571
                } catch (Exception e) {
572
                    Thread.dumpStack();
573
                    e.printStackTrace();
574
                    ExceptionHandler.handle("Erreur lors de la tentative de connexion à la base.", e);
575
 
576
                } finally {
577
                    if (f != null) {
578
                        FrameUtil.show(f);
579
                    }
580
                    System.out.println("Init phase 2:" + (System.currentTimeMillis() - t1) + "ms");
581
                }
582
            }
583
        });
19 ilm 584
 
585
        // needed so that we can uninstall modules
586
        System.setProperty(SQLBase.ALLOW_OBJECT_REMOVAL, "true");
156 ilm 587
    }
588
 
589
    private static void saveProperties(File fTOS, Properties pTOS) {
25 ilm 590
        try {
156 ilm 591
            final FileOutputStream outputStream = new FileOutputStream(fTOS);
174 ilm 592
            FastXMLProperties.store(pTOS, outputStream, "tos");
156 ilm 593
            outputStream.close();
594
        } catch (Exception e) {
595
            e.printStackTrace();
25 ilm 596
        }
18 ilm 597
    }
598
 
144 ilm 599
    public static ThrowableHandler createDefaultThrowableHandler() {
600
 
601
        return new ThrowableHandler() {
602
 
603
            @Override
604
            public boolean handle(String message, Throwable throwable) {
605
                if (throwable == null)
606
                    return false;
174 ilm 607
                throwable.printStackTrace();
144 ilm 608
                final ByteArrayOutputStream out = new ByteArrayOutputStream();
609
                throwable.printStackTrace(new PrintStream(out));
610
                String s = new String(out.toByteArray());
611
                if (s.contains("Database may be already in use")) {
612
                    JOptionPane.showMessageDialog(null,
613
                            "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.");
614
                    System.exit(1);
615
                    return true;
616
                } else if (s.contains("PSQLException: Connexion") && ComptaPropsConfiguration.getInstanceCompta().isOnCloud()) {
617
                    JOptionPane.showMessageDialog(null, "Suite à une coupure de votre connexion internet, vous avez été déconnecté du Cloud.\nMerci de redémarrer le logiciel.");
618
                    System.exit(1);
619
                    return true;
620
                } else if (s.contains("File corrupted while reading")) {
621
                    JOptionPane.showMessageDialog(null,
622
                            "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).");
623
                    System.exit(1);
624
                    return true;
156 ilm 625
                } else if (s.contains("h2") && (s.contains("File corrupted while reading") || s.contains("data leaf table"))) {
144 ilm 626
                    JOptionPane.showMessageDialog(null,
627
                            "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).");
628
                    System.exit(1);
629
                    return true;
630
                } else if (s.contains("/private/var/folders/")) {
631
                    JOptionPane.showMessageDialog(null,
632
                            "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.");
633
                    System.exit(1);
634
                    return true;
635
                } else if (s.contains("com.sun.java.swing.plaf.windows.WindowsTableHeaderUI")) {
636
                    // bug connu de Java sur les TableHeader
637
                    return true;
156 ilm 638
                } else if (s.contains("WInputMethod.openCandidateWindow") && s.contains("java.lang.NullPointerException: peer")) {
639
                    // bug windows...
640
                    // Caused by: java.lang.NullPointerException: peer
641
                    // at sun.awt.windows.WInputMethod.openCandidateWindow(Native Method)
642
                    // at sun.awt.windows.WInputMethod.access$400(Unknown Source)
643
                    // at sun.awt.windows.WInputMethod$1.run(Unknown Source)
644
                    // at java.awt.event.InvocationEvent.dispatch(Unknown Source)
645
                    return true;
144 ilm 646
                }
156 ilm 647
 
174 ilm 648
                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 649
                    JOptionPane.showMessageDialog(null, "Merci d'installer LibreOffice ou tout autre application succeptible d'ouvrir ce fichier");
650
                    return true;
651
                } else if (s.contains("java.net.SocketTimeoutException: connect timed out")) {
652
                    JOptionPane.showMessageDialog(null, "Le serveur de base de données n'est pas joignable.\n" + message);
653
                    return true;
654
                } else if (s.contains("java.lang.NoSuchMethodError")) {
655
                    JOptionPane.showMessageDialog(null, "Un de vos modules n'est pas à jour.\n" + message);
656
                    return true;
657
                } else if (s.contains("InvalidTemplateException")) {
658
                    JOptionPane.showMessageDialog(null, "Votre modèle de document n'est pas valide.\n" + message, "Modèle incorrect", JOptionPane.ERROR_MESSAGE);
659
                    return true;
660
                }
144 ilm 661
                return false;
662
            }
663
        };
664
    }
665
 
18 ilm 666
    /**
667
     * Si la base est 127.0.0.1 ou localhost alors on essaye de lancer postgres.
668
     *
669
     * @param conf the configuration to connect to.
670
     */
671
    private static void startDB(PropsConfiguration conf) {
672
 
673
        List<String> l = new ArrayList<String>();
674
        l.add("Lancement de la base de données");
675
        PostgreSQLFrame pgFrame = null;
676
        try {
677
            pgFrame = new PostgreSQLFrame("Démarrage en cours");
678
            pgFrame.setVisible(true);
679
        } catch (Exception e) {
680
            e.printStackTrace();
681
        }
682
        System.err.println("start DB");
683
        final WaitIndeterminatePanel panel = new WaitIndeterminatePanel(l);
684
        final PanelFrame f = new PanelFrame(panel, "Gestion NX");
685
        f.setResizable(false);
686
        f.setLocationRelativeTo(null);
687
        f.setVisible(true);
688
 
689
        // on recupere les properties
690
        final String serverAdr = conf.getProperty("server.ip");
691
        // si la base est en local on relance postgres
692
        if (serverAdr.startsWith("127.0.0.1") || serverAdr.startsWith("localhost")) {
693
 
694
            Runtime runtime = Runtime.getRuntime();
695
            try {
696
                File file = new File(".\\PostgreSQL\\bin\\");
697
                if (!file.canWrite()) {
698
                    ExceptionHandler.die("Vous n'avez pas le droit en écriture sur la base de données.\nImpossible de lancer le logiciel!");
699
                }
700
                final Process p = runtime.exec(new String[] { "cmd.exe", "/C", "launchPostGres.bat" }, null, file);
701
                // Consommation de la sortie standard de l'application externe dans un Thread
702
                // separe
703
                new Thread() {
704
                    public void run() {
705
                        try {
706
                            BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
707
                            String line = "";
708
                            try {
709
                                while ((line = reader.readLine()) != null) {
710
                                    System.out.println(line);
711
                                }
712
                            } finally {
713
                                reader.close();
714
                            }
715
                        } catch (IOException ioe) {
716
                            ioe.printStackTrace();
717
                        }
718
                    }
719
                }.start();
720
 
721
                // Consommation de la sortie d'erreur de l'application externe dans un Thread
722
                // separe
723
                new Thread() {
724
                    public void run() {
725
                        try {
726
                            BufferedReader reader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
727
                            String line = "";
728
                            try {
729
                                while ((line = reader.readLine()) != null) {
730
                                    System.err.println(line);
731
                                }
732
                            } finally {
733
                                reader.close();
734
                            }
735
                        } catch (IOException ioe) {
736
                            ioe.printStackTrace();
737
                        }
738
                    }
739
                }.start();
740
                try {
741
                    p.waitFor();
742
                } catch (InterruptedException e2) {
743
                    e2.printStackTrace();
744
                }
745
            } catch (IOException e1) {
746
                e1.printStackTrace();
747
            }
748
        } else {
749
            System.err.println("L'adresse du serveur n'est pas en local (" + serverAdr + ").");
750
        }
751
 
752
        panel.taskEnded(0);
753
        if (pgFrame != null) {
754
            pgFrame.dispose();
755
        }
756
        f.dispose();
757
        String realIp = "127.0.0.1";
758
        realIp = getIp();
759
        try {
760
            pgFrameStart = new PostgreSQLFrame(realIp + " port " + "6543");
761
            pgFrameStart.setVisible(true);
762
        } catch (Exception e) {
763
            e.printStackTrace();
764
        }
765
 
766
    }
767
 
768
    private static String getIp() {
769
        String realIp = "127.0.0.1";
770
        try {
771
            InetAddress Ip = InetAddress.getLocalHost();
772
            realIp = Ip.getHostAddress();
773
        } catch (Exception e) {
774
            e.printStackTrace();
775
        }
776
        try {
67 ilm 777
            Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
18 ilm 778
            while (e.hasMoreElements()) {
779
                NetworkInterface ni = (NetworkInterface) e.nextElement();
67 ilm 780
                Enumeration<InetAddress> e2 = ni.getInetAddresses();
18 ilm 781
                while (e2.hasMoreElements()) {
782
                    InetAddress ip = (InetAddress) e2.nextElement();
783
                    final String iip = ip.toString().replace('/', ' ').trim();
784
                    if (iip.startsWith("192")) {
785
                        return iip;
786
                    }
787
                }
788
            }
789
        } catch (Exception e) {
790
            e.printStackTrace();
791
        }
792
        return realIp;
793
    }
794
 
795
    public static PostgreSQLFrame pgFrameStart = null;
796
 
797
    private static JDialog frameExit = null;
798
 
80 ilm 799
    static public void askForExit() {
800
        askForExit(UserExitConf.DEFAULT);
801
    }
802
 
803
    static public void askForExit(UserExitConf conf) {
18 ilm 804
        JDialog exitDialog = new JDialog();
805
        exitDialog.setModal(true);
806
 
807
        if (frameExit == null) {
808
            frameExit = new JDialog();
809
            frameExit.setTitle("Quitter");
810
            frameExit.setModal(true);
811
            frameExit.setIconImages(Gestion.getFrameIcon());
812
            frameExit.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
813
        }
814
 
80 ilm 815
        frameExit.setContentPane(new UserExitPanel(conf));
18 ilm 816
        frameExit.pack();
817
        frameExit.setResizable(false);
818
        frameExit.setLocationRelativeTo(null);
819
        frameExit.setAlwaysOnTop(true);
820
        frameExit.setVisible(true);
821
    }
822
 
93 ilm 823
    public static synchronized List<Image> getFrameIcon() {
18 ilm 824
        if (frameIcon == null) {
825
            frameIcon = new ArrayList<Image>();
826
            int[] sizes = { 16, 32, 48, 96 };
827
            for (int i = 0; i < sizes.length; i++) {
828
                int v = sizes[i];
829
                try {
830
                    frameIcon.add(new ImageIcon(Gestion.class.getResource(v + ".png")).getImage());
831
                } catch (Exception e) {
832
                    ExceptionHandler.die("Impossible de charger l'icone de fenetre " + v + ".png");
833
                }
834
            }
835
        }
836
        return frameIcon;
837
    }
838
}