summaryrefslogtreecommitdiff
path: root/src/plugins/android/src/com/motorola/studio/android/model/ProjectCreationSupport.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/android/src/com/motorola/studio/android/model/ProjectCreationSupport.java')
-rw-r--r--src/plugins/android/src/com/motorola/studio/android/model/ProjectCreationSupport.java1377
1 files changed, 1377 insertions, 0 deletions
diff --git a/src/plugins/android/src/com/motorola/studio/android/model/ProjectCreationSupport.java b/src/plugins/android/src/com/motorola/studio/android/model/ProjectCreationSupport.java
new file mode 100644
index 0000000..8551e17
--- /dev/null
+++ b/src/plugins/android/src/com/motorola/studio/android/model/ProjectCreationSupport.java
@@ -0,0 +1,1377 @@
+/*
+ * 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.model;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.wizard.IWizardContainer;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.motorola.studio.android.AndroidPlugin;
+import com.motorola.studio.android.adt.ProjectUtils;
+import com.motorola.studio.android.adt.SdkUtils;
+import com.motorola.studio.android.common.IAndroidConstants;
+import com.motorola.studio.android.common.exception.AndroidException;
+import com.motorola.studio.android.common.log.StudioLogger;
+import com.motorola.studio.android.common.utilities.AndroidStatus;
+import com.motorola.studio.android.common.utilities.EclipseUtils;
+import com.motorola.studio.android.common.utilities.FileUtil;
+import com.motorola.studio.android.i18n.AndroidNLS;
+import com.motorola.studio.android.model.AndroidProject.SourceTypes;
+
+/**
+ * Project Creation Support.
+ */
+public class ProjectCreationSupport
+{
+ /**
+ * Only static calls
+ */
+ private ProjectCreationSupport()
+ {
+ }
+
+ private static final String PACKAGE_NAME = "PACKAGE"; //$NON-NLS-1$
+
+ private static final String APP_NAME = "app_name"; //$NON-NLS-1$
+
+ private static final String APPLICATION_NAME = "APPLICATION_NAME"; //$NON-NLS-1$
+
+ private static final String STRING_RSRC_PREFIX = "@string/"; //$NON-NLS-1$
+
+ private static final String MIN_SDK_VERSION = "MIN_SDK_VERSION"; //$NON-NLS-1$
+
+ private static final String BIN_DIR = IAndroidConstants.FD_OUTPUT + IPath.SEPARATOR;
+
+ private static final String RES_DIR = IAndroidConstants.FD_RESOURCES + IPath.SEPARATOR;
+
+ private static final String ASSETS_DIR = IAndroidConstants.FD_ASSETS + IPath.SEPARATOR;
+
+ private static final String DRAWABLE_DIR = IAndroidConstants.FD_DRAWABLE;
+
+ private static final String LAYOUT_DIR = IAndroidConstants.FD_LAYOUT + IPath.SEPARATOR;
+
+ private static final String VALUES_DIR = IAndroidConstants.FD_VALUES + IPath.SEPARATOR;
+
+ private static final String GEN_DIR = IAndroidConstants.FD_GEN_SOURCES + IPath.SEPARATOR;
+
+ private static final String XML_DIR = "xml" + IPath.SEPARATOR;
+
+ private static final String TEMPLATES_DIRECTORY = "templates/"; //$NON-NLS-1$
+
+ private static final String MANIFEST_TEMPLATE = TEMPLATES_DIRECTORY
+ + "AndroidManifest.template"; //$NON-NLS-1$
+
+ private static final String ACTIVITY_NAME = "ACTIVITY_NAME"; //$NON-NLS-1$
+
+ private static final String ACTIVITY_TEMPLATE = TEMPLATES_DIRECTORY + "activity.template"; //$NON-NLS-1$
+
+ private static final String LAUNCHER_INTENT_TEMPLATE = TEMPLATES_DIRECTORY
+ + "launcher_intent_filter.template"; //$NON-NLS-1$
+
+ private static final String INTENT_FILTERS = "INTENT_FILTERS"; //$NON-NLS-1$
+
+ private static final String ACTIVITIES = "ACTIVITIES"; //$NON-NLS-1$
+
+ private static final String USES_SDK_TEMPLATE = TEMPLATES_DIRECTORY + "uses-sdk.template"; //$NON-NLS-1$
+
+ private static final String USES_SDK = "USES-SDK"; //$NON-NLS-1$
+
+ private static final String ICON = "ic_launcher.png"; //$NON-NLS-1$
+
+ private static final String JAVA_ACTIVITY_TEMPLATE = "java_file.template"; //$NON-NLS-1$
+
+ private static final String MAIN_LAYOUT_XML = "main.xml"; //$NON-NLS-1$
+
+ private static final String LAYOUT_TEMPLATE = "layout.template"; //$NON-NLS-1$
+
+ private static final String STRING_HELLO_WORLD = "hello"; //$NON-NLS-1$
+
+ private static final String TEST_USES_LIBRARY = "TEST-USES-LIBRARY"; //$NON-NLS-1$
+
+ private static final String TEST_INSTRUMENTATION = "TEST-INSTRUMENTATION"; //$NON-NLS-1$
+
+ private static final String[] DPIS =
+ {
+ "hdpi", "ldpi", "mdpi"
+ };
+
+ /*
+ * Widget Project manifest creation constants
+ */
+
+ private static final String WIDGET_TEMPLATE_FOLDER = "templates/widget_project/";
+
+ private static final String WIDGET_MANIFEST_TEMPLATE_PATH =
+ "templates/widget_project/AndroidWidgetManifest.template"; //$NON-NLS-1$
+
+ private static final String WIDGET_ACTIVITY_TEMPLATE_PATH =
+ "templates/widget_project/activity.template"; //$NON-NLS-1$
+
+ private static final String WIDGET_RECEIVER_TEMPLATE_PATH =
+ "templates/widget_project/receiver.template"; //$NON-NLS-1$
+
+ private static final String WIDGET_USES_SDK_TEMPLATE_PATH =
+ "templates/widget_project/uses-sdk.template"; //$NON-NLS-1$
+
+ private static final String RECEIVERS = "RECEIVERS"; //$NON-NLS-1$
+
+ private static final String WIDGET_INITIAL_LAYOUT_XML = "widget_initial_layout.xml"; //$NON-NLS-1$
+
+ private static final String WIDGET_INFO_XML = "widget_info.xml"; //$NON-NLS-1$
+
+ private static final String WIDGET_PROVIDER_SAMPLE_NAME = "WidgetProvider"; //$NON-NLS-1$
+
+ private static final String WIDGET_PROVIDER_SAMPLE_TEMPLATE = "WidgetProvider.template"; //$NON-NLS-1$
+
+ private static final String IMPORT_RESOURCE_CLASS = "IMPORT_RESOURCE_CLASS";
+
+ /**
+ * Create a new Android Project
+ * @param androidProject
+ * @param container
+ * @return
+ * @throws AndroidException
+ */
+ public static boolean createProject(final AndroidProject androidProject,
+ IWizardContainer container) throws AndroidException
+ {
+ boolean created = true;
+
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ final IProject project = workspace.getRoot().getProject(androidProject.getName());
+
+ if (!canCreateProject(workspace.getRoot(), androidProject.getName()))
+ {
+ throw new AndroidException(
+ AndroidNLS.EXC_ProjectCreationSupport_CannotCreateProjectReadOnlyWorkspace);
+ }
+ else
+ {
+
+ final IProjectDescription description =
+ workspace.newProjectDescription(project.getName());
+
+ final Map<String, Object> parameters = new HashMap<String, Object>();
+ parameters.put(MIN_SDK_VERSION, androidProject.getMinSdkVersion());
+
+ if ((androidProject.getSourceType() == SourceTypes.NEW)
+ || (androidProject.getSourceType() == SourceTypes.WIDGET))
+ {
+ /*
+ * An activity name can be of the form ".package.Class" or ".Class".
+ * The initial dot is ignored, as it is always added later in the templates.
+ */
+ String activityName = androidProject.getActivityName();
+ if (activityName.startsWith(".")) { //$NON-NLS-1$
+ activityName = activityName.substring(1);
+ }
+ parameters.put(ACTIVITY_NAME, androidProject.getActivityName());
+ parameters.put(PACKAGE_NAME, androidProject.getPackageName());
+ parameters.put(APPLICATION_NAME, STRING_RSRC_PREFIX + APP_NAME);
+ parameters.put(IMPORT_RESOURCE_CLASS, "");
+ }
+
+ /*
+ * create a dictionary of string that will contain name+content.
+ * we'll put all the strings into values/strings.xml
+ */
+ final HashMap<String, String> stringDictionary = new HashMap<String, String>();
+ stringDictionary.put(APP_NAME, androidProject.getApplicationName());
+
+ if (!androidProject.isUsingDefaultLocation() && androidProject.isNewProject())
+ {
+ Path destination = new Path(androidProject.getLocation());
+ description.setLocation(destination);
+
+ if (!FileUtil.canWrite(destination.toFile()))
+ {
+ String errMsg =
+ NLS.bind(
+ AndroidNLS.EXC_ProjectCreationSupport_CannotCreateProjectReadOnlyDestination,
+ destination.toOSString());
+ throw new AndroidException(errMsg);
+ }
+
+ if (!validateNewProjectLocationIsEmpty(destination))
+ {
+ throw new AndroidException(AndroidNLS.UI_ProjectCreationSupport_NonEmptyFolder);
+ }
+ }
+
+ if (androidProject.getSourceType() == SourceTypes.EXISTING)
+ {
+ Path destination = new Path(androidProject.getLocation());
+ description.setLocation(destination);
+ }
+
+ /*
+ * Create a monitored operation to create the actual project
+ */
+ WorkspaceModifyOperation op = new WorkspaceModifyOperation()
+ {
+ @Override
+ protected void execute(IProgressMonitor monitor) throws InvocationTargetException
+ {
+
+ createProjectAsync(project, androidProject, description, monitor, parameters,
+ stringDictionary);
+ }
+ };
+
+ /*
+ * Run the operation in a different thread
+ */
+ created = runAsyncOperation(op, container);
+ }
+
+ return created;
+
+ }
+
+ /**
+ * Create android project.
+ * @param project
+ * @param androidProject
+ * @param description
+ * @param monitor
+ * @param parameters
+ * @param stringDictionary
+ * @throws InvocationTargetException
+ */
+ protected static void createProjectAsync(IProject project, AndroidProject androidProject,
+ IProjectDescription description, IProgressMonitor monitor,
+ Map<String, Object> parameters, Map<String, String> stringDictionary)
+ throws InvocationTargetException
+ {
+ monitor.beginTask(AndroidNLS.UI_ProjectCreationSupport_CopyingSamplesMonitorTaskTitle, 1000);
+ try
+ {
+ // Create project and open it
+ project.create(description, new SubProgressMonitor(monitor, 100));
+ if (monitor.isCanceled())
+ {
+ undoProjectCreation(project);
+ throw new OperationCanceledException();
+ }
+ project.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(monitor, 100));
+
+ ProjectUtils.setupAndroidNatures(project, monitor);
+
+ // Create folders in the project if they don't already exist
+ createDefaultDir(project, IAndroidConstants.WS_ROOT, BIN_DIR, new SubProgressMonitor(
+ monitor, 40));
+ createDefaultDir(project, IAndroidConstants.WS_ROOT, RES_DIR, new SubProgressMonitor(
+ monitor, 40));
+ createDefaultDir(project, IAndroidConstants.WS_ROOT, ASSETS_DIR,
+ new SubProgressMonitor(monitor, 40));
+ createDefaultDir(project, IAndroidConstants.WS_ROOT, GEN_DIR, new SubProgressMonitor(
+ monitor, 40));
+
+ switch (androidProject.getSourceType())
+ {
+ case NEW:
+ // Create the source folders in the project if they don't already exist
+ List<String> sourceFolders = androidProject.getSourceFolders();
+ for (String sourceFolder : sourceFolders)
+ {
+ createDefaultDir(project, IAndroidConstants.WS_ROOT, sourceFolder,
+ new SubProgressMonitor(monitor, 40));
+ }
+
+ // Create the resource folders in the project if they don't already exist.
+ int apiLevel = androidProject.getSdkTarget().getVersion().getApiLevel();
+ if (apiLevel < 4)
+ {
+ createDefaultDir(project, RES_DIR, DRAWABLE_DIR + File.separator,
+ new SubProgressMonitor(monitor, 40));
+ }
+ else
+ {
+ for (String dpi : DPIS)
+ {
+ createDefaultDir(project, RES_DIR, DRAWABLE_DIR + "-" + dpi
+ + File.separator, new SubProgressMonitor(monitor, 40));
+ }
+ }
+ createDefaultDir(project, RES_DIR, LAYOUT_DIR, new SubProgressMonitor(monitor,
+ 40));
+ createDefaultDir(project, RES_DIR, VALUES_DIR, new SubProgressMonitor(monitor,
+ 40));
+
+ // Create files in the project if they don't already exist
+ createManifest(project, parameters, stringDictionary, new SubProgressMonitor(
+ monitor, 80));
+ // add the default app icon
+ addIcon(project, apiLevel, new SubProgressMonitor(monitor, 100));
+ // Create the default package components
+ String primarySrcFolder = IAndroidConstants.FD_SOURCES;
+ if (!sourceFolders.contains(IAndroidConstants.FD_SOURCES))
+ {
+ primarySrcFolder = sourceFolders.get(0);
+ }
+ addInitialCode(project, primarySrcFolder, parameters, stringDictionary,
+ new SubProgressMonitor(monitor, 200));
+ // add the string definition file if needed
+ if (stringDictionary.size() > 0)
+ {
+ EclipseUtils.createOrUpdateDictionaryFile(project, stringDictionary, null,
+ new SubProgressMonitor(monitor, 100));
+ }
+
+ break;
+ case EXISTING:
+ createDefaultDir(project, IAndroidConstants.WS_ROOT, GEN_DIR,
+ new SubProgressMonitor(monitor, 650));
+ break;
+ case SAMPLE:
+ monitor.setTaskName(AndroidNLS.UI_ProjectCreationSupport_CopyingSamplesMonitorMessage);
+ FileUtil.copyDir(androidProject.getSample().getFolder(), project.getLocation()
+ .toFile());
+ project.refreshLocal(IResource.DEPTH_INFINITE, new SubProgressMonitor(monitor,
+ 650));
+ break;
+ case WIDGET:
+ // Create the source folders in the project if they don't already exist
+ List<String> widgetSourceFolders = androidProject.getSourceFolders();
+ for (String sourceFolder : widgetSourceFolders)
+ {
+ createDefaultDir(project, IAndroidConstants.WS_ROOT, sourceFolder,
+ new SubProgressMonitor(monitor, 40));
+ }
+
+ // Create the resource folders in the project if they don't already exist.
+ int widgetApiLevel = androidProject.getSdkTarget().getVersion().getApiLevel();
+ if (widgetApiLevel < 4)
+ {
+ createDefaultDir(project, RES_DIR, DRAWABLE_DIR + File.separator,
+ new SubProgressMonitor(monitor, 40));
+ }
+ else
+ {
+ for (String dpi : DPIS)
+ {
+ createDefaultDir(project, RES_DIR, DRAWABLE_DIR + "-" + dpi
+ + File.separator, new SubProgressMonitor(monitor, 40));
+ }
+ }
+ createDefaultDir(project, RES_DIR, LAYOUT_DIR, new SubProgressMonitor(monitor,
+ 40));
+ createDefaultDir(project, RES_DIR, VALUES_DIR, new SubProgressMonitor(monitor,
+ 40));
+ createDefaultDir(project, RES_DIR, XML_DIR, new SubProgressMonitor(monitor, 40));
+
+ // Create files in the project if they don't already exist
+ createWidgetManifest(project, parameters, stringDictionary,
+ new SubProgressMonitor(monitor, 80));
+ // add the default app icon
+ addIcon(project, widgetApiLevel, new SubProgressMonitor(monitor, 100));
+ // Create the default package components
+ String widgetPrimarySrcFolder = IAndroidConstants.FD_SOURCES;
+ if (!widgetSourceFolders.contains(IAndroidConstants.FD_SOURCES))
+ {
+ primarySrcFolder = widgetSourceFolders.get(0);
+ }
+ addInitialWidgetCode(project, widgetPrimarySrcFolder, parameters,
+ stringDictionary, new SubProgressMonitor(monitor, 200));
+ // add the string definition file if needed
+ if (stringDictionary.size() > 0)
+ {
+ EclipseUtils.createOrUpdateDictionaryFile(project, stringDictionary, null,
+ new SubProgressMonitor(monitor, 100));
+ }
+
+ break;
+ }
+
+ // Setup class path
+ IJavaProject javaProject = JavaCore.create(project);
+ setupSourceFolders(javaProject, androidProject.getSourceFolders(),
+ new SubProgressMonitor(monitor, 40));
+
+ // Set output location
+ javaProject.setOutputLocation(project.getFolder(BIN_DIR).getFullPath(),
+ new SubProgressMonitor(monitor, 40));
+ SdkUtils.associate(project, androidProject.getSdkTarget());
+ ProjectUtils.fixProject(project);
+ }
+ catch (CoreException e)
+ {
+ undoProjectCreation(project);
+ throw new InvocationTargetException(e);
+ }
+ catch (IOException e)
+ {
+ undoProjectCreation(project);
+ throw new InvocationTargetException(e);
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ /**
+ * Add initial code
+ * @param project
+ * @param sourceFolder
+ * @param parameters
+ * @param stringDictionary
+ * @param monitor
+ * @throws CoreException
+ * @throws IOException
+ */
+ private static void addInitialCode(IProject project, String sourceFolder,
+ Map<String, Object> parameters, Map<String, String> stringDictionary,
+ IProgressMonitor monitor) throws CoreException, IOException
+ {
+ monitor.beginTask(AndroidNLS.UI_ProjectCreationSupport_Configuring_Sample_Source_Task, 700);
+
+ try
+ {
+ IFolder pkgFolder = project.getFolder(sourceFolder);
+
+ Map<String, Object> processed_parameters = processSampleActivity(parameters);
+ String activityName = (String) processed_parameters.get(ACTIVITY_NAME);
+ String packageName = (String) processed_parameters.get(PACKAGE_NAME);
+
+ pkgFolder =
+ createPackageFolders(new SubProgressMonitor(monitor, 300), pkgFolder,
+ packageName);
+
+ if (activityName != null)
+ {
+ createSampleActivity(new SubProgressMonitor(monitor, 200), pkgFolder,
+ processed_parameters, activityName);
+ }
+
+ IFolder layoutfolder = project.getFolder(RES_DIR + LAYOUT_DIR);
+ IFile file = layoutfolder.getFile(MAIN_LAYOUT_XML);
+ if (!file.exists())
+ {
+ copyTemplateFile(LAYOUT_TEMPLATE, file, parameters, new SubProgressMonitor(monitor,
+ 100));
+ if (activityName != null)
+ {
+ stringDictionary
+ .put(STRING_HELLO_WORLD, NLS.bind(
+ AndroidNLS.GEN_ProjectCreationSupport_HelloWorldWithName,
+ activityName));
+ }
+ else
+ {
+ stringDictionary.put(STRING_HELLO_WORLD,
+ AndroidNLS.GEN_ProjectCreationSupport_HelloWorldSimple);
+ }
+ monitor.worked(100);
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ /**
+ * Add initial widget code
+ * @param project
+ * @param sourceFolder
+ * @param parameters
+ * @param stringDictionary
+ * @param monitor
+ * @throws CoreException
+ * @throws IOException
+ */
+ private static void addInitialWidgetCode(IProject project, String sourceFolder,
+ Map<String, Object> parameters, Map<String, String> stringDictionary,
+ IProgressMonitor monitor) throws CoreException, IOException
+ {
+ monitor.beginTask(AndroidNLS.UI_ProjectCreationSupport_Configuring_Sample_Source_Task, 800);
+
+ try
+ {
+ IFolder pkgFolder = project.getFolder(sourceFolder);
+
+ Map<String, Object> processed_parameters = processSampleActivity(parameters);
+ String activityName = (String) processed_parameters.get(ACTIVITY_NAME);
+ String packageName = (String) processed_parameters.get(PACKAGE_NAME);
+
+ pkgFolder =
+ createPackageFolders(new SubProgressMonitor(monitor, 200), pkgFolder,
+ packageName);
+
+ // Create sample activity
+ if (activityName != null)
+ {
+ createSampleActivity(new SubProgressMonitor(monitor, 100), pkgFolder,
+ processed_parameters, activityName);
+ }
+
+ // Create sample widget provider
+ createSampleWidgetProvider(new SubProgressMonitor(monitor, 100), pkgFolder,
+ processed_parameters);
+
+ // Layout xml file
+ IFolder layoutfolder = project.getFolder(RES_DIR + LAYOUT_DIR);
+
+ IFile file = layoutfolder.getFile(MAIN_LAYOUT_XML);
+ if (!file.exists())
+ {
+ copyTemplateFile(LAYOUT_TEMPLATE, file, parameters, new SubProgressMonitor(monitor,
+ 100));
+ if (activityName != null)
+ {
+ stringDictionary
+ .put(STRING_HELLO_WORLD, NLS.bind(
+ AndroidNLS.GEN_ProjectCreationSupport_HelloWorldWithName,
+ activityName));
+ }
+ else
+ {
+ stringDictionary.put(STRING_HELLO_WORLD,
+ AndroidNLS.GEN_ProjectCreationSupport_HelloWorldSimple);
+ }
+ monitor.worked(100);
+ }
+
+ // Widget initial layout xml file
+ IFile initial_layout_file = layoutfolder.getFile(WIDGET_INITIAL_LAYOUT_XML);
+ if (!initial_layout_file.exists())
+ {
+ copyWidgetTemplateFile(WIDGET_INITIAL_LAYOUT_XML, initial_layout_file,
+ processed_parameters, new SubProgressMonitor(monitor, 100));
+ monitor.worked(100);
+ }
+
+ // Widget info xml file
+ IFolder xmlFolder = project.getFolder(RES_DIR + XML_DIR);
+
+ IFile widget_info_file = xmlFolder.getFile(WIDGET_INFO_XML);
+ if (!widget_info_file.exists())
+ {
+ copyWidgetTemplateFile(WIDGET_INFO_XML, widget_info_file, processed_parameters,
+ new SubProgressMonitor(monitor, 100));
+ monitor.worked(100);
+ }
+
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ private static void createSampleActivity(IProgressMonitor monitor, IFolder pkgFolder,
+ Map<String, Object> processed_parameters, String activityName) throws CoreException,
+ IOException
+ {
+ monitor.beginTask(AndroidNLS.UI_ProjectCreationSupport_Configuring_Sample_Activity_Task,
+ 100);
+ try
+ {
+ IFile file = pkgFolder.getFile(activityName + IAndroidConstants.DOT_JAVA);
+ if (!file.exists())
+ {
+ monitor.worked(10);
+ copyTemplateFile(JAVA_ACTIVITY_TEMPLATE, file, processed_parameters,
+ new SubProgressMonitor(monitor, 90));
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ private static void createSampleWidgetProvider(IProgressMonitor monitor, IFolder pkgFolder,
+ Map<String, Object> processed_parameters) throws CoreException, IOException
+ {
+ monitor.beginTask(AndroidNLS.UI_ProjectCreationSupport_Configuring_Sample_Widget_Provider,
+ 100);
+ try
+ {
+ IFile file =
+ pkgFolder.getFile(WIDGET_PROVIDER_SAMPLE_NAME + IAndroidConstants.DOT_JAVA);
+ if (!file.exists())
+ {
+ monitor.worked(10);
+ copyWidgetTemplateFile(WIDGET_PROVIDER_SAMPLE_TEMPLATE, file, processed_parameters,
+ new SubProgressMonitor(monitor, 90));
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ private static IFolder createPackageFolders(IProgressMonitor monitor, IFolder pkgFolder,
+ String packageName) throws CoreException
+ {
+ String[] components = packageName.split(IAndroidConstants.RE_DOT);
+ monitor.beginTask(AndroidNLS.UI_ProjectCreationSupport_Preparing_Java_Packages_Task,
+ components.length * 100);
+ try
+ {
+ for (String component : components)
+ {
+ pkgFolder = pkgFolder.getFolder(component);
+ if (!pkgFolder.exists())
+ {
+ pkgFolder.create(true, true, new SubProgressMonitor(monitor, 100));
+ }
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+
+ return pkgFolder;
+ }
+
+ private static Map<String, Object> processSampleActivity(Map<String, Object> parameters)
+ {
+ String activityName = (String) parameters.get(ACTIVITY_NAME);
+
+ Map<String, Object> processed_parameters = new HashMap<String, Object>(parameters);
+ if ((activityName != null) && activityName.contains(".")) //$NON-NLS-1$
+ {
+ String packageName = (String) parameters.get(PACKAGE_NAME);
+ packageName += "." + activityName.substring(0, activityName.lastIndexOf('.')); //$NON-NLS-1$
+ activityName = activityName.substring(activityName.lastIndexOf('.'));
+
+ processed_parameters.put(PACKAGE_NAME, packageName);
+ processed_parameters.put(ACTIVITY_NAME, activityName);
+ }
+
+ return processed_parameters;
+ }
+
+ /**
+ * Copy template files
+ * @param resourceFilename
+ * @param destFile
+ * @param parameters
+ * @param monitor
+ * @throws CoreException
+ * @throws IOException
+ */
+ private static void copyTemplateFile(String resourceFilename, IFile destFile,
+ Map<String, Object> parameters, IProgressMonitor monitor) throws CoreException,
+ IOException
+ {
+ monitor.beginTask(AndroidNLS.UI_ProjectCreationSupport_Preparing_Template_File_Task, 150);
+ InputStream stream = null;
+ try
+ {
+ String template =
+ readEmbeddedTextFileADT(TEMPLATES_DIRECTORY + resourceFilename, parameters);
+ monitor.worked(50);
+ stream = new ByteArrayInputStream(template.getBytes("UTF-8")); //$NON-NLS-1$
+ destFile.create(stream, false, new SubProgressMonitor(monitor, 100));
+
+ }
+ finally
+ {
+ if (stream != null)
+ {
+ stream.close();
+ }
+ monitor.done();
+ }
+ }
+
+ /**
+ * Copy widget template files
+ * @param resourceFilename
+ * @param destFile
+ * @param parameters
+ * @param monitor
+ * @throws CoreException
+ * @throws IOException
+ */
+ private static void copyWidgetTemplateFile(String resourceFilename, IFile destFile,
+ Map<String, Object> parameters, IProgressMonitor monitor) throws CoreException,
+ IOException
+ {
+ monitor.beginTask(AndroidNLS.UI_ProjectCreationSupport_Preparing_Template_File_Task, 150);
+ InputStream stream = null;
+ try
+ {
+ String template =
+ readEmbeddedTextFileStudio(WIDGET_TEMPLATE_FOLDER + resourceFilename,
+ parameters);
+ monitor.worked(50);
+ stream = new ByteArrayInputStream(template.getBytes("UTF-8")); //$NON-NLS-1$
+ destFile.create(stream, false, new SubProgressMonitor(monitor, 100));
+
+ }
+ finally
+ {
+ if (stream != null)
+ {
+ stream.close();
+ }
+ monitor.done();
+ }
+ }
+
+ /**
+ * Add Icon to the project
+ * @param project
+ * @param apiLevel
+ * @param monitor
+ * @throws CoreException
+ */
+ private static void addIcon(IProject project, int apiLevel, IProgressMonitor monitor)
+ throws CoreException
+ {
+ monitor.beginTask(AndroidNLS.UI_ProjectCreationSupport_Configuring_Project_Icon_Task, 1000);
+ try
+ {
+ if (apiLevel < 4)
+ {
+ IFile imageFile =
+ project.getFile(RES_DIR + IPath.SEPARATOR + DRAWABLE_DIR + IPath.SEPARATOR
+ + ICON);
+ if (!imageFile.exists())
+ {
+ String fileName =
+ ICON.substring(0, ICON.length() - 4) + "_" + DPIS[2]
+ + ICON.substring(ICON.length() - 4);
+ createImageFromTemplate(monitor, imageFile, fileName);
+ }
+ }
+ else
+ {
+ for (String dpi : DPIS)
+ {
+ IFile imageFile =
+ project.getFile(RES_DIR + IPath.SEPARATOR + DRAWABLE_DIR + "-" + dpi
+ + IPath.SEPARATOR + ICON);
+ if (!imageFile.exists())
+ {
+ String fileName =
+ ICON.substring(0, ICON.length() - 4) + "_" + dpi
+ + ICON.substring(ICON.length() - 4);
+ createImageFromTemplate(monitor, imageFile, fileName);
+ }
+ }
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+
+ }
+
+ private static void createImageFromTemplate(IProgressMonitor monitor, IFile imageFile,
+ String fileName) throws CoreException
+ {
+ byte[] buffer = AdtPlugin.readEmbeddedFile(TEMPLATES_DIRECTORY + fileName);
+
+ if (buffer != null)
+ {
+ InputStream stream = null;
+ try
+ {
+ stream = new ByteArrayInputStream(buffer);
+ imageFile.create(stream, IResource.NONE, new SubProgressMonitor(monitor, 1000));
+ }
+ finally
+ {
+ try
+ {
+ stream.close();
+ }
+ catch (IOException e)
+ {
+ StudioLogger.info("Create image from template could not close stream. "
+ + e.getMessage());
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds the manifest to the project.
+ * @param project
+ * @param parameters
+ * @param stringDictionary
+ * @param monitor
+ * @throws CoreException
+ * @throws IOException
+ */
+ private static void createManifest(IProject project, Map<String, Object> parameters,
+ Map<String, String> stringDictionary, IProgressMonitor monitor) throws CoreException,
+ IOException
+ {
+ monitor.beginTask(AndroidNLS.UI_ProjectCreationSupport_Creating_Manifest_File_Task, 300);
+ try
+ {
+ IFile manifestFile = project.getFile(IAndroidConstants.FN_ANDROID_MANIFEST);
+ if (!manifestFile.exists())
+ {
+ monitor.setTaskName(AndroidNLS.UI_ProjectCreationSupport_Reading_Template_File_Task);
+ String manifestTemplate = readEmbeddedTextFileADT(MANIFEST_TEMPLATE, parameters);
+ monitor.worked(10);
+ if (parameters.containsKey(ACTIVITY_NAME))
+ {
+ String activities = readEmbeddedTextFileADT(ACTIVITY_TEMPLATE, parameters);
+ String intent = AdtPlugin.readEmbeddedTextFile(LAUNCHER_INTENT_TEMPLATE);
+ activities = activities.replaceAll(INTENT_FILTERS, intent);
+ manifestTemplate = manifestTemplate.replaceAll(ACTIVITIES, activities);
+ monitor.worked(90);
+ }
+ else
+ {
+ manifestTemplate = manifestTemplate.replaceAll(ACTIVITIES, ""); //$NON-NLS-1$
+ monitor.worked(90);
+ }
+
+ //We don't currently supports the TEST parameters. So let's just remove the unused tags.
+ manifestTemplate = manifestTemplate.replaceAll(TEST_USES_LIBRARY, ""); //$NON-NLS-1$
+ manifestTemplate = manifestTemplate.replaceAll(TEST_INSTRUMENTATION, ""); //$NON-NLS-1$
+
+ String minSdkVersion = (String) parameters.get(MIN_SDK_VERSION);
+ if ((minSdkVersion != null) && (minSdkVersion.length() > 0))
+ {
+ String usesSdk = readEmbeddedTextFileADT(USES_SDK_TEMPLATE, parameters);
+ manifestTemplate = manifestTemplate.replaceAll(USES_SDK, usesSdk);
+ monitor.worked(50);
+ }
+ else
+ {
+ manifestTemplate = manifestTemplate.replaceAll(USES_SDK, ""); //$NON-NLS-1$
+ monitor.worked(50);
+ }
+
+ InputStream stream = null;
+ try
+ {
+ stream = new ByteArrayInputStream(manifestTemplate.getBytes("UTF-8")); //$NON-NLS-1$
+ manifestFile.create(stream, IResource.NONE,
+ new SubProgressMonitor(monitor, 150));
+ }
+ finally
+ {
+ try
+ {
+ if (stream != null)
+ {
+ stream.close();
+ }
+ }
+ catch (IOException e)
+ {
+ StudioLogger.info("Could not close stream while creating manifest",
+ e.getMessage());
+ }
+ }
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ /**
+ * Adds the widget manifest to the project.
+ * @param project
+ * @param parameters
+ * @param stringDictionary
+ * @param monitor
+ * @throws CoreException
+ * @throws IOException
+ */
+ private static void createWidgetManifest(IProject project, Map<String, Object> parameters,
+ Map<String, String> stringDictionary, IProgressMonitor monitor) throws CoreException,
+ IOException
+ {
+ monitor.beginTask(AndroidNLS.UI_ProjectCreationSupport_Creating_Manifest_File_Task, 300);
+ try
+ {
+ IFile manifestFile = project.getFile(IAndroidConstants.FN_ANDROID_MANIFEST);
+ if (!manifestFile.exists())
+ {
+ monitor.setTaskName(AndroidNLS.UI_ProjectCreationSupport_Reading_Template_File_Task);
+
+ // Manifest skeleton
+ String manifestTemplate =
+ readEmbeddedTextFileStudio(WIDGET_MANIFEST_TEMPLATE_PATH, parameters);
+ monitor.worked(10);
+ // Activity information
+ if (parameters.containsKey(ACTIVITY_NAME))
+ {
+ String activities =
+ readEmbeddedTextFileStudio(WIDGET_ACTIVITY_TEMPLATE_PATH, parameters);
+ manifestTemplate = manifestTemplate.replaceAll(ACTIVITIES, activities);
+ monitor.worked(70);
+ }
+ else
+ {
+ manifestTemplate = manifestTemplate.replaceAll(ACTIVITIES, ""); //$NON-NLS-1$
+ monitor.worked(70);
+ }
+
+ // Receiver information
+ String receivers =
+ readEmbeddedTextFileStudio(WIDGET_RECEIVER_TEMPLATE_PATH, parameters);
+ manifestTemplate = manifestTemplate.replaceAll(RECEIVERS, receivers);
+ monitor.worked(70);
+
+ // Min Sdk information
+ String minSdkVersion = (String) parameters.get(MIN_SDK_VERSION);
+ if ((minSdkVersion != null) && (minSdkVersion.length() > 0))
+ {
+ String usesSdk =
+ readEmbeddedTextFileStudio(WIDGET_USES_SDK_TEMPLATE_PATH, parameters);
+ manifestTemplate = manifestTemplate.replaceAll(USES_SDK, usesSdk);
+ monitor.worked(50);
+ }
+ else
+ {
+ manifestTemplate = manifestTemplate.replaceAll(USES_SDK, ""); //$NON-NLS-1$
+ monitor.worked(50);
+ }
+
+ InputStream stream = null;
+
+ try
+ {
+ stream = new ByteArrayInputStream(manifestTemplate.getBytes("UTF-8")); //$NON-NLS-1$
+ manifestFile.create(stream, IResource.NONE,
+ new SubProgressMonitor(monitor, 100));
+ }
+ finally
+ {
+ try
+ {
+ if (stream != null)
+ {
+ stream.close();
+ }
+ }
+ catch (IOException e)
+ {
+ StudioLogger.info(
+ "Could not close stream while creating manifest for widget",
+ e.getMessage());
+ }
+ }
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ private static String readEmbeddedTextFileADT(String template, Map<String, Object> parameters)
+ {
+ String loadedTemplate = AdtPlugin.readEmbeddedTextFile(template);
+
+ for (String key : parameters.keySet())
+ {
+ if (parameters.get(key) instanceof String)
+ {
+ loadedTemplate = loadedTemplate.replaceAll(key, (String) parameters.get(key));
+ }
+ }
+
+ return loadedTemplate;
+ }
+
+ private static String readEmbeddedTextFileStudio(String template, Map<String, Object> parameters)
+ {
+ String loadedTemplate =
+ EclipseUtils.readEmbeddedResource(AndroidPlugin.getDefault().getBundle(), template);
+
+ for (String key : parameters.keySet())
+ {
+ if (parameters.get(key) instanceof String)
+ {
+ loadedTemplate = loadedTemplate.replaceAll(key, (String) parameters.get(key));
+ }
+ }
+
+ return loadedTemplate;
+ }
+
+ /**
+ * Setup src folders
+ * @param javaProject
+ * @param sourceFolder
+ * @param monitor
+ * @throws JavaModelException
+ */
+ private static void setupSourceFolders(IJavaProject javaProject, List<String> sourceFolders,
+ IProgressMonitor monitor) throws JavaModelException
+ {
+ monitor.beginTask(AndroidNLS.UI_ProjectCreationSupport_Preparing_Source_Folders_Task,
+ (sourceFolders.size() * 100) + 100);
+ try
+ {
+ IProject project = javaProject.getProject();
+ IClasspathEntry[] entries = javaProject.getRawClasspath();
+
+ for (String sourceFolder : sourceFolders)
+ {
+ IFolder srcFolder = project.getFolder(sourceFolder);
+ entries = removeClasspathEntry(entries, srcFolder);
+ entries = removeClasspathEntry(entries, srcFolder.getParent());
+ entries =
+ ProjectUtils.addEntryToClasspath(entries,
+ JavaCore.newSourceEntry(srcFolder.getFullPath()));
+ monitor.worked(100);
+ }
+
+ javaProject.setRawClasspath(entries, new SubProgressMonitor(monitor, 100));
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ /**
+ * Remove source folder from classpath
+ * @param entries
+ * @param folder
+ * @return
+ */
+ private static IClasspathEntry[] removeClasspathEntry(IClasspathEntry[] entries,
+ IContainer folder)
+ {
+
+ IClasspathEntry[] newClassPath = null;
+
+ if (folder != null)
+ {
+ IClasspathEntry removeEntry = JavaCore.newSourceEntry(folder.getFullPath());
+ List<IClasspathEntry> entriesList = Arrays.asList(entries);
+
+ if (entriesList.contains(removeEntry))
+ {
+ newClassPath = new IClasspathEntry[entries.length - 1];
+ int i = 0;
+ for (IClasspathEntry entry : entriesList)
+ {
+ if (!entry.equals(removeEntry))
+ {
+ newClassPath[i] = entry;
+ i++;
+ }
+ }
+ }
+ else
+ {
+ newClassPath = entries;
+ }
+ }
+ else
+ {
+ newClassPath = entries;
+ }
+ return newClassPath;
+ }
+
+ /**
+ * Add default directory to Project
+ * @param project
+ * @param parentFolder
+ * @param folderName
+ * @param monitor
+ * @throws CoreException
+ */
+ private static void createDefaultDir(IProject project, String parentFolder, String folderName,
+ IProgressMonitor monitor) throws CoreException
+ {
+ monitor.beginTask(
+ AndroidNLS.UI_ProjectCreationSupport_Creating_Directory_Task + folderName, 100);
+
+ try
+ {
+ monitor.setTaskName(AndroidNLS.UI_ProjectCreationSupport_Verifying_Directory_Task);
+ if (folderName.length() > 0)
+ {
+ monitor.worked(10);
+ IFolder folder = project.getFolder(parentFolder + folderName);
+ monitor.worked(10);
+ if (!folder.exists())
+ {
+ monitor.worked(10);
+ if (FileUtil.canWrite(folder.getLocation().toFile()))
+ {
+ monitor.worked(10);
+ monitor.setTaskName(AndroidNLS.UI_ProjectCreationSupport_Creating_Directory_Task);
+ folder.create(true, true, new SubProgressMonitor(monitor, 60));
+ }
+ else
+ {
+ String errMsg =
+ NLS.bind(
+ AndroidNLS.EXC_ProjectCreationSupport_CannotCreateFolderReadOnlyWorkspace,
+ folder.getLocation().toFile().toString());
+ IStatus status = new AndroidStatus(IStatus.ERROR, errMsg);
+ throw new CoreException(status);
+ }
+ }
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ /**
+ * Validate new Project Location.
+ * @param destination
+ * @param display
+ * @return
+ */
+ public static boolean validateNewProjectLocationIsEmpty(IPath destination)
+ {
+ File f = new File(destination.toOSString());
+ if (f.isDirectory() && (f.list().length > 0))
+ {
+ // EclipseUtils.showErrorDialog(
+ // AndroidNLS.UI_ProjectCreationSupport_NonEmptyFolderQuestionDialogTitle,
+ // AndroidNLS.UI_ProjectCreationSupport_NonEmptyFolderQuestion);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Run the operation in async thread.
+ * @param op
+ * @param container
+ *
+ * @return true if no errors occur during the operation or false otherwise
+ */
+ private static boolean runAsyncOperation(WorkspaceModifyOperation op, IWizardContainer container)
+ {
+ boolean created = false;
+
+ try
+ {
+ container.run(true, true, op);
+ created = true;
+ }
+ catch (InvocationTargetException ite)
+ {
+ Throwable t = ite.getTargetException();
+ if (t instanceof CoreException)
+ {
+ CoreException core = (CoreException) t;
+ if (core.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS)
+ {
+ MessageDialog.openError(container.getShell(),
+ AndroidNLS.UI_GenericErrorDialogTitle,
+ AndroidNLS.ERR_ProjectCreationSupport_CaseVariantExistsError);
+ }
+ else
+ {
+ ErrorDialog.openError(container.getShell(),
+ AndroidNLS.UI_GenericErrorDialogTitle, null, core.getStatus());
+ }
+ }
+ else
+ {
+ MessageDialog.openError(container.getShell(),
+ AndroidNLS.UI_GenericErrorDialogTitle, t.getMessage());
+ }
+ }
+ catch (InterruptedException e)
+ {
+ StudioLogger.error(ProjectCreationSupport.class, "Error creating project.", e); //$NON-NLS-1$
+ }
+
+ return created;
+ }
+
+ /**
+ * Checks if a project can be created on workspace
+ *
+ * @param root The workspace root
+ * @param projectName The project name
+ *
+ * @return true if the project can be created or false otherwise
+ */
+ private static boolean canCreateProject(IWorkspaceRoot root, String projectName)
+ {
+ File rootFolder = root.getLocation().toFile();
+ File projectFolder = new File(rootFolder, projectName);
+
+ return FileUtil.canWrite(projectFolder);
+ }
+
+ /**
+ * Undoes a project creation. Removes all files created by the project creation process
+ * and keeps any other previous files
+ *
+ * @param project The failed project
+ * @param existingResources A set containing the path of pre-existing resources before creating
+ * the project
+ */
+ private static void undoProjectCreation(IProject project)
+ {
+ File projectPath =
+ new File(project.getWorkspace().getRoot().getLocation().toFile(), project.getName());
+ Set<String> existingResources = getExistingResources(projectPath);
+
+ try
+ {
+ project.delete(false, true, new NullProgressMonitor());
+ }
+ catch (CoreException e1)
+ {
+ // Do nothing
+ StudioLogger.error(ProjectCreationSupport.class, e1.getLocalizedMessage(), e1);
+ }
+
+ if (existingResources.isEmpty())
+ {
+ try
+ {
+ FileUtil.deleteDirRecursively(project.getLocation().toFile());
+ }
+ catch (IOException e)
+ {
+ // Do nothing
+ StudioLogger.error(ProjectCreationSupport.class, e.getLocalizedMessage(), e);
+ }
+ }
+ else
+ {
+ File root =
+ new File(project.getWorkspace().getRoot().getLocation().toFile(),
+ project.getName());
+ removeCreatedResources(root, existingResources);
+ }
+ }
+
+ /**
+ * Retrieves a list of existing sub-resources from a folder
+ *
+ * @param folder the File object representing the folder
+ *
+ * @return a list of existing sub-resources from the folder
+ */
+ private static Set<String> getExistingResources(File folder)
+ {
+ Set<String> existing = new HashSet<String>();
+
+ if ((folder != null) && folder.exists() && folder.isDirectory())
+ {
+ existing.add(folder.toString());
+
+ File[] children = folder.listFiles();
+
+ if (children != null)
+ {
+ for (File child : children)
+ {
+ if (child.isDirectory())
+ {
+ existing.addAll(getExistingResources(child));
+ }
+ else
+ {
+ existing.add(child.toString());
+ }
+ }
+ }
+ }
+
+ return existing;
+ }
+
+ /**
+ * Removes the created resources by a failed project creation process
+ *
+ * @param startingPoint The project root folder (File object)
+ * @param existingResources The set containing the previous existing resources in the project root folder
+ */
+ private static void removeCreatedResources(File startingPoint, Set<String> existingResources)
+ {
+ File[] members = startingPoint.listFiles();
+
+ if (members != null)
+ {
+ for (File child : members)
+ {
+ if (child.isFile())
+ {
+ if (!existingResources.contains(child.toString()))
+ {
+ child.delete();
+ }
+ }
+ else
+ {
+ removeCreatedResources(child, existingResources);
+ }
+ }
+ }
+
+ if (!existingResources.contains(startingPoint.toString()))
+ {
+ startingPoint.delete();
+ }
+ }
+}