create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / startup / Startup.java
1 package net.sf.openrocket.startup;
2
3 import java.io.PrintStream;
4 import java.util.Locale;
5 import java.util.prefs.Preferences;
6
7 import net.sf.openrocket.gui.util.SwingPreferences;
8 import net.sf.openrocket.l10n.DebugTranslator;
9 import net.sf.openrocket.l10n.L10N;
10 import net.sf.openrocket.l10n.ResourceBundleTranslator;
11 import net.sf.openrocket.l10n.Translator;
12 import net.sf.openrocket.logging.DelegatorLogger;
13 import net.sf.openrocket.logging.LogHelper;
14 import net.sf.openrocket.logging.LogLevel;
15 import net.sf.openrocket.logging.LogLevelBufferLogger;
16 import net.sf.openrocket.logging.PrintStreamLogger;
17
18
19 /**
20  * The first class in the OpenRocket startup sequence.  This class is responsible
21  * for setting up the Application class with the statically used subsystems
22  * (logging and translation) and then delegating to Startup2 class.
23  * <p>
24  * This class must be very cautious about what classes it calls.  This is because
25  * the loggers/translators for classes are initialized as static final members during
26  * class initialization.  For example, this class MUST NOT use the Prefs class, because
27  * using it will cause LineStyle to be initialized, which then receives an invalid
28  * (not-yet-initialized) translator.
29  * 
30  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
31  */
32 public class Startup {
33         
34         static LogHelper log;
35         
36         private static final String LOG_STDERR_PROPERTY = "openrocket.log.stderr";
37         private static final String LOG_STDOUT_PROPERTY = "openrocket.log.stdout";
38         
39         private static final int LOG_BUFFER_LENGTH = 50;
40         
41         /**
42          * OpenRocket startup main method.
43          */
44         public static void main(final String[] args) throws Exception {
45                 
46                 // Check for "openrocket.debug" property before anything else
47                 checkDebugStatus();
48                 
49                 // Initialize logging first so we can use it
50                 initializeLogging();
51                 
52                 Application.setPreferences( new SwingPreferences() );
53                 
54                 // Setup the translations
55                 initializeL10n();
56
57                 // Continue startup in Startup2 class (where Application is already set up)
58                 Startup2.runMain(args);
59                 
60         }
61         
62
63         /**
64          * Set proper system properties if openrocket.debug is defined.
65          */
66         private static void checkDebugStatus() {
67                 if (System.getProperty("openrocket.debug") != null) {
68                         setPropertyIfNotSet("openrocket.log.stdout", "VBOSE");
69                         setPropertyIfNotSet("openrocket.log.tracelevel", "VBOSE");
70                         setPropertyIfNotSet("openrocket.debug.menu", "true");
71                         setPropertyIfNotSet("openrocket.debug.mutexlocation", "true");
72                         setPropertyIfNotSet("openrocket.debug.motordigest", "true");
73                 }
74         }
75         
76         private static void setPropertyIfNotSet(String key, String value) {
77                 if (System.getProperty(key) == null) {
78                         System.setProperty(key, value);
79                 }
80         }
81         
82         
83
84         /**
85          * Initializes the loggins system.
86          */
87         public static void initializeLogging() {
88                 DelegatorLogger delegator = new DelegatorLogger();
89                 
90                 // Log buffer
91                 LogLevelBufferLogger buffer = new LogLevelBufferLogger(LOG_BUFFER_LENGTH);
92                 delegator.addLogger(buffer);
93                 
94                 // Check whether to log to stdout/stderr
95                 PrintStreamLogger printer = new PrintStreamLogger();
96                 boolean logout = setLogOutput(printer, System.out, System.getProperty(LOG_STDOUT_PROPERTY), null);
97                 boolean logerr = setLogOutput(printer, System.err, System.getProperty(LOG_STDERR_PROPERTY), LogLevel.ERROR);
98                 if (logout || logerr) {
99                         delegator.addLogger(printer);
100                 }
101                 
102                 // Set the loggers
103                 Application.setLogger(delegator);
104                 Application.setLogBuffer(buffer);
105                 
106                 // Initialize the log for this class
107                 log = Application.getLogger();
108                 log.info("Logging subsystem initialized");
109                 String str = "Console logging output:";
110                 for (LogLevel l : LogLevel.values()) {
111                         PrintStream ps = printer.getOutput(l);
112                         str += " " + l.name() + ":";
113                         if (ps == System.err) {
114                                 str += "stderr";
115                         } else if (ps == System.out) {
116                                 str += "stdout";
117                         } else {
118                                 str += "none";
119                         }
120                 }
121                 str += " (" + LOG_STDOUT_PROPERTY + "=" + System.getProperty(LOG_STDOUT_PROPERTY) +
122                                 " " + LOG_STDERR_PROPERTY + "=" + System.getProperty(LOG_STDERR_PROPERTY) + ")";
123                 log.info(str);
124         }
125         
126         private static boolean setLogOutput(PrintStreamLogger logger, PrintStream stream, String level, LogLevel defaultLevel) {
127                 LogLevel minLevel = LogLevel.fromString(level, defaultLevel);
128                 if (minLevel == null) {
129                         return false;
130                 }
131                 
132                 for (LogLevel l : LogLevel.values()) {
133                         if (l.atLeast(minLevel)) {
134                                 logger.setOutput(l, stream);
135                         }
136                 }
137                 return true;
138         }
139         
140         
141
142
143         /**
144          * Initializes the localization system.
145          */
146         private static void initializeL10n() {
147                 
148                 // Check for locale propery
149                 String langcode = System.getProperty("openrocket.locale");
150                 
151                 if (langcode != null) {
152                         
153                         Locale l = L10N.toLocale(langcode);
154                         log.info("Setting custom locale " + l);
155                         Locale.setDefault(l);
156                         
157                 } else {
158                         
159                         // Check user-configured locale
160                         Locale l = getUserLocale();
161                         if (l != null) {
162                                 log.info("Setting user-selected locale " + l);
163                                 Locale.setDefault(l);
164                         } else {
165                                 log.info("Using default locale " + Locale.getDefault());
166                         }
167                         
168                 }
169                 
170                 // Setup the translator
171                 Translator t;
172                 t = new ResourceBundleTranslator("l10n.messages");
173                 if (Locale.getDefault().getLanguage().equals("xx")) {
174                         t = new DebugTranslator(t);
175                 }
176                 
177                 log.info("Set up translation for locale " + Locale.getDefault() +
178                                 ", debug.currentFile=" + t.get("debug.currentFile"));
179                 
180                 Application.setBaseTranslator(t);
181         }
182         
183         
184
185
186         private static Locale getUserLocale() {
187                 /*
188                  * This method MUST NOT use the Prefs class, since is causes a multitude
189                  * of classes to be initialized.  Therefore this duplicates the functionality
190                  * of the Prefs class locally.
191                  */
192
193                 if (System.getProperty("openrocket.debug.prefs") != null) {
194                         return null;
195                 }
196                 
197                 return L10N.toLocale(Preferences.userRoot().node("OpenRocket").get("locale", null));
198         }
199         
200
201 }