com.crashlytics.tools.android_2.1.0

!= null)
      {
        AbxConstants.AbxFileType type = getFileType(ze);
        if (type != null)
        {
          binaryXml = IOUtils.toByteArray(zin);
          if (type == AbxConstants.AbxFileType.MANIFEST) {
            manifestBinaryXml = binaryXml;
          } else if (type == AbxConstants.AbxFileType.STRINGS) {
            stringsBinaryXml = binaryXml;
          }
        }
      }
    }
    catch (IOException e)
    {
      byte[] binaryXml;
      logW("Error opening APK file.", e);
      return null;
    }
    finally
    {
      IOUtils.closeQuietly(zin);
    }
    if (manifestBinaryXml == null)
    {
      logW("Could not find AndroidManifest.xml in APK.", null);
      return null;
    }
    if (stringsBinaryXml == null)
    {
      logW("Could not find resources file in APK.", null);
      return null;
    }
    AbxNode manifest;
    try
    {
      manifest = new AbxParser(manifestBinaryXml).parseManifest();
      if (manifest == null)
      {
        logW("AndroidManifest.xml is blank.", null);
        return null;
      }
    }
    catch (IOException e)
    {
      logW("Could not parse AndroidManifest.xml file.", e);
      return null;
    }
    String packageName = manifest.getAttribute("package");
    if (TextUtils.isEmpty(packageName))
    {
      logW("Could not extract package name from APK.", null);
      return null;
    }
    String buildVersion = manifest.getAttribute("versionCode");
    if (TextUtils.isEmpty(buildVersion))
    {
      logW("Could not extract build version from APK.", null);
      return null;
    }
    String displayVersion = manifest.getAttribute("versionName");
    if (TextUtils.isEmpty(displayVersion))
    {
      logW("Could not extract display version from APK.", null);
      return null;
    }
    AbxNode application = null;
    for (AbxNode node : manifest.getChildren()) {
      if ("application".equals(node.getName())) {
        application = node;
      }
    }
    if (application == null)
    {
      logW("Could not find <application> tag in APK manifest file.", null);
      return null;
    }
    String appNameOrId = application.getAttribute("label");
    if (TextUtils.isEmpty(appNameOrId))
    {
      logW("Could not extract application name from APK manifest file.", null);
      return null;
    }
    StringResourcesMap strings;
    try
    {
      strings = new AbxParser(stringsBinaryXml).parseResourceTable(new Utf16ParseStringStrategy());
      log("Extracted these strings: " + strings);
    }
    catch (IOException e)
    {
      logW("Could not parse resources file.", e);
      return null;
    }
    String appName = null;
    String instanceIdentifier = null;
    try
    {
      appName = getAppNameFrom(appNameOrId, strings);
      instanceIdentifier = strings.getStringValue("com.crashlytics.android.build_id");
      if (TextUtils.isEmpty(instanceIdentifier))
      {
        logW("Could not find Crashlytics Build ID in resources file.", null);
        throw new IllegalArgumentException();
      }
    }
    catch (IllegalArgumentException e)
    {
      try
      {
        strings = new AbxParser(stringsBinaryXml).parseResourceTable(new Utf8ParseStringStrategy());
        log("Extracted these strings: " + strings);
        appName = getAppNameFrom(appNameOrId, strings);
        instanceIdentifier = strings.getStringValue("com.crashlytics.android.build_id");
        if (TextUtils.isEmpty(instanceIdentifier))
        {
          logW("Could not find Crashlytics Build ID in resources file.", null);
          return null;
        }
      }
      catch (IOException ioe)
      {
        logW("Could not parse resources file.", e);
        return null;
      }
    }
    return new AppRelease(appName, packageName, instanceIdentifier, displayVersion, buildVersion);
  }
  
  private static String getAppNameFrom(String appNameOrId, StringResourcesMap strings)
  {
    try
    {
      int appId = Integer.valueOf(appNameOrId).intValue();
      if (!AbxUtils.verifyPackageIdFromResIdIsDefault(appId))
      {
        logW("Extracting app name from other than the application's own package is currently not supported.", null);
        
        throw new IllegalArgumentException();
      }
      int entryIndex = AbxUtils.entryIndexFromResId(appId);
      appNameOrId = strings.findStringValueByResId(appId);
      log("appNameOrId: " + appId + "; " + appNameOrId + "; " + entryIndex);
      if (TextUtils.isEmpty(appNameOrId))
      {
        logW("Could not find application name in resources file.", null);
        throw new IllegalArgumentException();
      }
      return appNameOrId;
    }
    catch (NumberFormatException nfe)
    {
      log("[ApkUtils] Encountered hard-coded app name in AndroidManifest.xml: " + appNameOrId);
      throw new IllegalArgumentException(nfe);
    }
  }
  
  private static AbxConstants.AbxFileType getFileType(ZipEntry ze)
  {
    if (!ze.isDirectory())
    {
      String name = ze.getName();
      if (name.equals("AndroidManifest.xml")) {
        return AbxConstants.AbxFileType.MANIFEST;
      }
      if (name.endsWith(".arsc")) {
        return AbxConstants.AbxFileType.STRINGS;
      }
    }
    return null;
  }
  
  public static void log(String s) {}
  
  public static void logW(String s, Throwable t)
  {
    DeveloperTools.logW("[ApkUtils] " + s, t);
  }
  
  public static void logE(String s, Throwable t)
  {
    DeveloperTools.logE("[ApkUtils] " + s, t);
  }
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.ApkUtils
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

public abstract interface Callback<T>
{
  public abstract void call(T paramT);
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.Callback
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

final class FileUtils$1
  implements Runnable
{
  FileUtils$1(InputStream paramInputStream, OutputStream paramOutputStream) {}
  
  public void run()
  {
    try
    {
      FileUtils.redirect(val$in, val$out);
    }
    catch (IOException e)
    {
      throw new RuntimeException(e);
    }
  }
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.FileUtils.1
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.util.Enumeration;
import java.util.Scanner;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.xml.sax.Locator;

public class FileUtils
{
  private static final int ZIP_BUFFER = 2048;
  
  public static boolean isCrashlyticsJar(String filename)
  {
    filename = filename.toLowerCase();
    return (filename.endsWith(".jar")) && (filename.startsWith("crashlytics-"));
  }
  
  public static void verifyDirectory(File path)
    throws IOException
  {
    if (!path.exists()) {
      path.mkdirs();
    }
    if ((!path.exists()) || (!path.isDirectory())) {
      throw new IOException("Could not create directory: " + path);
    }
  }
  
  public static void redirect(InputStream in, OutputStream out)
    throws IOException
  {
    byte[] buffer = new byte['?'];
    int len;
    while ((len = in.read(buffer)) != -1) {
      out.write(buffer, 0, len);
    }
    out.flush();
  }
  
  public static Thread redirectAsync(InputStream in, final OutputStream out)
  {
    Thread t = new Thread(new Runnable()
    {
      public void run()
      {
        try
        {
          FileUtils.redirect(val$in, out);
        }
        catch (IOException e)
        {
          throw new RuntimeException(e);
        }
      }
    }, "Crashlytics Async Redirect");
    
    t.start();
    return t;
  }
  
  public static void copyFile(File sourceFile, File destFile)
    throws IOException
  {
    FileChannel source = null;
    FileChannel destination = null;
    try
    {
      source = new FileInputStream(sourceFile).getChannel();
      destination = new FileOutputStream(destFile).getChannel();
      destination.transferFrom(source, 0L, source.size());
    }
    finally
    {
      if (source != null) {
        source.close();
      }
      if (destination != null) {
        destination.close();
      }
    }
  }
  
  public static void zip(File sourceFile, File destFile, boolean preservePath)
    throws IOException
  {
    if ((!sourceFile.exists()) || (!sourceFile.isFile())) {
      throw new IllegalArgumentException("Source file does not exist: " + sourceFile);
    }
    BufferedInputStream origin = new BufferedInputStream(new FileInputStream(sourceFile));
    FileOutputStream destOs = new FileOutputStream(destFile);
    ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(destOs));
    byte[] data = new byte['?'];
    
    String entryPath = preservePath ? sourceFile.toString() : sourceFile.getName();
    ZipEntry entry = new ZipEntry(entryPath);
    out.putNextEntry(entry);
    int count;
    while ((count = origin.read(data, 0, 2048)) != -1) {
      out.write(data, 0, count);
    }
    origin.close();
    out.close();
  }
  
  public static void unzip(File zipFile, File outputDir)
    throws IOException
  {
    ZipFile zipfile = new ZipFile(zipFile);
    Enumeration<? extends ZipEntry> e = zipfile.entries();
    while (e.hasMoreElements())
    {
      ZipEntry entry = (ZipEntry)e.nextElement();
      InputStream is = new BufferedInputStream(zipfile.getInputStream(entry));
      
      byte[] data = new byte['?'];
      FileOutputStream fos = new FileOutputStream(new File(outputDir, entry.getName()));
      BufferedOutputStream dest = new BufferedOutputStream(fos, 2048);
      int count;
      while ((count = is.read(data, 0, 2048)) != -1) {
        dest.write(data, 0, count);
      }
      dest.flush();
      dest.close();
      is.close();
    }
  }
  
  public static void unzipArchive(ZipFile archive, File outputDir)
    throws IOException
  {
    for (Enumeration<? extends ZipEntry> e = archive.entries(); e.hasMoreElements();)
    {
      ZipEntry entry = (ZipEntry)e.nextElement();
      unzipEntry(archive, entry, outputDir);
    }
  }
  
  private static void unzipEntry(ZipFile zipfile, ZipEntry entry, File outputDir)
    throws IOException
  {
    if (entry.isDirectory())
    {
      verifyDirectory(new File(outputDir, entry.getName()));
      return;
    }
    File outputFile = new File(outputDir, entry.getName());
    if (!outputFile.getParentFile().exists()) {
      verifyDirectory(outputFile.getParentFile());
    }
    BufferedInputStream inputStream = new BufferedInputStream(zipfile.getInputStream(entry));
    BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));
    try
    {
      IOUtils.copy(inputStream, outputStream);
    }
    catch (IOException e)
    {
      throw e;
    }
    finally
    {
      outputStream.close();
      inputStream.close();
    }
  }
  
  public static boolean isValidZip(File file)
  {
    ZipFile zipfile = null;
    try
    {
      zipfile = new ZipFile(file);
      return true;
    }
    catch (Exception e)
    {
      return 0;
    }
    finally
    {
      try
      {
        if (zipfile != null) {
          zipfile.close();
        }
      }
      catch (IOException e) {}
    }
  }
  
  public static String unzipToString(File sourceFile)
    throws IOException
  {
    if ((!sourceFile.exists()) || (!sourceFile.isFile())) {
      throw new FileNotFoundException("source file does not exist: " + sourceFile);
    }
    ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(sourceFile)));
    zis.getNextEntry();
    
    String fileContents = new Scanner(zis).useDelimiter("\\A").next();
    return fileContents;
  }
  
  public static String fileToString(File sourceFile)
    throws IOException
  {
    if ((!sourceFile.exists()) || (!sourceFile.isFile())) {
      throw new FileNotFoundException("source file does not exist: " + sourceFile);
    }
    return streamToString(new FileInputStream(sourceFile));
  }
  
  public static String streamToString(InputStream stream)
  {
    Scanner s = null;
    String contents = null;
    try
    {
      s = new Scanner(stream, "UTF8").useDelimiter("\\A");
      contents = s.hasNext() ? s.next() : "";
    }
    finally
    {
      if (s != null) {
        s.close();
      }
    }
    return contents;
  }
  
  public static int locatorCharacterOffset(InputStream stream, Locator locator)
    throws IOException
  {
    return characterOffset(stream, locator.getLineNumber() - 1, locator.getColumnNumber() - 1);
  }
  
  public static int characterOffset(InputStream stream, int lineNum, int column)
    throws IOException
  {
    BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
    int offset = characterOffset(reader, lineNum, column);
    return offset;
  }
  
  private static int characterOffset(BufferedReader reader, int targetLine, int targetColumn)
    throws IOException
  {
    int linesRead = 0;
    int columnsRead = 0;
    int totalOffset = 0;
    char lastChar = '\000';
    int charVal = -1;
    
    charVal = reader.read();
    while ((charVal != -1) && ((linesRead != targetLine) || (targetColumn != columnsRead)))
    {
      char thisChar = (char)charVal;
      if ((thisChar != '\n') && (lastChar == '\r'))
      {
        linesRead++;
        columnsRead = 0;
      }
      if (thisChar != '\r') {
        if (thisChar == '\n')
        {
          linesRead++;
          columnsRead = 0;
        }
        else
        {
          columnsRead++;
        }
      }
      lastChar = thisChar;
      totalOffset++;
      charVal = reader.read();
    }
    return totalOffset;
  }
  
  public static String unqualifiedClassname(String fullyQualifiedName)
  {
    if (fullyQualifiedName == null) {
      return null;
    }
    int lastDot = fullyQualifiedName.lastIndexOf(".");
    if (lastDot > 0) {
      return fullyQualifiedName.substring(lastDot + 1);
    }
    return fullyQualifiedName;
  }
  
  public static void deleteAndRemakeFolder(File folder)
    throws IOException
  {
    if (folder.exists()) {
      org.apache.commons.io.FileUtils.deleteDirectory(folder);
    }
    folder.mkdirs();
  }
  
  public static String getIdentifier(File file)
  {
    if (file == null) {
      throw new IllegalArgumentException("Crashlytics cannot create a unique identifier from a null file.");
    }
    String returnIdentifier;
    try
    {
      returnIdentifier = String.format("%s-%s", new Object[] { file.getName(), DigestUtils.shaHex(file.getCanonicalPath()) });
    }
    catch (IOException e)
    {
      returnIdentifier = String.format("%s-%s", new Object[] { file.getName(), DigestUtils.shaHex(file.getAbsolutePath()) });
    }
    return returnIdentifier;
  }
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.FileUtils
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

public enum GradleParser$SearchResult$Result
{
  FOUND,  NOT_FOUND_IN_REGION,  REACHED_EOF;
  
  private GradleParser$SearchResult$Result() {}
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.GradleParser.SearchResult.Result
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

public class GradleParser$SearchResult
{
  private Result _searchResult;
  private int _position;
  
  public static enum Result
  {
    FOUND,  NOT_FOUND_IN_REGION,  REACHED_EOF;
    
    private Result() {}
  }
  
  private GradleParser$SearchResult(Result searchResult, int position)
  {
    _searchResult = searchResult;
    _position = position;
  }
  
  public static SearchResult eof()
  {
    return new SearchResult(Result.REACHED_EOF, -1);
  }
  
  public static SearchResult notFound(int lastOffsetOfSearch)
  {
    if (lastOffsetOfSearch < 0) {
      throw new IllegalArgumentException("Last position of search was out of bounds, search expected non-negative search region");
    }
    return new SearchResult(Result.NOT_FOUND_IN_REGION, lastOffsetOfSearch);
  }
  
  public static SearchResult found(int lastIndexOfResult)
  {
    return new SearchResult(Result.FOUND, lastIndexOfResult);
  }
  
  public boolean wasFound()
  {
    return Result.FOUND == _searchResult;
  }
  
  public Result getResult()
  {
    return _searchResult;
  }
  
  public int getPosition()
  {
    return _position;
  }
  
  public String toString()
  {
    return "Search Result: " + _searchResult + " (" + _position + ")";
  }
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.GradleParser.SearchResult
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

public class GradleParser
{
  private GradleTokenizer _tokenizer;
  
  public GradleParser(GradleTokenizer tokenizer)
  {
    _tokenizer = tokenizer;
  }
  
  public static final String[] ANDROID_PLUGIN_STRINGS = { "apply", "plugin:", "'", "android", "'" };
  public static final String[] CRASHLYTICS_PLUGIN_STRINGS = { "apply", "plugin:", "'", "crashlytics", "'" };
  
  private int passThroughCodeBlock(int delta, boolean returnAfterExitBracket)
  {
    String token = _tokenizer.next();
    int length = token.length();
    String trimmedToken = token.trim();
    while (null != token)
    {
      if (trimmedToken.equals("{"))
      {
        int result = passThroughCodeBlock(delta + length, true);
        if (result == -1) {
          return -1;
        }
        delta = result;
      }
      else
      {
        if (trimmedToken.equals("}"))
        {
          if (returnAfterExitBracket) {
            return delta + length;
          }
          return delta;
        }
        delta += length;
      }
      token = _tokenizer.next();
      length = token.length();
      trimmedToken = token.trim();
    }
    return -1;
  }
  
  public SearchResult findTokenSet(String... tokens)
  {
    _tokenizer.reset();
    boolean found = false;
    String currentToken = _tokenizer.next();
    int currentItem = 0;
    int currentOffset = 0;
    while (!found)
    {
      if (currentItem == tokens.length)
      {
        found = true;
        break;
      }
      if (currentToken == null) {
        break;
      }
      if (tokens[currentItem].equals(currentToken.trim())) {
        currentItem++;
      } else {
        currentItem = 0;
      }
      currentOffset += currentToken.length();
      currentToken = _tokenizer.next();
    }
    if (found) {
      return SearchResult.found(currentOffset);
    }
    return SearchResult.eof();
  }
  
  public static class SearchResult
  {
    private Result _searchResult;
    private int _position;
    
    public static enum Result
    {
      FOUND,  NOT_FOUND_IN_REGION,  REACHED_EOF;
      
      private Result() {}
    }
    
    private SearchResult(Result searchResult, int position)
    {
      _searchResult = searchResult;
      _position = position;
    }
    
    public static SearchResult eof()
    {
      return new SearchResult(Result.REACHED_EOF, -1);
    }
    
    public static SearchResult notFound(int lastOffsetOfSearch)
    {
      if (lastOffsetOfSearch < 0) {
        throw new IllegalArgumentException("Last position of search was out of bounds, search expected non-negative search region");
      }
      return new SearchResult(Result.NOT_FOUND_IN_REGION, lastOffsetOfSearch);
    }
    
    public static SearchResult found(int lastIndexOfResult)
    {
      return new SearchResult(Result.FOUND, lastIndexOfResult);
    }
    
    public boolean wasFound()
    {
      return Result.FOUND == _searchResult;
    }
    
    public Result getResult()
    {
      return _searchResult;
    }
    
    public int getPosition()
    {
      return _position;
    }
    
    public String toString()
    {
      return "Search Result: " + _searchResult + " (" + _position + ")";
    }
  }
  
  public SearchResult findNestedClosures(String... searchItems)
    throws IOException
  {
    _tokenizer.reset();
    
    SearchResult result = findNestedClosuresInScope(Arrays.asList(searchItems));
    return result;
  }
  
  public SearchResult findNestedClosuresEnding(String... searchItems)
    throws IOException
  {
    _tokenizer.reset();
    
    SearchResult result = findNestedClosuresInScope(Arrays.asList(searchItems));
    if (result.wasFound())
    {
      int endOfBlock = passThroughCodeBlock(result.getPosition(), false);
      if (endOfBlock == -1) {
        result = SearchResult.eof();
      }
      result = SearchResult.found(endOfBlock);
    }
    return result;
  }
  
  private SearchResult findNestedClosuresInScope(List<String> identifiers)
    throws IOException
  {
    if (identifiers.size() == 0) {
      return SearchResult.found(_tokenizer.getPosition());
    }
    String head = (String)identifiers.get(0);
    List<String> tail = identifiers.subList(1, identifiers.size());
    SearchResult currentSearch = findClosureInScope(head);
    while (currentSearch.wasFound())
    {
      currentSearch = findNestedClosuresInScope(tail);
      if (GradleParser.SearchResult.Result.NOT_FOUND_IN_REGION != currentSearch.getResult()) {
        break;
      }
      currentSearch = findClosureInScope(head);
    }
    return currentSearch;
  }
  
  private SearchResult findClosureInScope(String identifier)
    throws IOException
  {
    int currentPosition = 0;
    String lastToken = null;
    String token = _tokenizer.next();
    while (token != null)
    {
      currentPosition += token.length();
      if (token.trim().equals("{"))
      {
        if ((token != null) && (!identifier.equals(lastToken.trim())))
        {
          currentPosition = passThroughCodeBlock(currentPosition, true);
        }
        else
        {
          if (token.trim().equals("}")) {
            return SearchResult.notFound(currentPosition);
          }
          return SearchResult.found(currentPosition);
        }
      }
      else {
        lastToken = token;
      }
      token = _tokenizer.next();
    }
    return SearchResult.eof();
  }
  
  private boolean findPropertyInScope(LinkedList<String> identifiers)
  {
    if (identifiers.isEmpty()) {
      return true;
    }
    boolean result = false;
    
    String token = _tokenizer.next();
    while (token != null)
    {
      String trimmedToken = token.trim();
      if (isEndOfClosure(trimmedToken))
      {
        result = false;
      }
      else if (isStartOfNewClosure(trimmedToken))
      {
        passThroughCodeBlock(0, true);
      }
      else if (isMethodInvocationOrPropertyDefinition(trimmedToken))
      {
        passThroughNamespace(0, token);
      }
      else if (trimmedToken.equals(identifiers.get(0)))
      {
        LinkedList<String> identifiersLeft = new LinkedList(identifiers);
        identifiersLeft.pop();
        if (identifiersLeft.size() == 0)
        {
          result = true;
        }
        else
        {
          boolean namespaceDeclarationMatchesTargetNamespace = extractIdentifiersFromNamespaceDeclaration(identifiersLeft);
          if (namespaceDeclarationMatchesTargetNamespace) {
            result = findPropertyInScope(identifiersLeft);
          }
        }
        if (result == true) {
          break;
        }
      }
      token = _tokenizer.next();
      if (token == null) {
        result = false;
      }
    }
    return result;
  }
  
  private boolean isMethodInvocationOrPropertyDefinition(String trimmedToken)
  {
    return ".".equals(trimmedToken);
  }
  
  private boolean isEndOfClosure(String trimmedToken)
  {
    return "}".equals(trimmedToken);
  }
  
  private boolean isStartOfNewClosure(String trimmedToken)
  {
    return "{".equals(trimmedToken);
  }
  
  private boolean extractIdentifiersFromNamespaceDeclaration(LinkedList<String> identifiersToExtract)
  {
    for (;;)
    {
      if (identifiersToExtract.size() == 0) {
        return true;
      }
      boolean nextTokenIsNamespace = _tokenizer.peek().trim().equals(".");
      if (nextTokenIsNamespace)
      {
        _tokenizer.next();
        boolean nextTokenMatchesNextIdentifier = _tokenizer.peek().trim().equals(identifiersToExtract.get(0));
        if (nextTokenMatchesNextIdentifier)
        {
          identifiersToExtract.pop();
          _tokenizer.next();
        }
        else
        {
          _tokenizer.next();
          return false;
        }
      }
      else
      {
        if (_tokenizer.peek().trim().equals("{"))
        {
          _tokenizer.next();
          return true;
        }
        return false;
      }
    }
  }
  
  private int passThroughNamespace(int currentPosition, String lastToken)
  {
    String token = _tokenizer.peek();
    while ((token != null) && (
      (".".equals(lastToken.trim())) || (".".equals(token.trim()))))
    {
      _tokenizer.next();
      currentPosition += token.length();
      
      lastToken = token;
      token = _tokenizer.peek();
    }
    return currentPosition;
  }
  
  public boolean isAndroidGradleProject()
  {
    return findTokenSet(ANDROID_PLUGIN_STRINGS).wasFound();
  }
  
  public SearchResult findProperty(String... propertyPath)
  {
    _tokenizer.reset();
    if (findPropertyInScope(new LinkedList(Arrays.asList(propertyPath)))) {
      return SearchResult.found(_tokenizer.getPosition());
    }
    return SearchResult.notFound(_tokenizer.getPosition());
  }
  
  public List<String> getStringListProperty(String... propertyPath)
  {
    _tokenizer.reset();
    SearchResult result = findProperty(propertyPath);
    if (result.wasFound())
    {
      removeAnyAssignments();
      return getList();
    }
    return null;
  }
  
  public String getStringProperty(String... propertyPath)
  {
    _tokenizer.reset();
    SearchResult result = findProperty(propertyPath);
    if (result.wasFound())
    {
      removeAnyAssignments();
      return _tokenizer.extractString();
    }
    return null;
  }
  
  private void removeAnyAssignments()
  {
    String next = _tokenizer.peek().trim();
    if (next.equals("=")) {
      _tokenizer.next();
    }
  }
  
  private List<String> getList()
  {
    String next = _tokenizer.next();
    List<String> item = new LinkedList();
    if (next.trim().equals("[")) {
      while (next != null)
      {
        String trimmedNext = next.trim();
        if (trimmedNext.equals("]"))
        {
          _tokenizer.next();
          break;
        }
        if (trimmedNext.equals(",")) {
          _tokenizer.next();
        }
        String nextString = _tokenizer.extractString();
        if (nextString == null) {
          break;
        }
        item.add(nextString);
        
        next = _tokenizer.peek();
      }
    }
    return item;
  }
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.GradleParser
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

public enum GradleTokenizer$QuoteType
{
  SINGLE_QUOTES("'"),  DOUBLE_QUOTES("\""),  TRIPLE_QUOTES("\"\"\"");
  
  private String _quoteString;
  
  private GradleTokenizer$QuoteType(String quoteString)
  {
    _quoteString = quoteString;
  }
  
  public boolean matches(String possibleQuoteString)
  {
    return _quoteString.equals(possibleQuoteString);
  }
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.GradleTokenizer.QuoteType
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

import java.io.File;
import java.io.IOException;

public class GradleTokenizer
{
  private final String _data;
  
  public static enum QuoteType
  {
    SINGLE_QUOTES("'"),  DOUBLE_QUOTES("\""),  TRIPLE_QUOTES("\"\"\"");
    
    private String _quoteString;
    
    private QuoteType(String quoteString)
    {
      _quoteString = quoteString;
    }
    
    public boolean matches(String possibleQuoteString)
    {
      return _quoteString.equals(possibleQuoteString);
    }
  }
  
  private int _cachedCurrentPosition = 0;
  private int _cachedNumToIncludeInNextToken = 0;
  private int _currentNumToIncludeInNextToken = 0;
  private String _cachedNext = null;
  private int _currentPosition = 0;
  
  public GradleTokenizer(String data)
  {
    _data = data;
    reset();
  }
  
  public static GradleTokenizer create(File buildFile)
    throws IOException
  {
    return new GradleTokenizer(FileUtils.fileToString(buildFile));
  }
  
  public int getPosition()
  {
    return _currentPosition;
  }
  
  public String getContents()
  {
    return _data;
  }
  
  public void reset()
  {
    setPosition(0);
  }
  
  public void setPosition(int newPosition)
  {
    _cachedCurrentPosition = newPosition;
    _cachedNumToIncludeInNextToken = 0;
    _currentPosition = newPosition;
    _currentNumToIncludeInNextToken = 0;
    cacheNext();
  }
  
  private static final String[] SPECIAL_TOKENS = { "[", "]", "{", "}", "//", "/*", "*/", ".", "=", "\"\"\"", "\"", "'" };
  
  public String peek()
  {
    return _cachedNext;
  }
  
  public String next()
  {
    String previousVal = _cachedNext;
    _currentPosition = _cachedCurrentPosition;
    _currentNumToIncludeInNextToken = _cachedNumToIncludeInNextToken;
    cacheNext();
    return previousVal;
  }
  
  public void cacheNext()
  {
    int startPosition = _cachedCurrentPosition;
    boolean hasReadContent = false;
    for (;;)
    {
      if (_cachedNumToIncludeInNextToken > 0)
      {
        _cachedNumToIncludeInNextToken -= 1;
        _cachedCurrentPosition += 1;
        if (_cachedNumToIncludeInNextToken == 0) {
          break;
        }
      }
      else
      {
        if (_data.length() <= _cachedCurrentPosition) {
          break;
        }
        char c = _data.charAt(_cachedCurrentPosition);
        if (Character.isWhitespace(c))
        {
          if (hasReadContent) {
            break;
          }
          _cachedCurrentPosition += 1;
        }
        else
        {
          String[] arr$ = SPECIAL_TOKENS;int len$ = arr$.length;
          for (int i$ = 0;; i$++)
          {
            if (i$ >= len$) {
              break label202;
            }
            String specialToken = arr$[i$];
            int tokenLen = specialToken.length();
            if (_data.length() + 1 > _cachedCurrentPosition + tokenLen)
            {
              String stringAtPos = _data.substring(_cachedCurrentPosition, _cachedCurrentPosition + tokenLen);
              if (stringAtPos.equals(specialToken))
              {
                _cachedNumToIncludeInNextToken = tokenLen;
                if (!hasReadContent) {
                  break;
                }
                break label217;
              }
            }
          }
          label202:
          hasReadContent = true;
          _cachedCurrentPosition += 1;
        }
      }
    }
    label217:
    if (_cachedCurrentPosition - startPosition == 0) {
      _cachedNext = null;
    } else {
      _cachedNext = _data.substring(startPosition, _cachedCurrentPosition);
    }
  }
  
  public String extractString()
  {
    String next = next().trim();
    
    QuoteType stringType = null;
    if (QuoteType.DOUBLE_QUOTES.matches(next)) {
      stringType = QuoteType.DOUBLE_QUOTES;
    } else if (QuoteType.SINGLE_QUOTES.matches(next)) {
      stringType = QuoteType.SINGLE_QUOTES;
    } else if (QuoteType.TRIPLE_QUOTES.matches(next)) {
      stringType = QuoteType.TRIPLE_QUOTES;
    } else {
      return null;
    }
    int initialPosition = _currentPosition;
    int currentPosition = _currentPosition;
    boolean escaping = false;
    int charactersOfStringEndingRead = 0;
    while (currentPosition < _data.length())
    {
      char currentChar = _data.charAt(currentPosition);
      currentPosition++;
      if (escaping)
      {
        escaping = false;
      }
      else
      {
        if ((currentChar == '\'') && (QuoteType.SINGLE_QUOTES.equals(stringType)))
        {
          charactersOfStringEndingRead++;
          break;
        }
        if ((currentChar == '"') && (QuoteType.DOUBLE_QUOTES.equals(stringType)))
        {
          charactersOfStringEndingRead++;
          break;
        }
        if ((currentChar == '"') && (QuoteType.TRIPLE_QUOTES.equals(stringType)))
        {
          charactersOfStringEndingRead++;
          if (charactersOfStringEndingRead == 3) {
            break;
          }
        }
        else if (currentChar == '\\')
        {
          charactersOfStringEndingRead = 0;
          escaping = true;
        }
        else
        {
          charactersOfStringEndingRead = 0;
        }
      }
    }
    int stringEnding = currentPosition - charactersOfStringEndingRead;
    return _data.substring(initialPosition, stringEnding);
  }
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.GradleTokenizer
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

import java.util.StringTokenizer;

public class GradleUtils
{
  public static String getTabs(int numTabs)
  {
    StringBuilder b = new StringBuilder();
    for (int i = 0; i < numTabs; i++) {
      b.append("    ");
    }
    return b.toString();
  }
  
  public static String indentString(String code, int tabs)
  {
    String tabbedString = "";
    StringTokenizer s = new StringTokenizer(code, "\n", true);
    
    int count = s.countTokens();
    for (int i = 0; i < count / 2; i++) {
      tabbedString = tabbedString + getTabs(tabs) + s.nextToken() + s.nextToken();
    }
    if (count % 2 == 1) {
      tabbedString = tabbedString + getTabs(tabs) + s.nextToken();
    }
    return tabbedString;
  }
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.GradleUtils
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

public class IdenticalPair<A>
  extends Pair<A, A>
{
  public IdenticalPair(A fst, A snd)
  {
    super(fst, snd);
  }
  
  public static <A> IdenticalPair<A> identicalPairOf(A fst, A snd)
  {
    return new IdenticalPair(fst, snd);
  }
  
  public static <A> IdenticalPair<A> identicalPairOf(A fst, A snd, boolean reversed)
  {
    return reversed ? new IdenticalPair(snd, fst) : new IdenticalPair(fst, snd);
  }
  
  public IdenticalPair<A> cloneSwapped()
  {
    return new IdenticalPair(snd, fst);
  }
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.IdenticalPair
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

import java.util.Comparator;

final class JarUtils$1
  implements Comparator<String>
{
  public int compare(String v1, String v2)
  {
    String[] v1parts = v1.split("\\.", 4);
    String[] v2parts = v2.split("\\.", 4);
    for (int i = 0; i < 3; i++)
    {
      int v1x = Integer.parseInt(v1parts[i]);
      int v2x = Integer.parseInt(v2parts[i]);
      if (v1x < v2x) {
        return -1;
      }
      if (v1x > v2x) {
        return 1;
      }
    }
    String v1q = v1parts.length > 3 ? v1parts[3] : "";
    String v2q = v2parts.length > 3 ? v2parts[3] : "";
    return v1q.compareTo(v2q);
  }
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.JarUtils.1
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

import java.util.Comparator;
import java.util.jar.Manifest;

final class JarUtils$2
  implements Comparator<Manifest>
{
  JarUtils$2(String paramString) {}
  
  public int compare(Manifest m1, Manifest m2)
  {
    return JarUtils.VERSION_STRING_COMPARATOR.compare(JarUtils.getVersion(m1, val$attributeKey), JarUtils.getVersion(m2, val$attributeKey));
  }
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.JarUtils.2
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

import com.crashlytics.tools.android.DeveloperTools;
import java.io.File;
import java.util.Comparator;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

public class JarUtils
{
  private static final String VERSION_ATTRIBUTE = "Specification-Version";
  public static final Comparator<String> VERSION_STRING_COMPARATOR = new Comparator()
  {
    public int compare(String v1, String v2)
    {
      String[] v1parts = v1.split("\\.", 4);
      String[] v2parts = v2.split("\\.", 4);
      for (int i = 0; i < 3; i++)
      {
        int v1x = Integer.parseInt(v1parts[i]);
        int v2x = Integer.parseInt(v2parts[i]);
        if (v1x < v2x) {
          return -1;
        }
        if (v1x > v2x) {
          return 1;
        }
      }
      String v1q = v1parts.length > 3 ? v1parts[3] : "";
      String v2q = v2parts.length > 3 ? v2parts[3] : "";
      return v1q.compareTo(v2q);
    }
  };
  
  public static final Comparator<Manifest> getVersionComparator(String attributeKey)
  {
    new Comparator()
    {
      public int compare(Manifest m1, Manifest m2)
      {
        return JarUtils.VERSION_STRING_COMPARATOR.compare(JarUtils.getVersion(m1, val$attributeKey), JarUtils.getVersion(m2, val$attributeKey));
      }
    };
  }
  
  public static String getVersion(Manifest manifest, String attributesKey)
  {
    Attributes attrs = manifest.getAttributes(attributesKey);
    if (attrs != null) {
      return attrs.getValue("Specification-Version");
    }
    return null;
  }
  
  public static String extractManifestVersion(File jarFile, String attributesKey)
  {
    String thisVersion = null;
    if ((jarFile != null) && (jarFile.exists())) {
      try
      {
        thisVersion = getVersion(new JarFile(jarFile).getManifest(), attributesKey);
      }
      catch (Exception e)
      {
        DeveloperTools.logW("Exception while retrieving version from " + jarFile + ".", e);
        thisVersion = null;
      }
    }
    return thisVersion;
  }
  
  public static Manifest getMaybeManifest(File jarFile)
  {
    try
    {
      if (jarFile.exists()) {
        return new JarFile(jarFile).getManifest();
      }
    }
    catch (Exception e)
    {
      DeveloperTools.logW("Could not read manifest from " + jarFile, e);
    }
    return null;
  }
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.JarUtils
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

public abstract interface ListenableOutputStream$ProgressListener
{
  public abstract void bytesWritten(long paramLong);
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.utils.ListenableOutputStream.ProgressListener
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.utils;

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class ListenableOutputStream
  extends FilterOutputStream
{
  private final ProgressListener _listener;
  private long _transferred = 0L;
  
  public ListenableOutputStream(OutputStream out, ProgressListener listener)
  {
    super(out);
    _listener = listener;
  }
  
  public void write(byte[] b, int off, int len)
    throws IOException
  {
    out.write(b, off, len);
    _transferred += len;
    _listener.bytesWritten(_transferred);
  }
  
  public void write(int b)
    throws IOException
  {
    out.write(b);
    _transferred += 1L;
    _listener.bytesWritten(_
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

Further reading...

For more information on Java 1.5 Tiger, you may find Java 1.5 Tiger, A developer's Notebook by D. Flanagan and B. McLaughlin from O'Reilly of interest.

New!JAR listings


Copyright 2006-2019. Infinite Loop Ltd