OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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