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