Back to index

apport  2.3
ApportUncaughtExceptionHandler.java
Go to the documentation of this file.
00001 package com.ubuntu.apport;
00002 
00003 /*
00004  * Apport handler for uncaught Java exceptions
00005  * 
00006  * Copyright: 2010 Canonical Ltd.
00007  * Author: Matt Zimmerman <mdz@ubuntu.com>
00008  *
00009  * This program is free software; you can redistribute it and/or modify it
00010  * under the terms of the GNU General Public License as published by the
00011  * Free Software Foundation; either version 2 of the License, or (at your
00012  * option) any later version.  See http://www.gnu.org/copyleft/gpl.html for
00013  * the full text of the license.
00014  */
00015 
00016 import java.io.*;
00017 import java.util.HashMap;
00018 
00019 public class ApportUncaughtExceptionHandler
00020        implements java.lang.Thread.UncaughtExceptionHandler {
00021 
00022        /* Write out an apport problem report with details of the
00023      * exception, then print it in the usual canonical format */
00024        public void uncaughtException(Thread t, Throwable e) {
00025               //System.out.println("uncaughtException");
00026               if (e instanceof ThreadDeath)
00027                      return;
00028 
00029               HashMap problemReport = getProblemReport(t, e);
00030               //System.out.println("got problem report");
00031 
00032               try {
00033                      String handler_path = System.getenv("APPORT_JAVA_EXCEPTION_HANDLER");
00034                      if (handler_path == null)
00035                          handler_path = "/usr/share/apport/java_uncaught_exception";
00036                      Process p = new ProcessBuilder(handler_path).start();
00037                      //System.out.println("started process");
00038 
00039                      OutputStream os = p.getOutputStream();
00040                      writeProblemReport(os, problemReport);
00041                      //System.out.println("wrote problem report");
00042 
00043                      os.close();
00044 
00045                      try {
00046                             p.waitFor();
00047                      } catch (InterruptedException ignore) {
00048                             // ignored
00049                      }
00050 
00051               } catch (java.io.IOException ioe) {
00052                   System.out.println("could not call java_uncaught_exception");
00053               }
00054 
00055         System.err.print("Exception in thread \""
00056                          + t.getName() + "\" ");
00057         e.printStackTrace(System.err);
00058        }
00059 
00060        public HashMap getProblemReport(Thread t, Throwable e) {
00061               HashMap problemReport = new HashMap();
00062               
00063               StringWriter sw = new StringWriter();
00064               PrintWriter pw = new PrintWriter(sw);
00065               e.printStackTrace(pw);
00066               problemReport.put("StackTrace", sw.toString());
00067 
00068               problemReport.put("MainClassUrl", mainClassUrl(e));
00069 
00070               return problemReport;
00071        }
00072 
00073        public void writeProblemReport(OutputStream os, HashMap pr)
00074               throws IOException {
00075 
00076               StringWriter sw = new StringWriter();
00077               for(Object o : pr.keySet()) {
00078                      String key = (String)o;
00079                      String value = (String)pr.get(o);
00080                      sw.write(key);
00081                      sw.write("\0");
00082                      sw.write(value);
00083                      sw.write("\0");
00084               }
00085               os.write(sw.toString().getBytes());
00086        }
00087 
00088        public static String mainClassUrl(Throwable e) {
00089               StackTraceElement[] stacktrace = e.getStackTrace();
00090               String className = stacktrace[stacktrace.length-1].getClassName();
00091 
00092               if (!className.startsWith("/")) {
00093                      className = "/" + className;
00094               }
00095               className = className.replace('.', '/');
00096               className = className + ".class";
00097 
00098               java.net.URL classUrl =
00099                      new ApportUncaughtExceptionHandler().getClass().getResource(className);
00100 
00101               return classUrl.toString();
00102     }
00103 
00104        /* Install this handler as the default uncaught exception handler */
00105        public static void install() {
00106               Thread.setDefaultUncaughtExceptionHandler(new ApportUncaughtExceptionHandler());
00107        }
00108 }