gt:             for (int i = 0; i < array.length; i++) {
context: /**
   * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
   * <p/>
   * You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
   * copy, modify, and distribute this software in source code or binary form for use
   * in connection with the web services and APIs provided by Facebook.
   * <p/>
   * As with any software that integrates with the Facebook platform, your use of
   * this software is subject to the Facebook Developer Principles and Policies
   * [http://developers.facebook.com/policy/]. This copyright notice shall be
   * included in all copies or substantial portions of the software.
   * <p/>
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
   * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
   * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
   * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   */
  
  package com.facebook;
  
  import android.content.Context;
  import android.content.SharedPreferences;
  import android.os.Bundle;
  import android.util.Log;
  
  import com.facebook.internal.Logger;
  import com.facebook.internal.Utility;
  import com.facebook.internal.Validate;
  
  import org.json.JSONArray;
  import org.json.JSONException;
  import org.json.JSONObject;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Date;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
  final class LegacyTokenHelper {
  
      /**
       * The key used by AccessTokenCache to store the token value in the Bundle during
       * load and save.
       */
      public static final String TOKEN_KEY = "com.facebook.TokenCachingStrategy.Token";
  
      /**
       * The key used by AccessTokenCache to store the expiration date value in the Bundle
       * during load and save.
       */
      public static final String EXPIRATION_DATE_KEY = "com.facebook.TokenCachingStrategy.ExpirationDate";
  
      /**
       * The key used by AccessTokenCache to store the last refresh date value in the
       * Bundle during load and save.
       */
      public static final String LAST_REFRESH_DATE_KEY = "com.facebook.TokenCachingStrategy.LastRefreshDate";
  
      /**
       * The key used by AccessTokenCache to store an enum indicating the source of the token
       * in the Bundle during load and save.
       */
      public static final String TOKEN_SOURCE_KEY = "com.facebook.TokenCachingStrategy.AccessTokenSource";
  
      /**
       * The key used by AccessTokenCache to store the list of permissions granted by the
       * token in the Bundle during load and save.
       */
      public static final String PERMISSIONS_KEY = "com.facebook.TokenCachingStrategy.Permissions";
  
      /**
       * The key used by AccessTokenCache to store the list of permissions declined by the user in the token in
       * the Bundle during load and save.
       */
      public static final String DECLINED_PERMISSIONS_KEY = "com.facebook.TokenCachingStrategy.DeclinedPermissions";
  
      public static final String APPLICATION_ID_KEY = "com.facebook.TokenCachingStrategy.ApplicationId";
      public static final String DEFAULT_CACHE_KEY = "com.facebook.SharedPreferencesTokenCachingStrategy.DEFAULT_KEY";
      private static final long INVALID_BUNDLE_MILLISECONDS = Long.MIN_VALUE;
      private static final String IS_SSO_KEY = "com.facebook.TokenCachingStrategy.IsSSO";
      private static final String TAG = LegacyTokenHelper.class.getSimpleName();
  
      private static final String JSON_VALUE_TYPE = "valueType";
      private static final String JSON_VALUE = "value";
      private static final String JSON_VALUE_ENUM_TYPE = "enumType";
  
      private static final String TYPE_BOOLEAN = "bool";
      private static final String TYPE_BOOLEAN_ARRAY = "bool[]";
      private static final String TYPE_BYTE = "byte";
      private static final String TYPE_BYTE_ARRAY = "byte[]";
      private static final String TYPE_SHORT = "short";
      private static final String TYPE_SHORT_ARRAY = "short[]";
      private static final String TYPE_INTEGER = "int";
      private static final String TYPE_INTEGER_ARRAY = "int[]";
      private static final String TYPE_LONG = "long";
      private static final String TYPE_LONG_ARRAY = "long[]";
      private static final String TYPE_FLOAT = "float";
      private static final String TYPE_FLOAT_ARRAY = "float[]";
      private static final String TYPE_DOUBLE = "double";
      private static final String TYPE_DOUBLE_ARRAY = "double[]";
      private static final String TYPE_CHAR = "char";
      private static final String TYPE_CHAR_ARRAY = "char[]";
      private static final String TYPE_STRING = "string";
      private static final String TYPE_STRING_LIST = "stringList";
      private static final String TYPE_ENUM = "enum";
  
      private String cacheKey;
      private SharedPreferences cache;
  
      public LegacyTokenHelper(Context context) {
          this(context, null);
      }
  
      public LegacyTokenHelper(Context context, String cacheKey) {
          Validate.notNull(context, "context");
  
          this.cacheKey = Utility.isNullOrEmpty(cacheKey) ? DEFAULT_CACHE_KEY : cacheKey;
  
          // If the application context is available, use that. However, if it isn't
          // available (possibly because of a context that was created manually), use
          // the passed in context directly.
          Context applicationContext = context.getApplicationContext();
          context = applicationContext != null ? applicationContext : context;
  
          this.cache = context.getSharedPreferences(this.cacheKey, Context.MODE_PRIVATE);
      }
  
      public static boolean hasTokenInformation(Bundle bundle) {
          if (bundle == null) {
              return false;
          }
  
          String token = bundle.getString(TOKEN_KEY);
          if ((token == null) || (token.length() == 0)) {
              return false;
          }
  
          long expiresMilliseconds = bundle.getLong(EXPIRATION_DATE_KEY, 0L);
          return expiresMilliseconds != 0L;
  
      }
  
      public static String getToken(Bundle bundle) {
          Validate.notNull(bundle, "bundle");
          return bundle.getString(TOKEN_KEY);
      }
  
      public static void putToken(Bundle bundle, String value) {
          Validate.notNull(bundle, "bundle");
          Validate.notNull(value, "value");
          bundle.putString(TOKEN_KEY, value);
      }
  
      public static Date getExpirationDate(Bundle bundle) {
          Validate.notNull(bundle, "bundle");
          return getDate(bundle, EXPIRATION_DATE_KEY);
      }
  
      public static void putExpirationDate(Bundle bundle, Date value) {
          Validate.notNull(bundle, "bundle");
          Validate.notNull(value, "value");
          putDate(bundle, EXPIRATION_DATE_KEY, value);
      }
  
      public static long getExpirationMilliseconds(Bundle bundle) {
          Validate.notNull(bundle, "bundle");
          return bundle.getLong(EXPIRATION_DATE_KEY);
      }
  
      public static void putExpirationMilliseconds(Bundle bundle, long value) {
          Validate.notNull(bundle, "bundle");
          bundle.putLong(EXPIRATION_DATE_KEY, value);
      }
  
      public static Set<String> getPermissions(Bundle bundle) {
          Validate.notNull(bundle, "bundle");
          ArrayList<String> arrayList = bundle.getStringArrayList(PERMISSIONS_KEY);
          if (arrayList == null) {
              return null;
          }
          return new HashSet<String>(arrayList);
      }
  
      public static void putPermissions(Bundle bundle, Collection<String> value) {
          Validate.notNull(bundle, "bundle");
          Validate.notNull(value, "value");
  
          bundle.putStringArrayList(PERMISSIONS_KEY, new ArrayList<String>(value));
      }
  
      public static void putDeclinedPermissions(Bundle bundle, Collection<String> value) {
          Validate.notNull(bundle, "bundle");
          Validate.notNull(value, "value");
  
          bundle.putStringArrayList(DECLINED_PERMISSIONS_KEY, new ArrayList<String>(value));
      }
  
      public static AccessTokenSource getSource(Bundle bundle) {
          Validate.notNull(bundle, "bundle");
          if (bundle.containsKey(TOKEN_SOURCE_KEY)) {
              return (AccessTokenSource) bundle.getSerializable(TOKEN_SOURCE_KEY);
          } else {
              boolean isSSO = bundle.getBoolean(IS_SSO_KEY);
              return isSSO ? AccessTokenSource.FACEBOOK_APPLICATION_WEB : AccessTokenSource.WEB_VIEW;
          }
      }
  
      public static void putSource(Bundle bundle, AccessTokenSource value) {
          Validate.notNull(bundle, "bundle");
          bundle.putSerializable(TOKEN_SOURCE_KEY, value);
      }
  
      public static Date getLastRefreshDate(Bundle bundle) {
          Validate.notNull(bundle, "bundle");
          return getDate(bundle, LAST_REFRESH_DATE_KEY);
      }
  
      public static void putLastRefreshDate(Bundle bundle, Date value) {
          Validate.notNull(bundle, "bundle");
          Validate.notNull(value, "value");
          putDate(bundle, LAST_REFRESH_DATE_KEY, value);
      }
  
      public static long getLastRefreshMilliseconds(Bundle bundle) {
          Validate.notNull(bundle, "bundle");
          return bundle.getLong(LAST_REFRESH_DATE_KEY);
      }
  
      public static void putLastRefreshMilliseconds(Bundle bundle, long value) {
          Validate.notNull(bundle, "bundle");
          bundle.putLong(LAST_REFRESH_DATE_KEY, value);
      }
  
      public static String getApplicationId(Bundle bundle) {
          Validate.notNull(bundle, "bundle");
          return bundle.getString(APPLICATION_ID_KEY);
      }
  
      public static void putApplicationId(Bundle bundle, String value) {
          Validate.notNull(bundle, "bundle");
          bundle.putString(APPLICATION_ID_KEY, value);
      }
  
      static Date getDate(Bundle bundle, String key) {
          if (bundle == null) {
              return null;
          }
  
          long n = bundle.getLong(key, INVALID_BUNDLE_MILLISECONDS);
          if (n == INVALID_BUNDLE_MILLISECONDS) {
              return null;
          }
  
          return new Date(n);
      }
  
      static void putDate(Bundle bundle, String key, Date date) {
          bundle.putLong(key, date.getTime());
      }
  
      public Bundle load() {
          Bundle settings = new Bundle();
  
          Map<String, ?> allCachedEntries = cache.getAll();
  
          for (String key : allCachedEntries.keySet()) {
              try {
                  deserializeKey(key, settings);
              } catch (JSONException e) {
                  // Error in the cache. So consider it corrupted and return null
                  Logger.log(LoggingBehavior.CACHE, Log.WARN, TAG, "Error reading cached value for key: '" + key + "' -- " + e);
                  return null;
              }
          }
  
          return settings;
      }
  
      public void save(Bundle bundle) {
          Validate.notNull(bundle, "bundle");
  
          SharedPreferences.Editor editor = cache.edit();
  
          for (String key : bundle.keySet()) {
              try {
                  serializeKey(key, bundle, editor);
              } catch (JSONException e) {
                  // Error in the bundle. Don't store a partial cache.
                  Logger.log(LoggingBehavior.CACHE, Log.WARN, TAG, "Error processing value for key: '" + key + "' -- " + e);
  
                  // Bypass the commit and just return. This cancels the entire edit transaction
                  return;
              }
          }
          editor.apply();
      }
  
      /**
       * Clears out all token information stored in this cache.
       */
      public void clear() {
          cache.edit().clear().apply();
      }
  
      private void serializeKey(String key, Bundle bundle, SharedPreferences.Editor editor) throws JSONException {
          Object value = bundle.get(key);
          if (value == null) {
              // Cannot serialize null values.
              return;
          }
  
          String supportedType = null;
          JSONArray jsonArray = null;
          JSONObject json = new JSONObject();
  
          if (value instanceof Byte) {
              supportedType = TYPE_BYTE;
              json.put(JSON_VALUE, ((Byte) value).intValue());
          } else if (value instanceof Short) {
              supportedType = TYPE_SHORT;
              json.put(JSON_VALUE, ((Short) value).intValue());
          } else if (value instanceof Integer) {
              supportedType = TYPE_INTEGER;
              json.put(JSON_VALUE, ((Integer) value).intValue());
          } else if (value instanceof Long) {
              supportedType = TYPE_LONG;
              json.put(JSON_VALUE, ((Long) value).longValue());
          } else if (value instanceof Float) {
              supportedType = TYPE_FLOAT;
              json.put(JSON_VALUE, ((Float) value).doubleValue());
          } else if (value instanceof Double) {
              supportedType = TYPE_DOUBLE;
              json.put(JSON_VALUE, ((Double) value).doubleValue());
          } else if (value instanceof Boolean) {
              supportedType = TYPE_BOOLEAN;
              json.put(JSON_VALUE, ((Boolean) value).booleanValue());
          } else if (value instanceof Character) {
              supportedType = TYPE_CHAR;
              json.put(JSON_VALUE, value.toString());
          } else if (value instanceof String) {
              supportedType = TYPE_STRING;
              json.put(JSON_VALUE, value);
          } else if (value instanceof Enum<?>) {
              supportedType = TYPE_ENUM;
              json.put(JSON_VALUE, value.toString());
              json.put(JSON_VALUE_ENUM_TYPE, value.getClass().getName());
          } else {
              // Optimistically create a JSONArray. If not an array type, we can null
              // it out later
              jsonArray = new JSONArray();
              if (value instanceof byte[]) {
                  supportedType = TYPE_BYTE_ARRAY;
                  for (byte v : (byte[]) value) {
                      jsonArray.put((int) v);
                  }
              } else if (value instanceof short[]) {
                  supportedType = TYPE_SHORT_ARRAY;
                  for (short v : (short[]) value) {
                      jsonArray.put((int) v);
                  }
              } else if (value instanceof int[]) {
                  supportedType = TYPE_INTEGER_ARRAY;
                  for (int v : (int[]) value) {
                      jsonArray.put(v);
                  }
              } else if (value instanceof long[]) {
                  supportedType = TYPE_LONG_ARRAY;
                  for (long v : (long[]) value) {
                      jsonArray.put(v);
                  }
              } else if (value instanceof float[]) {
                  supportedType = TYPE_FLOAT_ARRAY;
                  for (float v : (float[]) value) {
                      jsonArray.put((double) v);
                  }
              } else if (value instanceof double[]) {
                  supportedType = TYPE_DOUBLE_ARRAY;
                  for (double v : (double[]) value) {
                      jsonArray.put(v);
                  }
              } else if (value instanceof boolean[]) {
                  supportedType = TYPE_BOOLEAN_ARRAY;
                  for (boolean v : (boolean[]) value) {
                      jsonArray.put(v);
                  }
              } else if (value instanceof char[]) {
                  supportedType = TYPE_CHAR_ARRAY;
                  for (char v : (char[]) value) {
                      jsonArray.put(String.valueOf(v));
                  }
              } else if (value instanceof List<?>) {
                  supportedType = TYPE_STRING_LIST;
                  @SuppressWarnings("unchecked") List<String> stringList = (List<String>) value;
                  for (String v : stringList) {
                      jsonArray.put((v == null) ? JSONObject.NULL : v);
                  }
              } else {
                  // Unsupported type. Clear out the array as a precaution even though
                  // it is redundant with the null supportedType.
                  jsonArray = null;
              }
          }
  
          if (supportedType != null) {
              json.put(JSON_VALUE_TYPE, supportedType);
              if (jsonArray != null) {
                  // If we have an array, it has already been converted to JSON. So use
                  // that instead.
                  json.putOpt(JSON_VALUE, jsonArray);
              }
  
              String jsonString = json.toString();
              editor.putString(key, jsonString);
          }
      }
  
      private void deserializeKey(String key, Bundle bundle) throws JSONException {
          String jsonString = cache.getString(key, "{}");
          JSONObject json = new JSONObject(jsonString);
  
          String valueType = json.getString(JSON_VALUE_TYPE);
  
          if (valueType.equals(TYPE_BOOLEAN)) {
              bundle.putBoolean(key, json.getBoolean(JSON_VALUE));
          } else if (valueType.equals(TYPE_BOOLEAN_ARRAY)) {
              JSONArray jsonArray = json.getJSONArray(JSON_VALUE);
              boolean[] array = new boolean[jsonArray.length()];
              for (int i = 0; i < array.length; i++) {
                  array[i] = jsonArray.getBoolean(i);
              }
              bundle.putBooleanArray(key, array);
          } else if (valueType.equals(TYPE_BYTE)) {
              bundle.putByte(key, (byte) json.getInt(JSON_VALUE));
          } else if (valueType.equals(TYPE_BYTE_ARRAY)) {
              JSONArray jsonArray = json.getJSONArray(JSON_VALUE);
              byte[] array = new byte[jsonArray.length()];
              for (int i = 0; i < array.length; i++) {
                  array[i] = (byte) jsonArray.getInt(i);
              }
              bundle.putByteArray(key, array);
          } else if (valueType.equals(TYPE_SHORT)) {
              bundle.putShort(key, (short) json.getInt(JSON_VALUE));
          } else if (valueType.equals(TYPE_SHORT_ARRAY)) {
              JSONArray jsonArray = json.getJSONArray(JSON_VALUE);
              short[] array = new short[jsonArray.length()];
              for (int i = 0; i < array.length; i++) {
                  array[i] = (short) jsonArray.getInt(i);
              }
              bundle.putShortArray(key, array);
          } else if (valueType.equals(TYPE_INTEGER)) {
              bundle.putInt(key, json.getInt(JSON_VALUE));
          } else if (valueType.equals(TYPE_INTEGER_ARRAY)) {
              JSONArray jsonArray = json.getJSONArray(JSON_VALUE);
              int[] array = new int[jsonArray.length()];
              for (int i = 0; i < array.length; i++) {
                  array[i] = jsonArray.getInt(i);
              }
              bundle.putIntArray(key, array);
          } else if (valueType.equals(TYPE_LONG)) {
              bundle.putLong(key, json.getLong(JSON_VALUE));
          } else if (valueType.equals(TYPE_LONG_ARRAY)) {
              JSONArray jsonArray = json.getJSONArray(JSON_VALUE);
              long[] array = new long[jsonArray.length()];
              for (int i = 0; i < array.length; i++) {
                  array[i] = jsonArray.getLong(i);
              }
              bundle.putLongArray(key, array);
          } else if (valueType.equals(TYPE_FLOAT)) {
              bundle.putFloat(key, (float) json.getDouble(JSON_VALUE));
          } else if (valueType.equals(TYPE_FLOAT_ARRAY)) {
              JSONArray jsonArray = json.getJSONArray(JSON_VALUE);
              float[] array = new float[jsonArray.length()];
  