KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > core > main > Bootstrap


1 // The contents of this file are subject to the Mozilla Public License Version
2
// 1.1
3
//(the "License"); you may not use this file except in compliance with the
4
//License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
5
//
6
//Software distributed under the License is distributed on an "AS IS" basis,
7
//WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
8
//for the specific language governing rights and
9
//limitations under the License.
10
//
11
//The Original Code is "The Columba Project"
12
//
13
//The Initial Developers of the Original Code are Frederik Dietz and Timo
14
// Stich.
15
//Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
16
//
17
//All Rights Reserved.
18
package org.columba.core.main;
19
20 import java.io.File JavaDoc;
21 import java.io.FilenameFilter JavaDoc;
22 import java.lang.reflect.Field JavaDoc;
23 import java.net.URL JavaDoc;
24 import java.net.URLClassLoader JavaDoc;
25 import java.text.MessageFormat JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.logging.Logger JavaDoc;
29
30 import javax.swing.JPopupMenu JavaDoc;
31 import javax.swing.RepaintManager JavaDoc;
32 import javax.swing.SwingUtilities JavaDoc;
33
34 import org.apache.commons.cli.CommandLine;
35 import org.apache.commons.cli.Option;
36 import org.apache.commons.cli.OptionBuilder;
37 import org.apache.commons.cli.ParseException;
38 import org.columba.core.association.AssociationStore;
39 import org.columba.core.backgroundtask.BackgroundTaskManager;
40 import org.columba.core.base.OSInfo;
41 import org.columba.core.component.ComponentManager;
42 import org.columba.core.config.Config;
43 import org.columba.core.config.DefaultConfigDirectory;
44 import org.columba.core.config.SaveConfig;
45 import org.columba.core.desktop.ColumbaDesktop;
46 import org.columba.core.gui.base.DebugRepaintManager;
47 import org.columba.core.gui.frame.FrameManager;
48 import org.columba.core.gui.profiles.Profile;
49 import org.columba.core.gui.profiles.ProfileManager;
50 import org.columba.core.gui.themes.ThemeSwitcher;
51 import org.columba.core.gui.trayicon.ColumbaTrayIcon;
52 import org.columba.core.gui.util.FontProperties;
53 import org.columba.core.gui.util.StartUpFrame;
54 import org.columba.core.logging.Logging;
55 import org.columba.core.plugin.PluginManager;
56 import org.columba.core.resourceloader.GlobalResourceLoader;
57 import org.columba.core.scripting.service.ServiceManager;
58 import org.columba.core.shutdown.ShutdownManager;
59 import org.columba.core.util.StackProfiler;
60 import org.columba.core.versioninfo.VersionInfo;
61 import org.frapuccino.swing.ActiveWindowTracker;
62
63 import sun.misc.URLClassPath;
64
65 public class Bootstrap {
66
67     private static final Logger JavaDoc LOG = Logger.getLogger("org.columba.core.main"); //$NON-NLS-1$
68

69     private static final String JavaDoc RESOURCE_PATH = "org.columba.core.i18n.global"; //$NON-NLS-1$
70

71     // TODO @author hubms have this flags, until the speed of the entitymanager
72
// is improved
73
public static boolean ENABLE_TAGS = false;
74
75     private String JavaDoc path;
76
77     private boolean showSplashScreen = true;
78
79     public void run(String JavaDoc args[]) throws Exception JavaDoc {
80
81         addNativeJarsToClasspath();
82         setLibraryPath();
83
84         // For the Mac ScreenBarMenus to work, this must be declared before
85
// *ANY* AWT / Swing gets initialised. Do *NOT* move it to plugin init
86
// location because that is too late...
87
if (OSInfo.isMac()) {
88             System.setProperty("apple.laf.useScreenMenuBar", "true");
89             System.setProperty(
90                     "com.apple.mrj.application.apple.menu.about.name",
91                     "Columba");
92         }
93
94         Logging.createDefaultHandler();
95         registerCommandLineArguments();
96
97         StackProfiler profiler = new StackProfiler();
98         profiler.push("main");
99         profiler.push("config");
100         profiler.push("profile");
101         // prompt user for profile
102
Profile profile = ProfileManager.getInstance().getProfile(path);
103         profiler.pop("profile");
104
105         // initialize configuration with selected profile
106
DefaultConfigDirectory.getInstance().setCurrentPath(profile.getLocation());
107         new Config(profile.getLocation());
108         profiler.pop("config");
109
110         // if user doesn't overwrite logger settings with commandline arguments
111
// just initialize default logging
112
// Logging.createDefaultHandler();
113
Logging.createDefaultFileHandler(DefaultConfigDirectory.getDefaultPath());
114
115         for (int i = 0; i < args.length; i++) {
116             LOG.info("arg[" + i + "]=" + args[i]);
117         }
118
119         SessionController.passToRunningSessionAndExit(args);
120
121         // enable debugging of repaint manager to track down swing gui
122
// access from outside the awt-event dispatcher thread
123

124         if (Logging.DEBUG)
125             RepaintManager.setCurrentManager(new DebugRepaintManager());
126
127         // use heavy-weight popups to ensure they are always on top
128
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
129
130         // keep track of active windows (used by dialogs which don't have a
131
// direct parent)
132
ActiveWindowTracker.class.getClass();
133
134         // show splash screen
135
StartUpFrame frame = null;
136         if (showSplashScreen) {
137             frame = new StartUpFrame();
138             frame.setVisible(true);
139         }
140
141         // register protocol handler
142
System.setProperty("java.protocol.handler.pkgs",
143                 "org.columba.core.url|"
144                         + System.getProperty("java.protocol.handler.pkgs", ""));
145
146         profiler.push("i18n");
147         // load user-customised language pack
148
GlobalResourceLoader.loadLanguage();
149         profiler.pop("i18n");
150
151         SaveConfig task = new SaveConfig();
152         BackgroundTaskManager.getInstance().register(task);
153         ShutdownManager.getInstance().register(task);
154
155         profiler.push("plugins core");
156         initPlugins();
157         profiler.pop("plugins core");
158
159         profiler.push("components");
160         // init all components
161
ComponentManager.getInstance().init();
162         ComponentManager.getInstance().registerCommandLineArguments();
163         profiler.pop("components");
164
165         // set Look & Feel
166
ThemeSwitcher.setTheme();
167
168         // initialize platform-dependant services
169
initPlatformServices();
170
171         // init font configuration
172
new FontProperties();
173
174         // set application wide font
175
FontProperties.setFont();
176
177 // handle commandline parameters
178
if (handleCoreCommandLineParameters(args)) {
179             System.exit(0);
180         }
181
182         // handle the commandline arguments of the modules
183
ComponentManager.getInstance().handleCommandLineParameters(
184                 ColumbaCmdLineParser.getInstance().getParsedCommandLine());
185
186         profiler.push("plugins external");
187         // now load all available plugins
188
// PluginManager.getInstance().initExternalPlugins();
189
profiler.pop("plugins external");
190
191         profiler.push("frames");
192
193         // restore frames of last session
194
if (ColumbaCmdLineParser.getInstance().getRestoreLastSession()) {
195             SwingUtilities.invokeLater(new Runnable JavaDoc() {
196                 public void run() {
197                     FrameManager.getInstance().openStoredViews();
198                 }
199             });
200         }
201
202         /* initialize services before dismissing the splash screen */
203         ServiceManager.getInstance().initServices();
204
205         // register shutdown manager
206
ShutdownManager.getInstance().register(new Runnable JavaDoc() {
207             public void run() {
208
209                 ServiceManager.getInstance().stopServices();
210                 ServiceManager.getInstance().disposeServices();
211             }
212         });
213
214         profiler.pop("frames");
215
216         // Add the tray icon to the System tray
217
// ColumbaTrayIcon.getInstance().addToSystemTray(
218
// FrameManager.getInstance().getActiveFrameMediator()
219
// .getFrameMediator());
220

221         profiler.push("tagging");
222
223         // initialize tagging
224
if (ENABLE_TAGS) {
225             AssociationStore.getInstance().init();
226             // register for cleanup
227
ShutdownManager.getInstance().register(AssociationStore.getInstance());
228         }
229
230         profiler.pop("tagging");
231
232         // hide splash screen
233
if (frame != null) {
234             frame.setVisible(false);
235         }
236
237         // call the postStartups of the modules
238
// e.g. check for default mailclient
239
ComponentManager.getInstance().postStartup();
240
241         /* everything is up and running, start services */
242         ServiceManager.getInstance().startServices();
243
244         profiler.pop("main");
245
246     }
247
248     /**
249      * initialize all extension handlers from core, mail and contacts.
250      * Additionally, load all internally shipped plugins and last but not least,
251      * load all external plugins residing in /plugin directory.
252      */

253     private void initPlugins() {
254
255         //
256
// first load all extension handlers
257
//
258

259         // load core extension handlers
260
PluginManager.getInstance().addExtensionHandlers(
261                 "org/columba/core/plugin/extensionhandler.xml");
262
263         // load addressbook extension handler
264
PluginManager.getInstance().addExtensionHandlers(
265                 "org/columba/addressbook/plugin/extensionhandler.xml");
266
267         // load mail extension handler
268
PluginManager.getInstance().addExtensionHandlers(
269                 "org/columba/mail/plugin/extensionhandler.xml");
270
271         // load all internal core plugins
272
String JavaDoc path = "org/columba/core/plugin/plugin.xml";
273         PluginManager.getInstance().addPlugin(path);
274
275         //
276
// following internal components plugin registration
277
//
278

279         // load all internal addressbook plugins
280
path = "org/columba/addressbook/plugin/plugin.xml";
281         PluginManager.getInstance().addPlugin(path);
282
283         // load all internal mail plugins
284
path = "org/columba/mail/plugin/plugin.xml";
285         PluginManager.getInstance().addPlugin(path);
286
287         // load all internal calendar plugins
288
path = "org/columba/calendar/plugin/plugin.xml";
289         PluginManager.getInstance().addPlugin(path);
290
291         //
292
// now load all external plugins residing in /plugins directory
293
//
294
PluginManager.getInstance().initExternalPlugins();
295     }
296
297     /**
298      * registerCommandLineArguments method
299      */

300     private void registerCommandLineArguments() {
301         ColumbaCmdLineParser parser = ColumbaCmdLineParser.getInstance();
302
303         parser.addOption(new Option("version", GlobalResourceLoader.getString(
304                 RESOURCE_PATH, "global", "cmdline_version")));
305
306         parser.addOption(new Option("help", GlobalResourceLoader.getString(
307                 RESOURCE_PATH, "global", "cmdline_help")));
308
309         parser.addOption(OptionBuilder.withArgName("path").hasArg().create(
310                 "profile"));
311
312         parser.addOption(new Option("profile", GlobalResourceLoader.getString(
313                 RESOURCE_PATH, "global", "cmdline_profile")));
314
315         parser.addOption(new Option("debug", GlobalResourceLoader.getString(
316                 RESOURCE_PATH, "global", "cmdline_debug")));
317
318         parser.addOption(new Option("nosplash", GlobalResourceLoader.getString(
319                 RESOURCE_PATH, "global", "cmdline_nosplash")));
320
321         // ComponentPluginHandler handler = null;
322
// try {
323
// handler = (ComponentPluginHandler) PluginManager.getInstance()
324
// .getHandler("org.columba.core.component");
325
// handler.registerCommandLineArguments();
326
// } catch (PluginHandlerNotFoundException e) {
327
// e.printStackTrace();
328
// }
329
}
330
331     /**
332      * Uses the command line parser to validate the passed arguments and invokes
333      * handlers to process the detected options.
334      */

335     private boolean handleCoreCommandLineParameters(String JavaDoc[] args) {
336         ColumbaCmdLineParser parser = ColumbaCmdLineParser.getInstance();
337         CommandLine commandLine;
338
339         try {
340             commandLine = parser.parse(args);
341         } catch (ParseException e) {
342             // oops, something went wrong
343
System.err.println("Parsing failed. Reason: " + e.getMessage());
344             parser.printUsage();
345
346             return true;
347         }
348
349         if (commandLine.hasOption("help")) {
350             parser.printUsage();
351
352             return true;
353         }
354
355         // TODO: Make this hack more i18n compatible
356
if (commandLine.hasOption("version")) {
357             LOG.info(MessageFormat.format(GlobalResourceLoader.getString(
358                     RESOURCE_PATH, "global", "info_version"), //$NON-NLS-2$
359
new Object JavaDoc[] { VersionInfo.getVersion(),
360                             VersionInfo.getBuildDate() }));
361             System.out.println("Columba (" + VersionInfo.getVersion()
362                     + ") built " + VersionInfo.getBuildDate() + "\n");
363             return true;
364         }
365
366         if (commandLine.hasOption("profile")) {
367
368             // TODO: There's probably a better way to do this hack...
369
path = commandLine.getArgList().toString();
370
371             // This is necessary because getArgList returns the path in
372
// square brackets
373
path = path.substring(1, path.length() - 1);
374         }
375
376         if (commandLine.hasOption("debug")) {
377             Logging.DEBUG = true;
378             Logging.setDebugging(true);
379         }
380
381         if (commandLine.hasOption("nosplash")) {
382             showSplashScreen = false;
383         }
384
385         // Do not exit
386
return false;
387     }
388
389     /**
390      * This hacks the classloader to adjust the library path for convenient
391      * native support.
392      *
393      * @author tstich
394      *
395      * @throws Exception
396      */

397     private void setLibraryPath() throws Exception JavaDoc {
398         String JavaDoc libDir;
399         if (OSInfo.isAMD64Bit())
400             libDir = "amd64";
401         else
402             libDir = "lib";
403
404         // Platform maintainers: add your platform here
405

406         String JavaDoc propertyPath = System.getProperty("java.library.path");
407
408         if (OSInfo.isLinux())
409             propertyPath += ":native/linux/";
410         else if (OSInfo.isMac())
411             propertyPath += ":native/mac/";
412         else if (OSInfo.isWin32Platform())
413             propertyPath += ";native\\win32\\";
414         // Platform maintainers: add your platform here
415

416         propertyPath += libDir;
417
418         System.setProperty("java.library.path", propertyPath);
419         LOG.info("The java.library.path = " + propertyPath);
420         Field JavaDoc fieldSysPath = ClassLoader JavaDoc.class.getDeclaredField("sys_paths");
421         fieldSysPath.setAccessible(true);
422         if (fieldSysPath != null) {
423             fieldSysPath.set(System JavaDoc.class.getClassLoader(), null);
424         }
425     }
426
427     /**
428      * This hacks the classloader to adjust the classpath for convenient native
429      * support.
430      * <p>
431      * I've cleaned this up using our new global class loader. This way we only
432      * add a few new <code>URLs</code> to our class loader instead of
433      * modifying the system class loader using reflection.
434      *
435      * @author tstich,fdietz
436      *
437      * @throws Exception
438      */

439     private void addNativeJarsToClasspath() throws Exception JavaDoc {
440         File JavaDoc nativeDir;
441
442         String JavaDoc libDir;
443         if (OSInfo.isAMD64Bit())
444             libDir = "amd64";
445         else
446             libDir = "lib";
447
448         // Setup the path
449
// Platform maintainers: add your platform here
450
// see also initPlatformServices() method
451
if (OSInfo.isLinux())
452             nativeDir = new File JavaDoc("native/linux/" + libDir);
453         else if (OSInfo.isMac())
454             nativeDir = new File JavaDoc("native/mac/" + libDir);
455         else if (OSInfo.isWin32Platform())
456             nativeDir = new File JavaDoc("native/win32/" + libDir);
457         else {
458             LOG.info("Native support for Platform not available.");
459             return;
460         }
461
462         // Find all native jars
463
File JavaDoc[] nativeJars = nativeDir.listFiles(new FilenameFilter JavaDoc() {
464             public boolean accept(File JavaDoc dir, String JavaDoc name) {
465                 return name.endsWith("jar") || name.endsWith("jnilib");
466             }
467         });
468         if (nativeJars == null)
469             return;
470
471         // @author: fdietz
472
//
473
// The following line is not working - just don't know why
474
// Main.mainClassLoader.addURLs((URL[]) urlList.toArray(new URL[0]));
475
//
476
// WORKAROUND:
477
//
478
// Modify the system class loader instead - horrible! But it works!
479

480         // Get the current classpath from the sysloader
481
// through reflection
482
URLClassLoader JavaDoc sysloader = (URLClassLoader JavaDoc) ClassLoader
483                 .getSystemClassLoader();
484
485         Field JavaDoc ucp = URLClassLoader JavaDoc.class.getDeclaredField("ucp");
486         ucp.setAccessible(true);
487         URLClassPath currentCP = (URLClassPath) ucp.get(sysloader);
488         URL JavaDoc[] currentURLs = currentCP.getURLs();
489
490         // add all native jars
491
List JavaDoc<URL JavaDoc> urlList = new ArrayList JavaDoc<URL JavaDoc>();
492         for (int i = 0; i < nativeJars.length; i++) {
493             urlList.add(nativeJars[i].toURL());
494         }
495
496         // add the old classpath
497
for (int i = 0; i < currentURLs.length; i++) {
498             urlList.add(currentURLs[i]);
499         }
500
501         // replace with the modified classpath
502
ucp.set(sysloader,
503                 new URLClassPath((URL JavaDoc[]) urlList.toArray(new URL JavaDoc[0])));
504     }
505
506     /**
507      * Initialise system dependent stuff
508      */

509     private void initPlatformServices() {
510
511         // Initialise system dependent stuff
512
ColumbaDesktop.getInstance().initActiveDesktop();
513         ColumbaTrayIcon.getInstance().initActiveIcon();
514     }
515 }
516
Popular Tags