com.crashlytics.tools.android_2.1.0

      for (int i = 0; i < metaDataNodes.getLength(); i++)
        {
          Element e = (Element)metaDataNodes.item(i);
          String name = e.getAttribute("android:name");
          String value = e.getAttribute("android:value");
          metaData.put(name, value);
        }
        NodeList usesPermissionNodes = manifestRoot.getElementsByTagName("uses-permission");
        for (int i = 0; i < usesPermissionNodes.getLength(); i++)
        {
          Element e = (Element)usesPermissionNodes.item(i);
          String permission = e.getAttribute("android:name");
          usesPermissions.add(permission);
        }
      }
      try
      {
        inputStream.close();
      }
      catch (IOException e)
      {
        throw new ManifestData.ManifestIOException("Crashlytics could not close the manifest input stream.");
      }
      versionCode = data.getVersionCode();
    }
    catch (Exception e)
    {
      throw new ManifestData.ManifestIOException("Crashlytics could not parse the manifest found at " + manifestPathOnDisk, e);
    }
    finally
    {
      try
      {
        inputStream.close();
      }
      catch (IOException e)
      {
        throw new ManifestData.ManifestIOException("Crashlytics could not close the manifest input stream.");
      }
    }
    Integer versionCode;
    ManifestData.Activity launcherActivity = data.getLauncherActivity();
    String launcherActivityName = launcherActivity == null ? null : launcherActivity.getName();
    String apiKey = (String)metaData.get("com.crashlytics.ApiKey");
    
    return new DefaultManifestData(resDir, applicationName, versionName, services, usesPermissions, metaData, iconName, applicationClass, packageName, versionCode, launcherActivityName, apiKey);
  }
  
  private static String findStringResourceInResRoot(String stringName, File resDir, String defaultValue)
  {
    String value = null;
    if (resDir.isDirectory()) {
      for (String folder : SEARCHED_RES_FOLDERS)
      {
        if (value != null) {
          break;
        }
        String folderName = folder;
        
        String[] matchingDirs = resDir.list(new FilenameFilter()
        {
          public boolean accept(File dir, String name)
          {
            return (dir.isDirectory()) && (val$folderName.equalsIgnoreCase(name));
          }
        });
        if ((matchingDirs != null) && (matchingDirs.length > 0)) {
          value = findStringResourceInResDir(stringName, new File(resDir, matchingDirs[0]));
        }
      }
    }
    return value == null ? defaultValue : value;
  }
  
  private static String findStringResourceInResDir(String stringName, File resDir)
  {
    String value = null;
    if (resDir.isDirectory())
    {
      File[] xmlFiles = resDir.listFiles(XML_FILES_FILTER);
      if (xmlFiles != null) {
        for (File f : xmlFiles)
        {
          if (value != null) {
            break;
          }
          value = findStringResourceInFile(stringName, f);
        }
      }
    }
    return value;
  }
  
  private static String findStringResourceInFile(String stringName, File resFile)
  {
    InputStream inputStream = null;
    try
    {
      inputStream = new BufferedInputStream(new FileInputStream(resFile));
      DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
      Document doc = docBuilder.parse(inputStream);
      
      Element resourcesRoot = doc.getDocumentElement();
      
      NodeList stringNodes = resourcesRoot.getElementsByTagName("string");
      for (int i = 0; i < stringNodes.getLength(); i++)
      {
        Node stringNode = stringNodes.item(i);
        String nodeName = ((Element)stringNode).getAttribute("name");
        if (stringName.equals(nodeName)) {
          return stringNode.getTextContent();
        }
      }
    }
    catch (Exception e)
    {
      DeveloperTools.logW("Crashlytics could not parse the resources file found at " + resFile.getAbsolutePath(), e);
    }
    finally
    {
      IOUtils.closeQuietly(inputStream);
    }
    return null;
  }
  
  public DefaultManifestData(File resDir, String applicationName, String versionName, Set<String> services, Set<String> usesPermissions, Hashtable<String, String> metaData, String iconName, String applicationClass, String packageName, Integer versionCodeOrNull, String launcherActivityName, String apiKey)
  {
    _resDir = resDir;
    _applicationName = applicationName;
    _versionName = versionName;
    _services = services;
    _usesPermissions = usesPermissions;
    _metaData = metaData;
    _iconName = iconName;
    _applicationClass = applicationClass;
    _packageName = packageName;
    _versionCodeOrNull = versionCodeOrNull;
    _launcherActivityName = launcherActivityName;
    _apiKey = apiKey;
  }
  
  protected DefaultManifestData()
  {
    this(null, null, null, null, null, null, null, null, null, null, null, null);
  }
  
  private static final FilenameFilter DRAWABLE_FOLDER_FILTER = new FilenameFilter()
  {
    public boolean accept(File dir, String name)
    {
      return (name.startsWith("drawable")) && (new File(dir, name).isDirectory());
    }
  };
  private static final FilenameFilter PNG_FILE_FILTER = new FilenameFilter()
  {
    public boolean accept(File dir, String name)
    {
      return name.toLowerCase().endsWith(".png");
    }
  };
  
  public File getLauncherIcon()
  {
    if ((_iconName == null) || (!_resDir.exists())) {
      return null;
    }
    int iconNameLength = _iconName.length() + ".png".length();
    for (File drawableDir : _resDir.listFiles(DRAWABLE_FOLDER_FILTER)) {
      for (String drawable : drawableDir.list(PNG_FILE_FILTER)) {
        if ((drawable.length() == iconNameLength) && (drawable.startsWith(_iconName))) {
          return new File(drawableDir.getAbsoluteFile(), drawable);
        }
      }
    }
    return null;
  }
  
  public String getApplicationName()
  {
    return _applicationName;
  }
  
  public Integer getVersionCodeOrNull()
  {
    return _versionCodeOrNull;
  }
  
  public String getVersionName()
  {
    return _versionName;
  }
  
  public boolean declaresService(String serviceName)
  {
    return _services.contains(serviceName);
  }
  
  public String getMainActivity()
  {
    return _launcherActivityName;
  }
  
  public String getApplicationClass()
  {
    return _applicationClass;
  }
  
  public Hashtable<String, String> getMetaData()
  {
    return _metaData;
  }
  
  public boolean usesPermission(String permission)
  {
    return _usesPermissions.contains(permission);
  }
  
  public String getPackageName()
  {
    return _packageName;
  }
  
  public String getApiKey()
  {
    return _apiKey;
  }
}

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

import java.io.File;
import java.io.IOException;
import java.util.List;

public abstract interface DeobfuscationManager
{
  public abstract void storeDeobfuscationFile(File paramFile, String paramString1, String paramString2)
    throws IOException;
  
  public abstract boolean hasCachedDeobfuscationFiles();
  
  public abstract List<File> getDeobfuscationFiles()
    throws IOException;
  
  public abstract File getDeobfuscationDirectory();
  
  public abstract File getDeobfuscationStorageDirectory();
}

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

import com.crashlytics.tools.android.DeveloperTools;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

class DeobsMetadata
{
  static final String DEOBS_EXTENSION = ".zip";
  static final String DEOBS_DATA_EXTENSION = ".meta";
  static final String PARAM_BUILD_ID = "resource[uuid]";
  static final String PARAM_DEOBS_FILE = "resource[file]";
  static final String PARAM_OBFUSCATOR_ID = "resource[vendor]";
  static final String PARAM_OBFUSCATOR_VERSION = "resource[vendor_version]";
  static final String PARAM_PACKAGE = "resource[bundle_identifier]";
  static final String PARAM_VERSION_CODE = "resource[version_number]";
  static final String PARAM_VERSION_NAME = "resource[short_version_number]";
  private String _buildId;
  private String _obfuscatorId = null;
  private String _obfuscatorVersion = null;
  private String _packageId = null;
  private int _versionCode = 0;
  private String _versionName = null;
  
  public DeobsMetadata() {}
  
  public DeobsMetadata(String buildId, File androidManifest)
    throws IOException
  {
    _buildId = buildId;
    
    ManifestData manifest = DefaultManifestData.createManifest(androidManifest);
    _packageId = manifest.getPackageName();
    Integer manifestVersionCode = manifest.getVersionCodeOrNull();
    if (manifestVersionCode == null)
    {
      DeveloperTools.logD("Crashlytics did not find a version code and is interpreting it to be 0 by default");
      _versionCode = 0;
    }
    else
    {
      _versionCode = manifestVersionCode.intValue();
    }
    _versionName = manifest.getVersionName();
  }
  
  public Map<String, String> toMap()
  {
    Map<String, String> props = new HashMap();
    if (_buildId != null) {
      props.put("resource[uuid]", _buildId);
    }
    if (_obfuscatorId != null) {
      props.put("resource[vendor]", _obfuscatorId);
    }
    if (_obfuscatorVersion != null) {
      props.put("resource[vendor_version]", _obfuscatorVersion);
    }
    if (_packageId != null) {
      props.put("resource[bundle_identifier]", _packageId);
    }
    props.put("resource[version_number]", Integer.toString(_versionCode));
    if (_versionName != null) {
      props.put("resource[short_version_number]", _versionName);
    }
    return props;
  }
  
  public void load(File file)
    throws IOException
  {
    JSONParser parser = new JSONParser();
    JSONObject props = null;
    try
    {
      props = (JSONObject)parser.parse(new FileReader(file));
    }
    catch (ParseException e)
    {
      throw new IOException("Exception while parsing JSON file: " + file, e);
    }
    _buildId = ((String)props.get("resource[uuid]"));
    _packageId = ((String)props.get("resource[bundle_identifier]"));
    String versionCodeStr = (String)props.get("resource[version_number]");
    if (versionCodeStr == null)
    {
      DeveloperTools.logD("Crashlytics did not find a version code and is interpreting it to be 0 by default");
      _versionCode = 0;
    }
    else
    {
      _versionCode = Integer.parseInt(versionCodeStr);
    }
    _versionName = ((String)props.get("resource[short_version_number]"));
    _obfuscatorId = ((String)props.get("resource[vendor]"));
    _obfuscatorVersion = ((String)props.get("resource[vendor_version]"));
  }
  
  public void store(File file)
    throws IOException
  {
    JSONObject props = new JSONObject();
    for (Map.Entry<String, String> entry : toMap().entrySet()) {
      props.put(entry.getKey(), entry.getValue());
    }
    FileWriter writer = new FileWriter(file);
    writer.write(props.toJSONString());
    writer.close();
  }
  
  public String getBuildId()
  {
    return _buildId;
  }
  
  public void setBuildId(String buildId)
  {
    _buildId = buildId;
  }
  
  public String getPackageId()
  {
    return _packageId;
  }
  
  public void setPackageId(String packageId)
  {
    _packageId = packageId;
  }
  
  public int getVersionCode()
  {
    return _versionCode;
  }
  
  public void setVersionCode(int versionCode)
  {
    _versionCode = versionCode;
  }
  
  public String getVersionName()
  {
    return _versionName;
  }
  
  public void setVersionName(String versionName)
  {
    _versionName = versionName;
  }
  
  public String getObfuscatorId()
  {
    return _obfuscatorId;
  }
  
  public void setObfuscatorId(String obfuscatorId)
  {
    _obfuscatorId = obfuscatorId;
  }
  
  public String getObfuscatorVersion()
  {
    return _obfuscatorVersion;
  }
  
  public void setObfuscatorVersion(String obfuscatorVersion)
  {
    _obfuscatorVersion = obfuscatorVersion;
  }
}

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

import com.crashlytics.api.WebApi;
import com.crashlytics.tools.utils.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Map;

public class DeobsUploader
{
  private static final String REQUEST_DEOBS_FORMAT = "%s/api/v1/%s/deobs";
  private final WebApi _webApi;
  
  public DeobsUploader(WebApi api)
  {
    _webApi = api;
  }
  
  public boolean uploadDeobfuscationFiles(DeobfuscationManager deobfuscationManager, String apiKey)
    throws IOException
  {
    List<File> deobsFiles = deobfuscationManager.getDeobfuscationFiles();
    int sentFiles = 0;
    File deobsStoreDir = deobfuscationManager.getDeobfuscationStorageDirectory();
    if (deobsStoreDir != null) {
      for (File deobsFile : deobfuscationManager.getDeobfuscationFiles())
      {
        boolean success = uploadDeobsFile(deobsFile, apiKey, deobsStoreDir);
        if (success) {
          sentFiles++;
        }
      }
    }
    return sentFiles == deobsFiles.size();
  }
  
  private boolean uploadDeobsFile(File deobsFile, String apiKey, File deobsStoreDir)
    throws IOException
  {
    String buildId = buildIdFromFilename(deobsFile);
    
    File deobsData = new File(deobsFile.getParent(), buildId + ".meta");
    DeobsMetadata meta = new DeobsMetadata();
    meta.load(deobsData);
    Map<String, String> params = meta.toMap();
    
    URL url = new URL(String.format("%s/api/v1/%s/deobs", new Object[] { _webApi.getBaseApiUrl(), apiKey }));
    boolean success = _webApi.sendFile(url, deobsFile, "application/zip", "resource[file]", params);
    if (success)
    {
      FileUtils.verifyDirectory(deobsStoreDir);
      if (!deobsData.renameTo(new File(deobsStoreDir, deobsData.getName()))) {
        deobsData.delete();
      }
      if (!deobsFile.renameTo(new File(deobsStoreDir, deobsFile.getName()))) {
        deobsFile.delete();
      }
    }
    return success;
  }
  
  private String buildIdFromFilename(File f)
  {
    String name = f.getName();
    int extensionIndex = name.lastIndexOf(".zip");
    return name.substring(0, extensionIndex);
  }
}

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

import com.crashlytics.api.WebApi.UploadProgressListener;

class DistributionUploader$1
  implements WebApi.UploadProgressListener
{
  DistributionUploader$1(DistributionUploader paramDistributionUploader) {}
  
  public void bytesWritten(long totalSize, long bytesSent) {}
}

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

import com.crashlytics.api.AppRelease;
import com.crashlytics.api.AuthenticationException;
import com.crashlytics.api.DistributionData;
import com.crashlytics.api.WebApi;
import com.crashlytics.api.WebApi.UploadProgressListener;
import com.crashlytics.tools.utils.ApkUtils;
import java.io.File;
import java.io.IOException;

public class DistributionUploader
{
  private final WebApi _webApi;
  
  public DistributionUploader(WebApi api)
  {
    _webApi = api;
  }
  
  public boolean uploadDistribution(String apkPath, String apiKey, String secretApiKey)
    throws IOException, AuthenticationException
  {
    File apkFile = new File(apkPath);
    long builtAtSeconds = apkFile.lastModified();
    
    AppRelease appRelease = ApkUtils.extractAppDataFromApk(apkFile);
    DistributionData distributionData = new DistributionData(apkFile, builtAtSeconds);
    
    _webApi.createDistribution(apiKey, secretApiKey, appRelease, distributionData, true, new WebApi.UploadProgressListener()
    {
      public void bytesWritten(long totalSize, long bytesSent) {}
    });
  }
}

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

import java.io.IOException;

public class ManifestData$ManifestIOException
  extends IOException
{
  public ManifestData$ManifestIOException(String userFriendlyMessage)
  {
    super(userFriendlyMessage);
  }
  
  public ManifestData$ManifestIOException(String userFriendlyMessage, Throwable stackTraceForTheLogs)
  {
    super(userFriendlyMessage, stackTraceForTheLogs);
  }
}

/* Location:
 * Qualified Name:     com.crashlytics.tools.android.project.ManifestData.ManifestIOException
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package com.crashlytics.tools.android.project;

import java.io.File;
import java.io.IOException;
import java.util.Hashtable;

public abstract interface ManifestData
{
  public static final String METADATA_API_KEY = "com.crashlytics.ApiKey";
  public static final String PERMISSION_INTERNET = "android.permission.INTERNET";
  
  public abstract String getApplicationName();
  
  public abstract File getLauncherIcon();
  
  public abstract Integer getVersionCodeOrNull();
  
  public abstract String getVersionName();
  
  public abstract boolean declaresService(String paramString);
  
  public abstract String getMainActivity();
  
  public abstract String getApplicationClass();
  
  public abstract Hashtable<String, String> getMetaData();
  
  public abstract boolean usesPermission(String paramString);
  
  public abstract String getPackageName();
  
  public abstract String getApiKey();
  
  public static class ManifestIOException
    extends IOException
  {
    public ManifestIOException(String userFriendlyMessage)
    {
      super();
    }
    
    public ManifestIOException(String userFriendlyMessage, Throwable stackTraceForTheLogs)
    {
      super(stackTraceForTheLogs);
    }
  }
}

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

import com.crashlytics.tools.android.onboard.Code;
import com.crashlytics.tools.android.onboard.FileCode;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.FileUtils;

public class ManifestFileProvider
  implements ManifestProvider
{
  private final File _manifestFile;
  
  public ManifestFileProvider(File manifestFile)
  {
    _manifestFile = manifestFile;
  }
  
  public InputStream getManifestStream()
    throws ManifestData.ManifestIOException
  {
    try
    {
      return new BufferedInputStream(new FileInputStream(_manifestFile));
    }
    catch (FileNotFoundException e)
    {
      throw new ManifestData.ManifestIOException("Crashlytics could not find the manifest. Not found at " + _manifestFile.getAbsolutePath());
    }
  }
  
  public File getManifestFile()
  {
    return _manifestFile;
  }
  
  public Code getManifestCode()
    throws ManifestData.ManifestIOException
  {
    return new FileCode(getManifestFile());
  }
  
  public String getManifestString()
    throws ManifestData.ManifestIOException
  {
    try
    {
      return FileUtils.readFileToString(_manifestFile);
    }
    catch (IOException e)
    {
      throw new ManifestData.ManifestIOException("Crashlytics could not read the manifest at" + _manifestFile.getAbsolutePath());
    }
  }
  
  public ManifestData getManifestData()
    throws ManifestData.ManifestIOException
  {
    return DefaultManifestData.createManifest(this);
  }
}

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

import com.crashlytics.tools.android.onboard.Code;
import java.io.File;
import java.io.InputStream;

public abstract interface ManifestProvider
{
  public abstract ManifestData getManifestData()
    throws ManifestData.ManifestIOException;
  
  public abstract String getManifestString()
    throws ManifestData.ManifestIOException;
  
  public abstract InputStream getManifestStream()
    throws ManifestData.ManifestIOException;
  
  public abstract File getManifestFile()
    throws ManifestData.ManifestIOException;
  
  public abstract Code getManifestCode()
    throws ManifestData.ManifestIOException;
}

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

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class ResourceHelper
{
  public static InputStream createEmptyResourceFileStream()
  {
    StringBuilder sb = new StringBuilder();
    sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
    sb.append("<resources>\n");
    sb.append("<!--\n");
    sb.append("  This file is automatically generated by Crashlytics to uniquely \n");
    sb.append("  identify individual builds of your Android application.\n");
    sb.append("\n");
    sb.append("  Do NOT modify, delete, or commit to source control!\n");
    sb.append("-->\n");
    sb.append("</resources>\n");
    
    return new ByteArrayInputStream(sb.toString().getBytes());
  }
  
  public static Element getBuildIdElement(Document doc)
  {
    NodeList strings = doc.getElementsByTagName("string");
    
    Element buildIdElement = null;
    for (int i = 0; i < strings.getLength(); i++)
    {
      Element el = (Element)strings.item(i);
      if ((el.hasAttribute("name")) && (el.getAttribute("name").equals("com.crashlytics.android.build_id")))
      {
        buildIdElement = el;
        break;
      }
    }
    return buildIdElement;
  }
  
  public static void writeInputStreamToFile(InputStream source, File dest)
    throws IOException
  {
    if (!dest.exists()) {
      dest.createNewFile();
    }
    BufferedReader reader = null;
    PrintWriter writer = null;
    try
    {
      reader = new BufferedReader(new InputStreamReader(source));
      writer = new PrintWriter(dest);
      String line;
      while ((line = reader.readLine()) != null) {
        writer.println(line);
      }
    }
    finally
    {
      if (writer != null) {
        writer.close();
      }
      if (reader != null) {
        reader.close();
      }
    }
  }
}

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

import java.util.Properties;
import java.util.UUID;

public class ResourceUpdateData
{
  private final UUID _buildId;
  private final Properties _buildProperties;
  
  public ResourceUpdateData(UUID buildId, Properties buildProperties)
  {
    _buildId = buildId;
    _buildProperties = buildProperties;
  }
  
  public UUID getBuildId()
  {
    return _buildId;
  }
  
  public Properties getBuildProperties()
  {
    return _buildProperties;
  }
}

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

import com.crashlytics.tools.android.DeveloperTools;
import com.crashlytics.tools.utils.FileUtils;
import java.io.File;
import java.io.IOException;

public class StandardAndroidProject
  implements AndroidProject
{
  public static final String STANDARD_TYPE = "STANDARD_PROJECT";
  private final File _dataPath;
  private final ManifestData _manifestData;
  private final File _manifestFile;
  private final File _rootPath;
  private final File _propertyFilePath;
  private final File _resourceFile;
  private final File _assetsDir;
  private final String _projectType;
  private final String _buildSecret;
  private final boolean _modulesEnabled;
  private boolean hasVerified = false;
  private final String _apiKey;
  private final String _packageName;
  private final String _applicationName;
  private final File _launcherIcon;
  private final boolean _betaDistributionEnabled;
  
  public static File getPropertiesLoc(File projLoc)
  {
    return new File(projLoc, "crashlytics.properties");
  }
  
  public static File getDataDirectory(File projectRootDirectory)
  {
    return new File(DeveloperTools.CRASHLYTICS_PROJECTS_ROOT, FileUtils.getIdentifier(projectRootDirectory));
  }
  
  public static File getStringResourceLoc(File projectResDirectory)
  {
    if (!projectResDirectory.isDirectory()) {
      throw new IllegalArgumentException("Invalid resource path: " + projectResDirectory.getAbsolutePath());
    }
    File valuesPath = new File(projectResDirectory, "values");
    File resourceFile = new File(valuesPath, "com_crashlytics_export_strings.xml");
    return resourceFile;
  }
  
  public StandardAndroidProject(File projectPath, File manifestFile, File projectDataPath, File propertyFilePath, File resourceFile, File assetsDir, ManifestData manifestData, String projectType, String buildSecret, String apiKey, String packageName, String applicationName, File launcherIcon, boolean betaDistributionEnabled, boolean modulesEnabled)
  {
    _manifestFile = manifestFile;
    _manifestData = manifestData;
    _dataPath = projectDataPath;
    _rootPath = projectPath;
    _propertyFilePath = propertyFilePath;
    _resourceFile = resourceFile;
    _assetsDir = assetsDir;
    _projectType = projectType;
    _buildSecret = buildSecret;
    _apiKey = apiKey;
    _packageName = packageName;
    _applicationName = applicationName;
    _launcherIcon = launcherIcon;
    _betaDistributionEnabled = betaDistributionEnabled;
    _modulesEnabled = modulesEnabled;
  }
  
  protected synchronized void createDataDir()
    throws IOException
  {
    FileUtils.verifyDirectory(_dataPath);
  }
  
  public boolean isBetaDistributionEnabled()
  {
    return _betaDistributionEnabled;
  }
  
  public boolean isModulesEnabled()
  {
    return _modulesEnabled;
  }
  
  public File getManifestFile()
  {
    return _manifestFile;
  }
  
  public ManifestData getManifestData()
  {
    return _manifestData;
  }
  
  public File getLauncherIcon()
  {
    return _manifestData.getLauncherIcon();
  }
  
  public File getDataDirectory()
  {
    if (!hasVerified)
    {
      try
      {
        FileUtils.verifyDirectory(_dataPath);
      }
      catch (IOException e) {}
      hasVerified = true;
    }
    return _dataPath;
  }
  
  public File getResourceFile()
  {
    return _resourceFile;
  }
  
  public File getRootPath()
  {
    return _rootPath;
  }
  
  public File getAssetsDir()
  {
    return _assetsDir;
  }
  
  public String getApiKey()
  {
    return _apiKey;
  }
  
  public File getPropertiesPath()
  {
    return _propertyFilePath;
  }
  
  public String getProjectType()
  {
    return _projectType;
  }
  
  public String getBuildSecret()
  {
    return _buildSecret;
  }
  
  public String getPackageName()
  {
    return _packageName;
  }
  
  public String getApplicationName()
  {
    return _applicationName;
  }
  
  public File getIcon()
  {
    return _launcherIcon;
  }
  
  public String toString()
  {
    return "StandardAndroidProject{dataPath=" + _dataPath + ", manifestFile=" + _manifestFile + ", rootPath=" + _rootPath + ", propertyFilePath=" + _propertyFilePath + ", resourceFile=" + _resourceFile + ", assetsDir=" + _assetsDir + ", projectType='" + _projectType + '\'' + ", buildSecret='" + _buildSecret + '\'' + ", hasVerified=" + hasVerified + ", apiKey='" + _apiKey + '\'' + ", packageName='" + _packageName + '\'' + ", launcherIcon=" + _launcherIcon + ", betaDistributionEnabled=" + _betaDistributionEnabled + '}';
  }
}

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

import com.crashlytics.tools.utils.PropertiesUtils;
import java.io.File;
import java.io.IOException;
import java.util.Properties;

public class StandardAndroidProjectFactory
{
  public AndroidProject create(Properties properties)
    throws IOException
  {
    File projectPath = new File(properties.getProperty("projectPath", "."));
    File manifestPath;
    File manifestPath;
    if (properties.containsKey("androidManifest")) {
      manifestPath = new File(properties.getProperty("androidManifest"));
    } else {
      manifestPath = new File(projectPath, "AndroidManifest.xml");
    }
    File resPath;
    File resPath;
    if (properties.containsKey("androidRes")) {
      resPath = new File(properties.getProperty("androidRes"));
    } else {
      resPath = new File(projectPath, "res");
    }
    File assetsPath;
    File assetsPath;
    if (properties.containsKey("androidAssets")) {
      assetsPath = new File(properties.getProperty("androidAssets"));
    } else {
      assetsPath = new File(projectPath, "assets");
    }
    File propertiesFile = StandardAndroidProject.getPropertiesLoc(projectPath);
    if (properties.containsKey("properties")) {
      propertiesFile = new File(properties.getProperty("properties"));
    }
    AndroidProjectStructure structure = new AndroidProjectStructure(projectPath, manifestPath, resPath, assetsPath, StandardAndroidProject.getDataDirectory(projectPath), propertiesFile);
    
    AndroidProject project = create(structure, properties);
    return project;
  }
  
  public AndroidProject create(AndroidProjectStructure structure)
    throws IOException
  {
    return createTypedProject(structure, "STANDARD_PROJECT");
  }
  
  public AndroidProject create(AndroidProjectStructure structure, Properties properties)
    throws IOException
  {
    return createTypedProject(structure, properties, "STANDARD_PROJECT");
  }
  
  protected AndroidProject createTypedProject(AndroidProjectStructure structure, String projectType)
    throws IOException
  {
    Properties properties;
    try
    {
      properties = PropertiesUtils.read(structure.getPropertyFile());
    }
    catch (IOException e)
    {
      properties = new Properties();
    }
    return createTypedProject(structure, properties, projectType);
  }
  
  protected StandardAndroidProject createTypedProject(AndroidProjectStructure structure, Properties properties, String projectType)
    throws IOException
  {
    File projectPath = structure.getProjectRootDir();
    if (!projectPath.isDirectory()) {
      throw new IllegalArgumentException("Project path is not a directory: " + projectPath);
    }
    File manifestFile = structure.getManifestFile();
    File dataPath = structure.getProjectDataPath();
    File resDir = structure.getResourceDir();
    File assetsDir = structure.getAssetsDir();
    
    File resourceFile = StandardAndroidProject.getStringResourceLoc(resDir);
    ManifestData manifestData = DefaultManifestData.createManifest(new ManifestFileProvider(structure.getManifestFile()), resDir);
    if (!projectPath.isDirectory()) {
      throw new IllegalArgumentException("Project path is not a directory: " + projectPath);
    }
    String apiKey = manifestData.getApiKey();
    if (apiKey == null) {
      apiKey = properties.getProperty("apiKey");
    }
    String buildSecret = properties.getProperty("apiSecret");
    
    String packageName = properties.getProperty("renamedPackage");
    if ((packageName == null) || (packageName.isEmpty())) {
      packageName = manifestData.getPackageName();
    }
    String appName = manifestData.getApplicationName();
    if (appName == null) {
      appName = packageName;
    }
    File launcherIcon = manifestData.getLauncherIcon();
    
    boolean betaDistEnabled = Boolean.parseBoolean(properties.getProperty("betaDistributionEnabled"));
    
    boolean modulesEnabled = Boolean.parseBoolean(properties.getProperty("modulesEnabled"));
    
    return new StandardAndroidProject(projectPath, manifestFile, dataPath, structure.getPropertyFile(), resourceFile, assetsDir, manifestData, projectType, buildSecret, apiKey, packageName, appName, launcherIcon, betaDistEnabled, modulesEnabled);
  }
}

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

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.UUID;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

public class XmlBuildIdManager
  implements BuildIdManager
{
  private final DocumentBuilder _docBuilder;
  private final File _resourceFile;
  
  public static XmlBuildIdManager createManager(File resourceFile)
  {
    DocumentBuilder docBuilder;
    try
    {
      docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    }
    catch (ParserConfigurationException ex)
    {
      throw new RuntimeException(ex);
    }
    return new XmlBuildIdManager(resourceFile, docBuilder);
  }
  
  public XmlBuildIdManager(File resourceFile, DocumentBuilder docBuilder)
  {
    _resourceFile = resourceFile;
    _docBuilder = docBuilder;
  }
  
  public boolean fileExists()
  {
    return (_resourceFile.exists()) && (_resourceFile.isFile());
  }
  
  private void createEmptyResourceFile()
    throws IOException
  {
    File parentDir = _resourceFile.getParentFile();
    if ((parentDir.exists()) && (!parentDir.isDirectory())) {
      throw new IOException("Could not create resource file, path is not a directory: " + parentDir);
    }
    if ((!parentDir.exists()) && 
      (!parentDir.mkdir())) {
      throw new IOException("Could not create resource directory: " + parentDir);
    }
    ResourceHelper.writeInputStreamToFile(ResourceHelper.createEmptyResourceFileStream(), _resourceFile);
  }
  
  public void removeBuildId()
  {
    _resourceFile.delete();
  }
  
  public UUID updateBuildId()
    throws IOException
  {
    if (!fileExists()) {
      createEmptyResourceFile();
    }
    UUID toReturn = UUID.randomUUID();
    try
    {
      InputStream is = updateBuildId(new FileInputStream(_resourceFile), toReturn.toString());
      ResourceHelper.writeInputStreamToFile(is, _resourceFile);
    }
    catch (Exception e)
    {
      throw new RuntimeException("Crashlytics could not create: " + _resourceFile, e);
    }
    return toReturn;
  }
  
  private InputStream updateBuildId(InputStream source, String newId)
    throws SAXException, IOException
  {
    Document doc = _docBuilder.parse(source);
    Element buildIdElement = ResourceHelper.getBuildIdElement(doc);
    if (buildIdElement == null)
    {
      buildIdElement = doc.createElement("string");
      buildIdElement.setAttribute("name", "com.crashlytics.android.build_id");
      buildIdElement.setAttribute("translatable", "false");
      Node resources = doc.getFirstChild();
      resources.appendChild(buildIdElement);
    }
    buildIdElement.setTextContent(newId);
    
    InputStream toReturn = null;
    try
    {
      Transformer transformer = TransformerFactory.newInstance().newTransformer();
      transformer.setOutputProperty("indent", "yes");
      
      StreamResult result = new StreamResult(new StringWriter());
      DOMSource newSource = new DOMSource(doc);
      transformer.transform(newSource, result);
      
      toReturn = new ByteArrayInputStream(result.getWriter().toString().getBytes());
    }
    catch (Exception e)
    {
      throw new RuntimeException(e);
    }
    return toReturn;
  }
  
  public UUID getBuildId()
    throws IOException
  {
    if (!_resourceFile.exists()) {
      return null;
    }
    UUID toReturn = null;
    try
    {
      Document doc = _docBuilder.parse(_resourceFile);
      Element buildIdElement = ResourceHelper.getBuildIdElement(doc);
      if (buildIdElement != null) {
        toReturn = UUID.fromString(buildIdElement.getTextContent());
      }
    }
    catch (SAXException e)
    {
      throw new IOException(e);
    }
    return toReturn;
  }
  
  public File getResourceFile()
  {
    return _resourceFile;
  }
}

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

import com.crashlytics.api.AppRelease;
import com.crashlytics.tools.android.DeveloperTools;
import com.crashlytics.tools.utils.abx.AbxConstants.AbxFileType;
import com.crashlytics.tools.utils.abx.AbxNode;
import com.crashlytics.tools.utils.abx.AbxParser;
import com.crashlytics.tools.utils.abx.AbxUtils;
import com.crashlytics.tools.utils.abx.StringResourcesMap;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.apache.commons.io.IOUtils;
import org.apache.http.util.TextUtils;

public class ApkUtils
{
  private static final String TAG = "[ApkUtils] ";
  public static final boolean DEBUG_LOGGING = false;
  
  public static final AppRelease readBuildPropertiesFromApk(File apkFile)
  {
    ZipInputStream zin = null;
    ZipEntry ze = null;
    
    Properties buildProperties = new Properties();
    try
    {
      zin = new ZipInputStream(new FileInputStream(apkFile));
      while ((ze = zin.getNextEntry()) != null) {
        if (!ze.isDirectory())
        {
          String name = ze.getName();
          if ("assets/crashlytics-build.properties".equals(name))
          {
            buildProperties.load(zin);
            break;
          }
        }
      }
    }
    catch (Exception e)
    {
      logE("Crashlytics could not find assets/crashlytics-build.properties in the APK.", e);
    }
    finally
    {
      IOUtils.closeQuietly(zin);
    }
    if (!buildProperties.isEmpty())
    {
      String appName = buildProperties.getProperty("app_name");
      String packageName = buildProperties.getProperty("package_name");
      String instanceId = buildProperties.getProperty("build_id");
      String displayVersion = buildProperties.getProperty("version_name");
      String buildVersion = buildProperties.getProperty("version_code");
      
      return new AppRelease(appName, packageName, instanceId, displayVersion, buildVersion);
    }
    return null;
  }
  
  public static final AppRelease extractAppDataFromApk(File apk)
  {
    ZipInputStream zin = null;
    ZipEntry ze = null;
    
    byte[] manifestBinaryXml = null;
    byte[] stringsBinaryXml = null;
    try
    {
      zin = new ZipInputStream(new FileInputStream(apk));
      while ((ze = zin.getNextEntry()) 
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