Java tutorial
/* * Copyright 2012 Krzysztof Otrebski * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package pl.otros.logview.exceptionshandler; import com.google.common.base.Throwables; import net.miginfocom.swing.MigLayout; import org.apache.commons.configuration.DataConfiguration; import pl.otros.logview.exceptionshandler.errrorreport.*; import pl.otros.logview.gui.ConfKeys; import pl.otros.logview.gui.Icons; import pl.otros.logview.gui.OtrosApplication; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; import java.lang.Thread.UncaughtExceptionHandler; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; public class ShowErrorDialogExceptionHandler extends AbstractSwingUncaughtExceptionHandler implements UncaughtExceptionHandler { private static final Logger LOGGER = Logger.getLogger(ShowErrorDialogExceptionHandler.class.getName()); private OtrosApplication otrosApplication; private JTextField emailTextField; private JTextArea commentTextArea; private JCheckBox checkBoxUseProxy; private JTextField proxyTf; private SpinnerNumberModel proxyPortModel; private JTextField proxyUser; private JPasswordField proxyPasswordField; private JSpinner proxySpinner; private JLabel labelProxyHost; private JLabel labelProxyPort; private JLabel labelProxyUser; private JLabel labelProxyPassword; private Set<String> caughtStackTraces; public ShowErrorDialogExceptionHandler(OtrosApplication otrosApplication) { this.otrosApplication = otrosApplication; caughtStackTraces = new HashSet<String>(); } @Override protected void uncaughtExceptionInSwingEDT(Thread thread, Throwable throwable) { String stackTraceAsString = Throwables.getStackTraceAsString(throwable); if (caughtStackTraces.contains(stackTraceAsString)) { LOGGER.info("Not sending the same error report twice"); return; } caughtStackTraces.add(stackTraceAsString); JPanel message = new JPanel(new BorderLayout()); message.add(new JLabel("Error in thread " + thread.getName()), BorderLayout.NORTH); String stackTrace = getStackTrace(throwable); JTextArea textArea = new JTextArea(10, 70); textArea.setText(stackTrace); textArea.setCaretPosition(0); message.add(new JScrollPane(textArea)); JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE); Map<String, String> errorReportData = generateReportData(thread, throwable, otrosApplication); JComponent jComponent = createDialogView(); String[] options = { "Send", "Do not send" }; int sendReport = JOptionPane.showOptionDialog(otrosApplication.getApplicationJFrame(), jComponent, "Send error report confirmation", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, Icons.MEGAPHONE_24, options, options[0]); errorReportData.put("USER:email", emailTextField.getText()); errorReportData.put("USER:comment", commentTextArea.getText()); if (sendReport == JOptionPane.YES_OPTION) { DataConfiguration c = otrosApplication.getConfiguration(); c.setProperty(ConfKeys.HTTP_PROXY_USE, checkBoxUseProxy.isSelected()); c.setProperty(ConfKeys.HTTP_PROXY_HOST, proxyTf.getText()); c.setProperty(ConfKeys.HTTP_PROXY_PORT, proxyPortModel.getNumber().intValue()); c.setProperty(ConfKeys.HTTP_PROXY_USER, proxyUser.getText()); sendReportInNewBackground(errorReportData); } else { LOGGER.info("Not sending error report"); } logErrorReport(errorReportData); } private void logErrorReport(Map<String, String> errorReportData) { LOGGER.info( "Dumping information about running application. Have " + errorReportData.size() + " properties"); TreeSet<String> keys = new TreeSet<String>(errorReportData.keySet()); for (String key : keys) { LOGGER.info(String.format("%s: %s", key, errorReportData.get(key))); } } private void sendReportInNewBackground(final Map<String, String> stringStringMap) { Runnable r = new Runnable() { @Override public void run() { ErrorReportSender errorReportSender = new ErrorReportSender(); if (checkBoxUseProxy.isSelected()) { errorReportSender.setProxy(proxyTf.getText()); errorReportSender.setPassword(new String(proxyPasswordField.getPassword())); errorReportSender.setUser(proxyUser.getText()); errorReportSender.setProxyPort(proxyPortModel.getNumber().intValue()); } try { errorReportSender.sendReport(stringStringMap); } catch (IOException e) { LOGGER.log(Level.SEVERE, "Cant send error report", e); } } }; new Thread(r, "Error sending thread").start(); } public Map<String, String> generateReportData(Thread thread, Throwable throwable, OtrosApplication otrosApplication) { ErrorReportCollectingContext ctx = new ErrorReportCollectingContext(); ctx.setThread(thread); ctx.setThrowable(throwable); ctx.setOtrosApplication(otrosApplication); ArrayList<ErrorReportDataCollector> collectors = new ArrayList<ErrorReportDataCollector>(); collectors.add(new RuntimeInfoERDC()); collectors.add(new SystemPropertiesERDC()); collectors.add(new DesktopERDC()); collectors.add(new ExceptionERDC()); collectors.add(new OtrosAppERDC()); collectors.add(new UuidERDC()); HashMap<String, String> map = new HashMap<String, String>(); for (ErrorReportDataCollector errorReportDataCollector : collectors) { try { map.putAll(errorReportDataCollector.collect(ctx)); } catch (Throwable t) { LOGGER.log(Level.SEVERE, "Error during collecting diagnostic data", t); } } return map; } private String getStackTrace(Throwable throwable) { ByteArrayOutputStream bout = new ByteArrayOutputStream(); throwable.printStackTrace(new PrintStream(bout)); return new String(bout.toByteArray()); } protected JComponent createDialogView() { JPanel jPanel = new JPanel(new MigLayout()); JLabel label = new JLabel("Do you want to send error report?"); label.setFont(label.getFont().deriveFont(Font.BOLD)); jPanel.add(label, "span 4, wrap, center"); jPanel.add(new JLabel("Comment:")); commentTextArea = new JTextArea(10, 30); commentTextArea.setWrapStyleWord(true); commentTextArea.setLineWrap(true); JScrollPane jScrollPane = new JScrollPane(commentTextArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); jPanel.add(jScrollPane, "span 3, wrap"); jPanel.add(new JLabel("Email (optional):")); emailTextField = new JTextField(30); jPanel.add(emailTextField, "span 3, wrap"); jPanel.add(new JSeparator(), "span 4, wrap, grow"); checkBoxUseProxy = new JCheckBox("Use HTTP proxy"); proxyTf = new JTextField(); proxyPortModel = new SpinnerNumberModel(80, 1, 256 * 256 - 1, 1); proxyUser = new JTextField(); proxyPasswordField = new JPasswordField(); proxySpinner = new JSpinner(proxyPortModel); jPanel.add(checkBoxUseProxy, "wrap"); labelProxyHost = new JLabel("Proxy address"); jPanel.add(labelProxyHost); jPanel.add(proxyTf, "wrap, span 3, grow"); labelProxyPort = new JLabel("Proxy port"); jPanel.add(labelProxyPort); jPanel.add(proxySpinner, "wrap"); labelProxyUser = new JLabel("User"); jPanel.add(labelProxyUser); jPanel.add(proxyUser, "grow"); labelProxyPassword = new JLabel("Password"); jPanel.add(labelProxyPassword); jPanel.add(proxyPasswordField, "grow"); checkBoxUseProxy.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { setProxyEnabled(checkBoxUseProxy.isSelected()); } }); DataConfiguration c = otrosApplication.getConfiguration(); proxyTf.setText(c.getString(ConfKeys.HTTP_PROXY_HOST, "")); proxyUser.setText(c.getString(ConfKeys.HTTP_PROXY_USER, "")); proxyPortModel.setValue(Integer.valueOf(c.getInt(ConfKeys.HTTP_PROXY_PORT, 80))); boolean useProxy = c.getBoolean(ConfKeys.HTTP_PROXY_USE, false); checkBoxUseProxy.setSelected(useProxy); setProxyEnabled(useProxy); return jPanel; } private void setProxyEnabled(boolean enabled) { proxyTf.setEnabled(enabled); proxySpinner.setEnabled(enabled); proxyUser.setEnabled(enabled); proxyPasswordField.setEnabled(enabled); labelProxyHost.setEnabled(enabled); labelProxyPassword.setEnabled(enabled); labelProxyPort.setEnabled(enabled); labelProxyUser.setEnabled(enabled); } }