summaryrefslogtreecommitdiff
path: root/src/plugins/android/src/com/motorola/studio/android/obfuscate/ObfuscatorManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/android/src/com/motorola/studio/android/obfuscate/ObfuscatorManager.java')
-rw-r--r--src/plugins/android/src/com/motorola/studio/android/obfuscate/ObfuscatorManager.java378
1 files changed, 378 insertions, 0 deletions
diff --git a/src/plugins/android/src/com/motorola/studio/android/obfuscate/ObfuscatorManager.java b/src/plugins/android/src/com/motorola/studio/android/obfuscate/ObfuscatorManager.java
new file mode 100644
index 0000000..3bfaec2
--- /dev/null
+++ b/src/plugins/android/src/com/motorola/studio/android/obfuscate/ObfuscatorManager.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.motorola.studio.android.obfuscate;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Scanner;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.osgi.framework.Bundle;
+
+import com.motorola.studio.android.AndroidPlugin;
+import com.motorola.studio.android.common.log.StudioLogger;
+import com.motorola.studio.android.common.utilities.AndroidUtils;
+
+/**
+ * Manager to set Proguard files inside project
+ * Manipulates the file on <project_root>/default.properties
+ * Copy proguard.cfg
+ */
+public class ObfuscatorManager
+{
+
+ private static final String PROGUARD_PATH = "/files/proguard.cfg";
+
+ private static final String PROGUARD_SDK_PATH = "tools/lib/proguard.cfg";
+
+ private static final String PROGUARD_FILENAME = "proguard.cfg";
+
+ private static final String PROGUARD_CONFIG_STATEMENT = "proguard.config=proguard.cfg";
+
+ private static final String DEFAULT_PROPERTIES_FILENAME = "default.properties";
+
+ private static final String PROJECT_PROPERTIES_FILENAME = "project.properties";
+
+ private static final String NL = System.getProperty("line.separator");
+
+ /**
+ * Prepares the project with the Proguard settings
+ * to obfuscate when the project is exported in release mode
+ * @param project
+ * @param monitor
+ * @return
+ */
+ public static IStatus obfuscate(IProject project, IProgressMonitor monitor)
+ {
+ IStatus status = Status.OK_STATUS;
+
+ /*
+ * Project properties file is the new filename for ADT
+ */
+ File projectPropertiesFile =
+ project.getFile(PROJECT_PROPERTIES_FILENAME).getLocation().toFile();
+ File defaultPropertiesFile =
+ project.getFile(DEFAULT_PROPERTIES_FILENAME).getLocation().toFile();
+ if (projectPropertiesFile.canWrite())
+ {
+ defaultPropertiesFile = projectPropertiesFile;
+ }
+
+ File proguardFile = project.getFile(PROGUARD_FILENAME).getLocation().toFile();
+
+ try
+ {
+ addProguardLine(defaultPropertiesFile);
+ if (!fileExists(proguardFile))
+ {
+ copyProguardFile(project, monitor);
+ }
+ try
+ {
+ project.refreshLocal(IResource.DEPTH_ONE, null);
+ }
+ catch (CoreException e)
+ {
+ // Do nothing, user just have to press F5
+ }
+ }
+ catch (Exception e)
+ {
+ StudioLogger.error(ObfuscatorManager.class,
+ "Error while setting Proguard to obfuscate", e);
+ status =
+ new Status(IStatus.ERROR, AndroidPlugin.PLUGIN_ID,
+ "Could not set Proguard to obfuscate", e);
+ }
+
+ StudioLogger.collectUsageData(StudioLogger.WHAT_OBFUSCATE, StudioLogger.KIND_OBFUSCATE,
+ StudioLogger.DESCRIPTION_DEFAULT, AndroidPlugin.PLUGIN_ID, AndroidPlugin
+ .getDefault().getBundle().getVersion().toString());
+
+ return status;
+ }
+
+ /**
+ * Removes Proguard settings
+ * (Project will not be obfuscated when the is exported in release mode)
+ * @param project
+ * @return
+ */
+ public static IStatus unobfuscate(IProject project)
+ {
+ IStatus status = Status.OK_STATUS;
+
+ try
+ {
+ File projectPropertiesFile =
+ project.getFile(PROJECT_PROPERTIES_FILENAME).getLocation().toFile();
+ File defaultPropertiesFile =
+ project.getFile(DEFAULT_PROPERTIES_FILENAME).getLocation().toFile();
+ if (isProguardSet(defaultPropertiesFile))
+ {
+ removeProguardLine(defaultPropertiesFile);
+ }
+ if (isProguardSet(projectPropertiesFile))
+ {
+ removeProguardLine(projectPropertiesFile);
+ }
+ try
+ {
+ project.refreshLocal(IResource.DEPTH_ONE, null);
+ }
+ catch (CoreException e)
+ {
+ // Do nothing, user just have to press F5
+ }
+ }
+ catch (Exception e)
+ {
+ StudioLogger
+ .error(ObfuscatorManager.class, "Error while removing Proguard settings", e);
+ status =
+ new Status(IStatus.ERROR, AndroidPlugin.PLUGIN_ID,
+ "Could not remove Proguard settings", e);
+ }
+
+ StudioLogger.collectUsageData(StudioLogger.WHAT_OBFUSCATE, StudioLogger.KIND_DESOBFUSCATE,
+ StudioLogger.DESCRIPTION_DEFAULT, AndroidPlugin.PLUGIN_ID, AndroidPlugin
+ .getDefault().getBundle().getVersion().toString());
+
+ return status;
+ }
+
+ /*
+ * @param propertiesFile file to write
+ * @param newContent content to write (replaces entire file)
+ * @throws IOException
+ */
+ private static void write(File propertiesFile, String newContent) throws IOException
+ {
+ Writer out = new OutputStreamWriter(new FileOutputStream(propertiesFile));
+ try
+ {
+ out.write(newContent);
+ }
+ finally
+ {
+ if (out != null)
+ {
+ out.close();
+ }
+ }
+ }
+
+ /*
+ * @param ignoreProguardStatement true it does not return the line with proguard.config=proguard.cfg
+ * @return
+ * @throws IOException
+ */
+ private static String read(File propertiesFile, boolean ignoreProguardStatement)
+ throws IOException
+ {
+ StringBuilder text = new StringBuilder();
+ Scanner scanner = null;
+ FileInputStream stream = null;
+ try
+ {
+ stream = new FileInputStream(propertiesFile);
+ scanner = new Scanner(stream);
+ while (scanner.hasNextLine())
+ {
+ String line = scanner.nextLine();
+ if (!ignoreProguardStatement || !line.contains(PROGUARD_CONFIG_STATEMENT))
+ {
+ text.append(line + NL);
+ }
+ }
+ }
+ finally
+ {
+ try
+ {
+ if (scanner != null)
+ {
+ scanner.close();
+ }
+ if (stream != null)
+ {
+ stream.close();
+ }
+ }
+ catch (IOException e)
+ {
+ StudioLogger
+ .info("Could not close stream while reading obfuscator properties file. "
+ + e.getMessage());
+ }
+ }
+ return text.toString();
+ }
+
+ private static boolean fileExists(File proguardFile)
+ {
+ return (proguardFile != null) && proguardFile.exists();
+ }
+
+ /**
+ * Checks if default.properties have Proguard statement
+ * and if the proguard.cfg exists in the project
+ * @param project
+ * @return
+ */
+ public static boolean isProguardSet(IProject project)
+ {
+ File projectPropertiesFile =
+ project.getFile(PROJECT_PROPERTIES_FILENAME).getLocation().toFile();
+ File defaultPropertiesFile =
+ project.getFile(DEFAULT_PROPERTIES_FILENAME).getLocation().toFile();
+ File proguardFile = project.getFile(PROGUARD_FILENAME).getLocation().toFile();
+
+ return (isProguardSet(projectPropertiesFile) || isProguardSet(defaultPropertiesFile))
+ && fileExists(proguardFile);
+ }
+
+ /**
+ * Checks if default.properties have the Proguard statement
+ * @param propertiesFile
+ * @return
+ */
+ private static boolean isProguardSet(File propertiesFile)
+ {
+ String defaultPropertiesContent = null;
+ try
+ {
+ defaultPropertiesContent = read(propertiesFile, false);
+ }
+ catch (IOException e)
+ {
+ StudioLogger.error(ObfuscatorManager.class, e.getMessage(), e);
+ }
+ return ((defaultPropertiesContent != null) && defaultPropertiesContent
+ .contains(PROGUARD_CONFIG_STATEMENT));
+ }
+
+ /**
+ * Add the following line to file
+ * proguard.config=proguard.cfg
+ * if it does not exist yet
+ * @param project
+ * @throws IOException
+ */
+ private static void addProguardLine(File propertiesFile) throws IOException
+ {
+ String currentContent = null;
+ currentContent = read(propertiesFile, false);
+ if (!currentContent.toString().contains(PROGUARD_CONFIG_STATEMENT))
+ {
+ String newContent =
+ currentContent.endsWith(NL) ? currentContent + PROGUARD_CONFIG_STATEMENT
+ : currentContent + NL + PROGUARD_CONFIG_STATEMENT;
+ write(propertiesFile, newContent);
+ }
+ }
+
+ /**
+ * Remove the following line to file
+ * proguard.config=proguard.cfg
+ * if it exists
+ * @param project
+ * @throws IOException
+ */
+ private static void removeProguardLine(File propertiesFile) throws IOException
+ {
+ String contentWithoutProguardStatement = null;
+ contentWithoutProguardStatement = read(propertiesFile, true);
+ write(propertiesFile, contentWithoutProguardStatement);
+ }
+
+ private static void copyProguardFile(IProject project, IProgressMonitor monitor)
+ throws IOException, CoreException
+ {
+ SubMonitor subMonitor = SubMonitor.convert(monitor);
+
+ URL proguardURL = getProguardFileURL();
+ if (proguardURL != null)
+ {
+ InputStream is = null;
+ try
+ {
+ is = proguardURL.openStream();
+ IFile destFile = project.getFile(PROGUARD_FILENAME);
+ destFile.create(is, IResource.NONE, subMonitor);
+ }
+ finally
+ {
+ if (is != null)
+ {
+ is.close();
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the most suitable proguard file, either from SDK or our plug-in
+ * @return the URL of the best proguard file found
+ */
+ private static URL getProguardFileURL()
+ {
+ String sdkPath = AndroidUtils.getSDKPathByPreference();
+ File sdkPathFile = sdkPath.isEmpty() ? new File(sdkPath) : null;
+ File proguardFromSDK = null;
+ if (sdkPathFile != null)
+ {
+ proguardFromSDK = new File(sdkPathFile, PROGUARD_SDK_PATH);
+ }
+
+ URL fileURL = null;
+ // copy newest proguard file from SDK
+ if ((proguardFromSDK != null) && proguardFromSDK.canRead())
+ {
+ try
+ {
+ fileURL = proguardFromSDK.toURI().toURL();
+ }
+ catch (MalformedURLException e)
+ {
+ StudioLogger.warn(ObfuscatorManager.class,
+ "Exception converting proguard template file to URL", e);
+ }
+ }
+ //copy file bundled with android plugin
+ else
+ {
+ Bundle bundle = AndroidPlugin.getDefault().getBundle();
+ fileURL = bundle.getEntry(PROGUARD_PATH);
+ }
+
+ return fileURL;
+ }
+}