content: /**
   * Copyright 2010-present Facebook.
   *
   * Licensed 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 com.facebook.internal;
  
  import android.util.Log;
  import com.facebook.LoggingBehavior;
  import com.facebook.Settings;
  
  import java.util.HashMap;
  import java.util.Map;
  
  /**
   * com.facebook.internal is solely for the use of other packages within the Facebook SDK for Android. Use of
   * any of the classes in this package is unsupported, and they may be modified or removed without warning at
   * any time.
   */
  public class Logger {
      public static final String LOG_TAG_BASE = "FacebookSDK.";
      private static final HashMap<String, String> stringsToReplace = new HashMap<String, String>();
  
      private final LoggingBehavior behavior;
      private final String tag;
      private StringBuilder contents;
      private int priority = Log.DEBUG;
  
      // Note that the mapping of replaced strings is never emptied, so it should be used only for things that
      // are not expected to be too numerous, such as access tokens.
      public synchronized static void registerStringToReplace(String original, String replace) {
          stringsToReplace.put(original, replace);
      }
  
      public synchronized static void registerAccessToken(String accessToken) {
          if (Settings.isLoggingBehaviorEnabled(LoggingBehavior.INCLUDE_ACCESS_TOKENS) == false) {
              registerStringToReplace(accessToken, "ACCESS_TOKEN_REMOVED");
          }
      }
  
      public static void log(LoggingBehavior behavior, String tag, String string) {
          log(behavior, Log.DEBUG, tag, string);
      }
  
      public static void log(LoggingBehavior behavior, String tag, String format, Object... args) {
          if (Settings.isLoggingBehaviorEnabled(behavior)) {
              String string = String.format(format, args);
              log(behavior, Log.DEBUG, tag, string);
          }
      }
  
      public static void log(LoggingBehavior behavior, int priority, String tag, String string) {
          if (Settings.isLoggingBehaviorEnabled(behavior)) {
              string = replaceStrings(string);
              if (tag.startsWith(LOG_TAG_BASE) == false) {
                  tag = LOG_TAG_BASE + tag;
              }
              Log.println(priority, tag, string);
  
              // Developer errors warrant special treatment by printing out a stack trace, to make both more noticeable,
              // and let the source of the problem be more easily pinpointed.
              if (behavior == LoggingBehavior.DEVELOPER_ERRORS) {
                  (new Exception()).printStackTrace();
              }
          }
      }
  
      private synchronized static String replaceStrings(String string) {
          for (Map.Entry<String, String> entry : stringsToReplace.entrySet()) {
              string = string.replace(entry.getKey(), entry.getValue());
          }
          return string;
      }
  
      public Logger(LoggingBehavior behavior, String tag) {
          Validate.notNullOrEmpty(tag, "tag");
  
          this.behavior = behavior;
          this.tag = LOG_TAG_BASE + tag;
          this.contents = new StringBuilder();
      }
  
      public int getPriority() {
          return priority;
      }
  
      public void setPriority(int value) {
          Validate.oneOf(value, "value", Log.ASSERT, Log.DEBUG, Log.ERROR, Log.INFO, Log.VERBOSE, Log.WARN);
  
          priority = value;
      }
  
      public String getContents() {
          return replaceStrings(contents.toString());
      }
  
      // Writes the accumulated contents, then clears contents to start again.
      public void log() {
          logString(contents.toString());
          contents = new StringBuilder();
      }
  
      // Immediately logs a string, ignoring any accumulated contents, which are left unchanged.
      public void logString(String string) {
          log(behavior, priority, tag, string);
      }
  
      public void append(StringBuilder stringBuilder) {
          if (shouldLog()) {
              contents.append(stringBuilder);
          }
      }
  
      public void append(String string) {
          if (shouldLog()) {
              contents.append(string);
          }
      }
  
      public void append(String format, Object... args) {
          if (shouldLog()) {
              contents.append(String.format(format, args));
          }
      }
  
      public void appendKeyValue(String key, Object value) {
          append("  %s:\t%s\n", key, value);
      }
  
      private boolean shouldLog() {
          return Settings.isLoggingBehaviorEnabled(behavior);
      }
  }
  