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

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