1
package org.helioviewer.jhv;
3
import java.awt.EventQueue;
4
import java.io.IOException;
5
import java.lang.reflect.Method;
6
import java.net.MalformedURLException;
8
import java.net.URISyntaxException;
9
import java.util.HashSet;
10
import java.util.Locale;
12
import java.util.TimeZone;
14
import javax.swing.UIManager;
16
import org.helioviewer.base.logging.Log;
17
import org.helioviewer.base.logging.LogSettings;
18
import org.helioviewer.base.message.Message;
19
import org.helioviewer.jhv.gui.ImageViewerGui;
20
import org.helioviewer.jhv.gui.components.layerTable.LayerTableOverlapWatcher;
21
import org.helioviewer.jhv.internal_plugins.InternalFilterPlugin;
22
import org.helioviewer.jhv.io.CommandLineProcessor;
23
import org.helioviewer.jhv.layers.LayersModel;
24
import org.helioviewer.jhv.opengl.GLInfo;
25
import org.helioviewer.jhv.resourceloader.ResourceLoader;
26
import org.helioviewer.jhv.resourceloader.SystemProperties;
27
import org.helioviewer.viewmodel.view.jp2view.JP2Image;
28
import org.helioviewer.viewmodel.view.jp2view.kakadu.JHV_KduException;
29
import org.helioviewer.viewmodelplugin.controller.PluginManager;
30
import org.helioviewer.viewmodelplugin.interfaces.Plugin;
33
* This class starts the applications.
36
* @author Benjamin Wamsler
37
* @author Markus Langenberg
38
* @author Stephan Pagel
40
* @author Helge Dietert
43
public class JavaHelioViewer {
45
public static void main(String[] args) {
46
main(args, (Plugin[]) null);
49
public static void main(String[] args, Plugin builtinPlugin) {
50
main(args, new Plugin[] { builtinPlugin });
53
public static void main(String[] args, Plugin[] builtinPlugins) {
55
// Prints the usage message
56
if (args.length == 1 && (args[0].equals("-h") || args[0].equals("--help"))) {
57
System.out.println(CommandLineProcessor.getUsageMessage());
61
// Uncaught runtime errors are displayed in a dialog box in addition
62
JHVUncaughtExceptionHandler.setupHandlerForThread();
64
// Save command line arguments
65
CommandLineProcessor.setArguments(args);
67
// Save current default system timezone in user.timezone
68
System.setProperty("user.timezone", TimeZone.getDefault().getID());
70
// Per default all times should be given in GMT
71
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
73
// Save current default locale to user.locale
74
System.setProperty("user.locale", Locale.getDefault().toString());
76
// Per default, the us locale should be used
77
Locale.setDefault(Locale.US);
80
LogSettings.init("/settings/log4j.initial.properties", JHVDirectory.SETTINGS.getPath() + "log4j.properties", JHVDirectory.LOGS.getPath(), CommandLineProcessor.isOptionSet("--use-existing-log-time-stamp"));
82
// Information log message
83
String argString = "";
84
for (int i = 0; i < args.length; ++i) {
85
argString += " " + args[i];
87
Log.info("JHelioviewer started with command-line options:" + argString);
89
// This attempts to create the necessary directories for the application
90
Log.info("Create directories...");
91
JHVGlobals.createDirs();
93
// Save the log settings. Must be done AFTER the directories are created
94
LogSettings.getSingletonInstance().update();
96
// Read the version and revision from the JAR metafile
97
JHVGlobals.determineVersionAndRevision();
99
Log.info("Initializing JHelioviewer");
100
// display the splash screen
101
Log.debug("Create splash screen");
102
JHVSplashScreen splash = JHVSplashScreen.getSingletonInstance();
104
int numProgressSteps = 10;
105
Log.debug("Number of progress steps: " + numProgressSteps);
106
splash.setProgressSteps(numProgressSteps);
108
splash.setProgressText("Initializing JHelioviewer...");
110
// Load settings from file but do not apply them yet
111
// The settings must not be applied before the kakadu engine has been
113
splash.setProgressText("Loading settings...");
115
Log.info("Load settings");
116
Settings.getSingletonInstance().load();
118
// If the user has not specified any desired look and feel yet, the
119
// system default theme will be used
120
if (Settings.getSingletonInstance().getProperty("display.laf") == null || Settings.getSingletonInstance().getProperty("display.laf").length() <= 0) {
121
Log.info("Use default look and feel");
122
Settings.getSingletonInstance().setProperty("display.laf", UIManager.getSystemLookAndFeelClassName());
124
Settings.getSingletonInstance().save();
126
// Set the platform system properties
128
splash.setProgressText("Determining platform...");
130
SystemProperties.setPlatform();
131
Log.info("OS: " + System.getProperty("jhv.os") + " - arch: " + System.getProperty("jhv.arch") + " - java arch: " + System.getProperty("jhv.java.arch"));
133
// Remove about menu on mac
134
if (System.getProperty("jhv.os").equals("mac")) {
136
Class<?> applicationClass = Class.forName("com.apple.eawt.Application");
137
Method getSingletonApplication = applicationClass.getMethod("getApplication", (Class<?>[]) null);
138
Object application = getSingletonApplication.invoke(applicationClass.newInstance());
139
Method removeAboutMenuItem = applicationClass.getMethod("removeAboutMenuItem", (Class<?>[]) null);
140
removeAboutMenuItem.invoke(application);
141
} catch (Exception e) {
142
Log.warn(">> JavaHelioViewer.main(String[]) > Failed to disable native Mac OS about menu. Probably not running on Mac OS", e);
146
// Directories where to search for lib config files
147
URI libs = JHVDirectory.LIBS.getFile().toURI();
148
URI defaultPlugins = JHVDirectory.PLUGINS.getFile().toURI();
149
URI defaultPluginsBackup = JHVDirectory.PLUGINS_LAST_CONFIG.getFile().toURI();
150
URI libsBackup = JHVDirectory.LIBS_LAST_CONFIG.getFile().toURI();
151
URI libsRemote = null;
153
libsRemote = new URI(Settings.getSingletonInstance().getProperty("default.remote.lib.path"));
154
} catch (URISyntaxException e1) {
155
Log.error("Invalid uri for remote library server");
158
// Determine glibc version
159
if (System.getProperty("jhv.os").equals("linux")) {
160
splash.setProgressText("Determining glibc version...");
161
Log.info("Try to install glibc-version tool");
162
if (null == ResourceLoader.getSingletonInstance().loadResource("glibc-version", libsRemote, libs, libs, libsBackup, System.getProperties())) {
163
Log.error(">> JavaHelioViewer > Could not load glibc-version tool");
164
Message.err("Error loading glibc-version tool", "Error! The glibc-version tool could not be loaded. This may slow down the loading process and increase the network load.", false);
166
Log.info("Successfully installed glibc version tool");
168
if (SystemProperties.setGLibcVersion() != null) {
169
Log.info("Successfully determined glibc version: " + System.getProperty("glibc.version"));
171
Log.error(">> JavaHelioViewer > Could not determine glibc version");
172
Message.err("Error detecting glibc version", "Error! The glibc version could not be detected. This may slow down the loading process and increase the network load.", false);
174
} catch (Throwable t) {
175
Log.error(">> JavaHelioViewer > Could not determine glibc version", t);
176
Message.err("Error detecting glibc version", "Error! The glibc version could not be detected. This may slow down the loading process and increase the network load.", false);
181
/* ----------Setup kakadu ----------- */
182
Log.debug("Instantiate Kakadu engine");
183
KakaduEngine engine = new KakaduEngine();
186
splash.setProgressText("Initializing Kakadu libraries...");
187
Log.info("Try to load Kakadu libraries");
188
if (null == ResourceLoader.getSingletonInstance().loadResource("kakadu", libsRemote, libs, libs, libsBackup, System.getProperties())) {
189
Log.fatal("Could not load Kakadu libraries");
190
Message.err("Error loading Kakadu libraries", "Fatal error! The kakadu libraries could not be loaded. The log output may contain additional information.", true);
193
Log.info("Successfully loaded Kakadu libraries");
196
// The following code-block attempts to start the native message
200
Log.debug("Setup Kakadu message handlers.");
201
engine.startKduMessageSystem();
202
} catch (JHV_KduException e) {
203
Log.fatal("Failed to setup Kakadu message handlers.", e);
204
Message.err("Error starting Kakadu message handler", e.getMessage(), true);
208
// Apply settings after kakadu engine has been initialized
209
Log.info("Use cache directory: " + JHVDirectory.CACHE.getPath());
210
JP2Image.setCachePath(JHVDirectory.CACHE.getFile());
212
Log.info("Update settings");
213
Settings.getSingletonInstance().update();
215
/* ----------Setup OpenGL ----------- */
218
splash.setProgressText("Load OpenGL libraries...");
220
final URI finalLibs = libs;
221
final URI finalLibsRemote = libsRemote;
222
final URI finalLibsBackup = libsBackup;
224
// Has to run in EventQueue due to bug in NVidia Driver 260.99
226
EventQueue.invokeAndWait(new Runnable() {
229
Log.info("Try to load OpenGL libraries");
230
if (!System.getProperty("jhv.os").equals("mac")) {
231
System.loadLibrary("jawt");
233
if (null == ResourceLoader.getSingletonInstance().loadResource("jogl", finalLibsRemote, finalLibs, finalLibs, finalLibsBackup, System.getProperties())) {
234
Log.error("Could not load OpenGL libraries");
235
Message.err("Error loading OpenGL libraries", "The OpenGL libraries could not be loaded. JHelioviewer will run in software mode.", false);
238
com.sun.opengl.impl.NativeLibLoader.disableLoading();
239
com.sun.gluegen.runtime.NativeLibLoader.disableLoading();
240
Log.info("Successfully loaded OpenGL libraries");
244
} catch (Exception e1) {
245
e1.printStackTrace();
248
Log.info("Try to install CG Compiler");
249
if (null == ResourceLoader.getSingletonInstance().loadResource("cgc", libsRemote, libs, libs, libsBackup, System.getProperties())) {
250
Log.error("Could not install CG Compiler");
251
Message.err("Error installing CG Compiler", "The CG Compiler could not be installed. JHelioviewer will run in software mode.", false);
254
Log.info("Successfully installed CG Compiler");
257
/* ----------Setup FFmpeg ----------- */
260
splash.setProgressText("Initialize FFmpeg...");
261
// Load/download ffmpeg
262
Log.info("Install FFmpeg");
263
if (null == ResourceLoader.getSingletonInstance().loadResource("ffmpeg", libsRemote, libs, libs, libsBackup, System.getProperties())) {
264
Log.error("Error installing FFmpeg");
265
Message.err("Error installing FFmpeg", "Could not install FFmpeg tool. Movie export will not work.", false);
267
Log.info("Successfully installed FFmpeg tool");
271
splash.setProgressText("Initialize MP4Box...");
272
// Load/download mp4box
273
Log.info("Install MP4Box");
274
if (null == ResourceLoader.getSingletonInstance().loadResource("mp4box", libsRemote, libs, libs, libsBackup, System.getProperties())) {
275
Log.error("Error installing MP4Box");
276
Message.err("Error installing MP4Box", "Could not install MP4Box tool. Exported movies will not contain timestamps in subtitles.", false);
278
Log.info("Successfully installed MP4Box tool");
281
// This code updates the ImageViewer
282
Log.info("Initialize GUI");
283
ImageViewerGui.getSingletonInstance().updateComponents();
285
// Check for updates in parallel, if newer version is available a small
286
// message is displayed
288
JHVUpdate update = new JHVUpdate();
290
} catch (MalformedURLException e) {
291
// Should never happen
292
Log.error("Error retrieving internal update URL", e);
295
Log.debug("Installing Overlap Watcher");
296
LayerTableOverlapWatcher overlapWatcher = new LayerTableOverlapWatcher();
297
LayersModel.getSingletonInstance().addLayersListener(overlapWatcher);
299
// Load Plug ins at the very last point
302
splash.setProgressText("Loading Plugins...");
304
Log.info("Load plugin settings");
305
PluginManager.getSingeltonInstance().loadSettings(JHVDirectory.PLUGINS.getPath());
307
Log.info("Add internal plugin: " + "FilterPlugin");
308
Plugin internalPlugin = new InternalFilterPlugin();
309
PluginManager.getSingeltonInstance().addInternalPlugin(internalPlugin.getClass().getClassLoader(), internalPlugin);
311
if (builtinPlugins != null) {
312
for (int i = 0; i < builtinPlugins.length; ++i) {
313
PluginManager.getSingeltonInstance().addPlugin(builtinPlugins[i].getClass().getClassLoader(), builtinPlugins[i], null);
317
Set<String> deactivedPlugins = new HashSet<String>();
319
for (int i = 0; i < args.length - 1; ++i) {
320
if (args[i].equals("--deactivate-plugin")) {
321
deactivedPlugins.add(args[i + 1]);
325
Log.info("Download default plugins");
326
if (null == ResourceLoader.getSingletonInstance().loadResource("sdo-cutout", libsRemote, defaultPlugins, defaultPlugins, defaultPluginsBackup, System.getProperties())) {
327
Log.error("Error fetching SDO-Cutout plugin. Maybe JHelioviewer version not recent enough. Try updating JHV to the newest version.");
329
Log.info("Successfully downloaded SDO-Cutout plugin.");
332
if (null == ResourceLoader.getSingletonInstance().loadResource("default-plugins", libsRemote, defaultPlugins, defaultPlugins, defaultPluginsBackup, System.getProperties())) {
333
Log.error("Error fetching default plugins");
334
Message.err("Error fetching default plugins", "Could not download default plugins. You can try to download them from their respective website.", false);
336
Log.info("Successfully downloaded default plugins.");
340
Log.info("Search for plugins in " + JHVDirectory.PLUGINS.getPath());
341
PluginManager.getSingeltonInstance().searchForPlugins(JHVDirectory.PLUGINS.getFile(), true, deactivedPlugins);
342
} catch (IOException e) {
343
String title = "An error occured while loading the plugin files. At least one plugin file is corrupt!";
344
String message = "The following files are affected:\n" + e.getMessage();
345
Log.error(title + " " + message, e);
346
Message.warn(title, message);
350
splash.setProgressText("Start main window...");
352
// Create main view chain and display main window
353
Log.info("Start main window");
354
splash.initializeViewchain();