content: package org.littleshoot.proxy.impl;
  
  import java.util.Arrays;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.slf4j.helpers.MessageFormatter;
  import org.slf4j.spi.LocationAwareLogger;
  
  /**
   * <p>
   * A helper class that logs messages for ProxyConnections. All it does is make
   * sure that the Channel and current state are always included in the log
   * messages (if available).
   * </p>
   *
   * <p>
   * Note that this depends on us using a LocationAwareLogger so that we can
   * report the line numbers of the caller rather than this helper class.
   * If the SLF4J binding does not provide a LocationAwareLogger, then a fallback
   * to Logger is provided.
   * </p>
   */
  class ProxyConnectionLogger {
      private final ProxyConnection connection;
      private final LogDispatch dispatch;
      private final Logger logger;
      private final String fqcn = this.getClass().getCanonicalName();
  
      public ProxyConnectionLogger(ProxyConnection connection) {
          this.connection = connection;
          final Logger lg = LoggerFactory.getLogger(connection
                  .getClass());
          if (lg instanceof LocationAwareLogger) {
              dispatch = new LocationAwareLogggerDispatch((LocationAwareLogger) lg);
          }
          else {
              dispatch = new LoggerDispatch();
          }
          logger = lg;
      }
  
      protected void error(String message, Object... params) {
          if (logger.isErrorEnabled()) {
              dispatch.doLog(LocationAwareLogger.ERROR_INT, message, params, null);
          }
      }
  
      protected void error(String message, Throwable t) {
          if (logger.isErrorEnabled()) {
              dispatch.doLog(LocationAwareLogger.ERROR_INT, message, null, t);
          }
      }
  
      protected void warn(String message, Object... params) {
          if (logger.isWarnEnabled()) {
              dispatch.doLog(LocationAwareLogger.WARN_INT, message, params, null);
          }
      }
  
      protected void warn(String message, Throwable t) {
          if (logger.isWarnEnabled()) {
              dispatch.doLog(LocationAwareLogger.WARN_INT, message, null, t);
          }
      }
  
      protected void info(String message, Object... params) {
          if (logger.isInfoEnabled()) {
              dispatch.doLog(LocationAwareLogger.INFO_INT, message, params, null);
          }
      }
  
      protected void info(String message, Throwable t) {
          if (logger.isInfoEnabled()) {
              dispatch.doLog(LocationAwareLogger.INFO_INT, message, null, t);
          }
      }
  
      protected void debug(String message, Object... params) {
          if (logger.isDebugEnabled()) {
              dispatch.doLog(LocationAwareLogger.DEBUG_INT, message, params, null);
          }
      }
  
      protected void debug(String message, Throwable t) {
          if (logger.isDebugEnabled()) {
              dispatch.doLog(LocationAwareLogger.DEBUG_INT, message, null, t);
          }
      }
  
      protected void log(int level, String message, Object... params) {
          if (level != LocationAwareLogger.DEBUG_INT || logger.isDebugEnabled()) {
              dispatch.doLog(level, message, params, null);
          }
      }
  
      protected void log(int level, String message, Throwable t) {
          if (level != LocationAwareLogger.DEBUG_INT || logger.isDebugEnabled()) {
              dispatch.doLog(level, message, null, t);
          }
      }
  
      private interface LogDispatch {
          void doLog(int level, String message, Object[] params, Throwable t);
      }
  
      private String fullMessage(String message) {
          String stateMessage = connection.getCurrentState().toString();
          if (connection.isTunneling()) {
              stateMessage += " {tunneling}";
          }
          String messagePrefix = "(" + stateMessage + ")";
          if (connection.channel != null) {
              messagePrefix = messagePrefix + " " + connection.channel;
          }
          return messagePrefix + ": " + message;
      }
  
      /**
       * Fallback dispatch if a LocationAwareLogger is not available from
       * the SLF4J LoggerFactory.
       */
      private class LoggerDispatch implements LogDispatch {
          @Override
          public void doLog(int level, String message, Object[] params, Throwable t) {
              String formattedMessage = fullMessage(message);
  
              final Object[] paramsWithThrowable;
  
              if (t != null) {
                  if (params == null) {
                      paramsWithThrowable = new Object[1];
                      paramsWithThrowable[0] = t;
                  } else {
                      paramsWithThrowable = Arrays.copyOf(params, params.length + 1);
                      paramsWithThrowable[params.length] = t;
                  }
              }
              else {
                  paramsWithThrowable = params;
              }
              switch (level) {
              case LocationAwareLogger.TRACE_INT:
                  logger.trace(formattedMessage, paramsWithThrowable);
                  break;
              case LocationAwareLogger.DEBUG_INT:
                  logger.debug(formattedMessage, paramsWithThrowable);
                  break;
              case LocationAwareLogger.INFO_INT:
                  logger.info(formattedMessage, paramsWithThrowable);
                  break;
              case LocationAwareLogger.WARN_INT:
                  logger.warn(formattedMessage, paramsWithThrowable);
                  break;
              case LocationAwareLogger.ERROR_INT:
              default:
                  logger.error(formattedMessage, paramsWithThrowable);
                  break;
              }
          }
      }
  
      /**
       * Dispatcher for a LocationAwareLogger.
       */
      private class LocationAwareLogggerDispatch implements LogDispatch {
  
          private LocationAwareLogger log;
  
          public LocationAwareLogggerDispatch(LocationAwareLogger log) {
              this.log = log;
          }
  
          @Override
          public void doLog(int level, String message, Object[] params, Throwable t) {
              String formattedMessage = fullMessage(message);
              if (params != null && params.length > 0) {
                  formattedMessage = MessageFormatter.arrayFormat(formattedMessage,
                          params).getMessage();
              }
              log.log(null, fqcn, level, formattedMessage, null, t);
          }
      }
  }