JAL-3026 srcjar files for VARNA and log4j
[jalview.git] / srcjar / org / apache / log4j / EnhancedThrowableRenderer.java
diff --git a/srcjar/org/apache/log4j/EnhancedThrowableRenderer.java b/srcjar/org/apache/log4j/EnhancedThrowableRenderer.java
new file mode 100644 (file)
index 0000000..c5b8d7b
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.log4j;
+
+import org.apache.log4j.spi.ThrowableRenderer;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.security.CodeSource;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Enhanced implementation of ThrowableRenderer.  Uses Throwable.getStackTrace
+ * if running on JDK 1.4 or later and delegates to DefaultThrowableRenderer.render
+ * on earlier virtual machines.
+ *
+ * @since 1.2.16
+ */
+public final class EnhancedThrowableRenderer implements ThrowableRenderer {
+    /**
+     * Throwable.getStackTrace() method.
+     */
+    private Method getStackTraceMethod;
+    /**
+     * StackTraceElement.getClassName() method.
+     */
+    private Method getClassNameMethod;
+
+
+    /**
+     * Construct new instance.
+     */
+    public EnhancedThrowableRenderer() {
+        try {
+            Class[] noArgs = null;
+            getStackTraceMethod = Throwable.class.getMethod("getStackTrace", noArgs);
+            Class ste = Class.forName("java.lang.StackTraceElement");
+            getClassNameMethod = ste.getMethod("getClassName", noArgs);
+        } catch(Exception ex) {
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String[] doRender(final Throwable throwable) {
+        if (getStackTraceMethod != null) {
+            try {
+                Object[] noArgs = null;
+                Object[] elements = (Object[]) getStackTraceMethod.invoke(throwable, noArgs);
+                String[] lines = new String[elements.length + 1];
+                lines[0] = throwable.toString();
+                Map classMap = new HashMap();
+                for(int i = 0; i < elements.length; i++) {
+                    lines[i+1] = formatElement(elements[i], classMap);
+                }
+                return lines;
+            } catch(Exception ex) {
+            }
+        }
+        return DefaultThrowableRenderer.render(throwable);
+    }
+
+    /**
+     * Format one element from stack trace.
+     * @param element element, may not be null.
+     * @param classMap map of class name to location.
+     * @return string representation of element.
+     */
+    private String formatElement(final Object element, final Map classMap) {
+        StringBuffer buf = new StringBuffer("\tat ");
+        buf.append(element);
+        try {
+            String className = getClassNameMethod.invoke(element, (Object[]) null).toString();
+            Object classDetails = classMap.get(className);
+            if (classDetails != null) {
+                buf.append(classDetails);
+            } else {
+                Class cls = findClass(className);
+                int detailStart = buf.length();
+                buf.append('[');
+                try {
+                    CodeSource source = cls.getProtectionDomain().getCodeSource();
+                    if (source != null) {
+                        URL locationURL = source.getLocation();
+                        if (locationURL != null) {
+                            //
+                            //   if a file: URL
+                            //
+                            if ("file".equals(locationURL.getProtocol())) {
+                                String path = locationURL.getPath();
+                                if (path != null) {
+                                    //
+                                    //  find the last file separator character
+                                    //
+                                    int lastSlash = path.lastIndexOf('/');
+                                    int lastBack = path.lastIndexOf(File.separatorChar);
+                                    if (lastBack > lastSlash) {
+                                        lastSlash = lastBack;
+                                    }
+                                    //
+                                    //  if no separator or ends with separator (a directory)
+                                    //     then output the URL, otherwise just the file name.
+                                    //
+                                    if (lastSlash <= 0 || lastSlash == path.length() - 1) {
+                                        buf.append(locationURL);
+                                    } else {
+                                        buf.append(path.substring(lastSlash + 1));
+                                    }
+                                }
+                            } else {
+                                buf.append(locationURL);
+                            }
+                        }
+                    }
+                } catch(SecurityException ex) {
+                }
+                buf.append(':');
+                Package pkg = cls.getPackage();
+                if (pkg != null) {
+                    String implVersion = pkg.getImplementationVersion();
+                    if (implVersion != null) {
+                        buf.append(implVersion);
+                    }
+                }
+                buf.append(']');
+                classMap.put(className, buf.substring(detailStart));
+            }
+        } catch(Exception ex) {
+        }
+        return buf.toString();
+    }
+
+    /**
+     * Find class given class name.
+     * @param className class name, may not be null.
+     * @return class, will not be null.
+     * @throws ClassNotFoundException thrown if class can not be found.
+     */
+    private Class findClass(final String className) throws ClassNotFoundException {
+     try {
+       return Thread.currentThread().getContextClassLoader().loadClass(className);
+     } catch (ClassNotFoundException e) {
+       try {
+         return Class.forName(className);
+       } catch (ClassNotFoundException e1) {
+          return getClass().getClassLoader().loadClass(className);
+      }
+    }
+  }
+
+}