You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LogUtils.java 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. * Copyright (c) 2006-2015 DMDirc Developers
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. * SOFTWARE.
  21. */
  22. package com.dmdirc.util;
  23. import com.dmdirc.logger.ErrorLevel;
  24. import ch.qos.logback.classic.Level;
  25. import ch.qos.logback.classic.spi.ILoggingEvent;
  26. import ch.qos.logback.classic.spi.IThrowableProxy;
  27. import ch.qos.logback.classic.spi.StackTraceElementProxy;
  28. import java.lang.reflect.Constructor;
  29. import java.lang.reflect.InvocationTargetException;
  30. import javax.annotation.Nonnull;
  31. import javax.annotation.Nullable;
  32. import org.slf4j.Marker;
  33. import org.slf4j.MarkerFactory;
  34. /**
  35. * Utility methods for logging in the client.
  36. */
  37. public final class LogUtils {
  38. public static final Marker USER_ERROR = MarkerFactory.getMarker("UserError");
  39. public static final Marker APP_ERROR = MarkerFactory.getMarker("AppError");
  40. public static final Marker FATAL_USER_ERROR = MarkerFactory.getMarker("FatalUserError");
  41. public static final Marker FATAL_APP_ERROR = MarkerFactory.getMarker("FatalAppError");
  42. private LogUtils() {
  43. }
  44. /**
  45. * Converts a SLF4J {@link Level} into a DMDirc {@link ErrorLevel}
  46. *
  47. * @param level Error to convert
  48. *
  49. * @return Converted error
  50. */
  51. @Nonnull
  52. public static ErrorLevel getErrorLevel(@Nonnull final Level level) {
  53. if (level.equals(Level.ERROR)) {
  54. return ErrorLevel.HIGH;
  55. } else if (level.equals(Level.WARN)) {
  56. return ErrorLevel.MEDIUM;
  57. } else if (level.equals(Level.INFO)) {
  58. return ErrorLevel.LOW;
  59. } else {
  60. return ErrorLevel.UNKNOWN;
  61. }
  62. }
  63. /**
  64. * Converts the {@link IThrowableProxy} from an SLF4J {@link ILoggingEvent} into a
  65. * {@link Throwable}.
  66. *
  67. * @param eventObject Event containing the {@link IThrowableProxy}
  68. *
  69. * @return {@link Throwable} representation of the {@link IThrowableProxy} or {@code null} if
  70. * there is no {@link IThrowableProxy} present.
  71. */
  72. @Nullable
  73. public static Throwable getThrowable(final ILoggingEvent eventObject) {
  74. if (eventObject.getThrowableProxy() == null) {
  75. return null;
  76. }
  77. try {
  78. return getThrowable(eventObject.getThrowableProxy());
  79. } catch (ReflectiveOperationException ex) {
  80. return new IllegalStateException("Error converting exception", ex);
  81. }
  82. }
  83. /**
  84. * Converts a SLF4J {@link IThrowableProxy} into a {@link Throwable}.
  85. *
  86. * @param proxy {@link IThrowableProxy} to convert
  87. *
  88. * @return {@link Throwable} representation of the {@link IThrowableProxy}
  89. *
  90. * @throws ReflectiveOperationException If an error ocurred creating the real {@link Throwable}
  91. */
  92. @Nonnull
  93. public static Throwable getThrowable(@Nonnull final IThrowableProxy proxy)
  94. throws ReflectiveOperationException {
  95. final Class<? extends Throwable> clazz = getThrowableClass(proxy.getClassName());
  96. Throwable throwable = null;
  97. if (proxy.getCause() == null) {
  98. // Just find a constructor that takes a string.
  99. final Constructor<? extends Throwable> ctor =
  100. clazz.getDeclaredConstructor(String.class);
  101. throwable = ctor.newInstance(proxy.getMessage());
  102. } else if (clazz == InvocationTargetException.class) {
  103. // We don't care about the InvocationTargetException, unwrap it.
  104. return getThrowable(proxy.getCause());
  105. } else {
  106. // Try and find a constructor that takes a string and a throwable.
  107. for (Constructor<?> ctor : clazz.getDeclaredConstructors()) {
  108. if (ctor.getParameterCount() == 2) {
  109. final Class<?>[] parameterTypes = ctor.getParameterTypes();
  110. if (parameterTypes[0] == String.class && parameterTypes[1] == Throwable.class) {
  111. throwable = (Throwable) ctor.newInstance(
  112. proxy.getMessage(), getThrowable(proxy.getCause()));
  113. break;
  114. } else if (parameterTypes[1] == String.class
  115. && parameterTypes[0] == Throwable.class) {
  116. throwable = (Throwable) ctor.newInstance(
  117. getThrowable(proxy.getCause()), proxy.getMessage());
  118. break;
  119. }
  120. }
  121. }
  122. if (throwable == null) {
  123. try {
  124. // Or maybe just a throwable?
  125. throwable = clazz.getConstructor(Throwable.class).newInstance(getThrowable(proxy.getCause()));
  126. } catch (NoSuchMethodException ex) {
  127. try {
  128. throwable = clazz.getConstructor(String.class).newInstance(proxy.getMessage());
  129. } catch (NoSuchMethodException ex2) {
  130. // *Shrug*
  131. throw new ReflectiveOperationException("Unable to find ctor of " + clazz);
  132. }
  133. }
  134. }
  135. }
  136. throwable.setStackTrace(getStackTraceElements(proxy.getStackTraceElementProxyArray()));
  137. return throwable;
  138. }
  139. /**
  140. * Converts an SLF4F {@link StackTraceElementProxy}[] into a {@link StackTraceElement}[].
  141. *
  142. * @param elements {@link StackTraceElementProxy}s to convert
  143. *
  144. * @return Non null {@link StackTraceElement}[] of the input
  145. */
  146. @Nonnull
  147. public static StackTraceElement[] getStackTraceElements(
  148. final StackTraceElementProxy... elements) {
  149. final StackTraceElement[] returnValue = new StackTraceElement[elements.length];
  150. for (int i = 0; i < elements.length; i++) {
  151. returnValue[i] = elements[i].getStackTraceElement();
  152. }
  153. return returnValue;
  154. }
  155. @SuppressWarnings("unchecked")
  156. private static Class<Throwable> getThrowableClass(final String string)
  157. throws ClassNotFoundException {
  158. return (Class<Throwable>) Class.forName(string);
  159. }
  160. }