View Javadoc
1   /*
2    * Copyright (C) 2013 4th Line GmbH, Switzerland
3    *
4    * The contents of this file are subject to the terms of either the GNU
5    * Lesser General Public License Version 2 or later ("LGPL") or the
6    * Common Development and Distribution License Version 1 or later
7    * ("CDDL") (collectively, the "License"). You may not use this file
8    * except in compliance with the License. See LICENSE.txt for more
9    * information.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14   */
15  
16  package org.fourthline.cling.support.shared;
17  
18  import org.fourthline.cling.support.shared.log.LogView;
19  import org.seamless.util.logging.LoggingUtil;
20  import org.seamless.swing.Application;
21  import org.seamless.swing.logging.LogMessage;
22  import org.seamless.swing.logging.LoggingHandler;
23  import org.seamless.util.OS;
24  
25  import javax.inject.Inject;
26  import javax.inject.Singleton;
27  import javax.swing.JButton;
28  import javax.swing.JFrame;
29  import javax.swing.JScrollPane;
30  import javax.swing.JTextArea;
31  import javax.swing.SwingUtilities;
32  import javax.swing.UIManager;
33  import java.awt.BorderLayout;
34  import java.awt.Dimension;
35  import java.awt.Window;
36  import java.awt.event.ActionEvent;
37  import java.awt.event.ActionListener;
38  import java.awt.event.WindowAdapter;
39  import java.awt.event.WindowEvent;
40  import java.io.PrintWriter;
41  import java.io.StringWriter;
42  import java.io.Writer;
43  import java.util.logging.LogManager;
44  
45  /**
46   * @author Christian Bauer
47   */
48  public abstract class Main implements ShutdownHandler, Thread.UncaughtExceptionHandler {
49  
50      @Inject
51      LogView.Presenter logPresenter;
52  
53      final protected JFrame errorWindow = new JFrame();
54  
55      // In addition to the JUL-configured handler, show log messages in the UI
56      final protected LoggingHandler loggingHandler =
57          new LoggingHandler() {
58              @Override
59              protected void log(LogMessage msg) {
60                  logPresenter.pushMessage(msg);
61              }
62          };
63  
64      protected boolean isRegularShutdown;
65  
66      public void init() {
67  
68          try {
69              // Platform specific setup
70              if (OS.checkForMac())
71                  NewPlatformApple.setup(this, getAppName());
72  
73              // Some UI stuff (of course, why would the OS L&F be the default -- too easy?!)
74              UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
75  
76          } catch (Exception ex) {
77              // Ignore...
78          }
79  
80          // Exception handler
81          errorWindow.setPreferredSize(new Dimension(900, 400));
82          errorWindow.addWindowListener(new WindowAdapter() {
83              @Override
84              public void windowClosing(WindowEvent windowEvent) {
85                  errorWindow.dispose();
86              }
87          });
88          Thread.setDefaultUncaughtExceptionHandler(this);
89  
90          // Shutdown behavior
91          Runtime.getRuntime().addShutdownHook(new Thread() {
92              @Override
93              public void run() {
94                  if (!isRegularShutdown) { // Don't run the hook if everything is already stopped
95                      shutdown();
96                  }
97              }
98          });
99  
100         // Wire logging UI into JUL, don't reset JUL root logger but
101         // add our handler if there is a JUL config file
102         if (System.getProperty("java.util.logging.config.file") == null) {
103             LoggingUtil.resetRootHandler(loggingHandler);
104         } else {
105             LogManager.getLogManager().getLogger("").addHandler(loggingHandler);
106         }
107     }
108 
109     @Override
110     public void shutdown() {
111         isRegularShutdown = true;
112         SwingUtilities.invokeLater(new Runnable() {
113             public void run() {
114                 errorWindow.dispose();
115             }
116         });
117     }
118 
119     @Override
120     public void uncaughtException(Thread thread, final Throwable throwable) {
121 
122         System.err.println("In thread '" + thread + "' uncaught exception: " + throwable);
123         throwable.printStackTrace(System.err);
124 
125         SwingUtilities.invokeLater(new Runnable() {
126             @Override
127             public void run() {
128                 errorWindow.getContentPane().removeAll();
129 
130                 JTextArea textArea = new JTextArea();
131                 textArea.setEditable(false);
132                 StringBuilder text = new StringBuilder();
133 
134                 text.append("An exceptional error occurred!\nYou can try to continue or exit the application.\n\n");
135                 text.append("Please tell us about this here:\nhttp://www.4thline.org/projects/mailinglists-cling.html\n\n");
136                 text.append("-------------------------------------------------------------------------------------------------------------\n\n");
137                 Writer stackTrace = new StringWriter();
138                 throwable.printStackTrace(new PrintWriter(stackTrace));
139                 text.append(stackTrace.toString());
140 
141                 textArea.setText(text.toString());
142                 JScrollPane pane = new JScrollPane(textArea);
143                 errorWindow.getContentPane().add(pane, BorderLayout.CENTER);
144 
145                 JButton exitButton = new JButton("Exit Application");
146                 exitButton.addActionListener(new ActionListener() {
147                     @Override
148                     public void actionPerformed(ActionEvent e) {
149                         System.exit(1);
150                     }
151                 });
152 
153                 errorWindow.getContentPane().add(exitButton, BorderLayout.SOUTH);
154 
155                 errorWindow.pack();
156                 Application.center(errorWindow);
157                 textArea.setCaretPosition(0);
158 
159                 errorWindow.setVisible(true);
160             }
161         });
162     }
163 
164     protected void removeLoggingHandler() {
165         LogManager.getLogManager().getLogger("").removeHandler(loggingHandler);
166     }
167 
168     abstract protected String getAppName();
169 
170 }