NewProjectWizardpublic class NewProjectWizard extends org.eclipse.jface.wizard.Wizard implements org.eclipse.ui.INewWizardA "New Android Project" Wizard.
Note: this class is public so that it can be accessed from unit tests.
It is however an internal class. Its API may change without notice.
It should semantically be considered as a private final class.
Do not derive from this class. |
Fields Summary |
---|
private static final String | PARAM_SDK_TOOLS_DIR | private static final String | PARAM_ACTIVITY | private static final String | PARAM_APPLICATION | private static final String | PARAM_PACKAGE | private static final String | PARAM_PROJECT | private static final String | PARAM_STRING_NAME | private static final String | PARAM_STRING_CONTENT | private static final String | PARAM_IS_NEW_PROJECT | private static final String | PARAM_SRC_FOLDER | private static final String | PARAM_SDK_TARGET | private static final String | PARAM_MIN_SDK_VERSION | private static final String | PH_ACTIVITIES | private static final String | PH_USES_SDK | private static final String | PH_INTENT_FILTERS | private static final String | PH_STRINGS | private static final String | BIN_DIRECTORY | private static final String | RES_DIRECTORY | private static final String | ASSETS_DIRECTORY | private static final String | DRAWABLE_DIRECTORY | private static final String | LAYOUT_DIRECTORY | private static final String | VALUES_DIRECTORY | private static final String | GEN_SRC_DIRECTORY | private static final String | TEMPLATES_DIRECTORY | private static final String | TEMPLATE_MANIFEST | private static final String | TEMPLATE_ACTIVITIES | private static final String | TEMPLATE_USES_SDK | private static final String | TEMPLATE_INTENT_LAUNCHER | private static final String | TEMPLATE_STRINGS | private static final String | TEMPLATE_STRING | private static final String | ICON | private static final String | STRINGS_FILE | private static final String | STRING_RSRC_PREFIX | private static final String | STRING_APP_NAME | private static final String | STRING_HELLO_WORLD | private static final String[] | DEFAULT_DIRECTORIES | private static final String[] | RES_DIRECTORIES | private static final String | PROJECT_LOGO_LARGE | private static final String | JAVA_ACTIVITY_TEMPLATE | private static final String | LAYOUT_TEMPLATE | private static final String | MAIN_LAYOUT_XML | protected static final String | MAIN_PAGE_NAME | private NewProjectCreationPage | mMainPage |
Methods Summary |
---|
private void | addDefaultDirectories(org.eclipse.core.resources.IProject project, java.lang.String parentFolder, java.lang.String[] folders, org.eclipse.core.runtime.IProgressMonitor monitor)Adds default directories to the project.
for (String name : folders) {
if (name.length() > 0) {
IFolder folder = project.getFolder(parentFolder + name);
if (!folder.exists()) {
folder.create(true /* force */, true /* local */,
new SubProgressMonitor(monitor, 10));
}
}
}
| private void | addIcon(org.eclipse.core.resources.IProject project, org.eclipse.core.runtime.IProgressMonitor monitor)Adds default application icon to the project.
IFile file = project.getFile(RES_DIRECTORY + AndroidConstants.WS_SEP
+ DRAWABLE_DIRECTORY + AndroidConstants.WS_SEP + ICON);
if (!file.exists()) {
// read the content from the template
byte[] buffer = AdtPlugin.readEmbeddedFile(TEMPLATES_DIRECTORY + ICON);
// if valid
if (buffer != null) {
// Save in the project
InputStream stream = new ByteArrayInputStream(buffer);
file.create(stream, false /* force */, new SubProgressMonitor(monitor, 10));
}
}
| private void | addManifest(org.eclipse.core.resources.IProject project, java.util.Map parameters, java.util.Map stringDictionary, org.eclipse.core.runtime.IProgressMonitor monitor)Adds the manifest to the project.
// get IFile to the manifest and check if it's not already there.
IFile file = project.getFile(AndroidConstants.FN_ANDROID_MANIFEST);
if (!file.exists()) {
// Read manifest template
String manifestTemplate = AdtPlugin.readEmbeddedTextFile(TEMPLATE_MANIFEST);
// Replace all keyword parameters
manifestTemplate = replaceParameters(manifestTemplate, parameters);
if (parameters.containsKey(PARAM_ACTIVITY)) {
// now get the activity template
String activityTemplate = AdtPlugin.readEmbeddedTextFile(TEMPLATE_ACTIVITIES);
// Replace all keyword parameters to make main activity.
String activities = replaceParameters(activityTemplate, parameters);
// set the intent.
String intent = AdtPlugin.readEmbeddedTextFile(TEMPLATE_INTENT_LAUNCHER);
// set the intent to the main activity
activities = activities.replaceAll(PH_INTENT_FILTERS, intent);
// set the activity(ies) in the manifest
manifestTemplate = manifestTemplate.replaceAll(PH_ACTIVITIES, activities);
} else {
// remove the activity(ies) from the manifest
manifestTemplate = manifestTemplate.replaceAll(PH_ACTIVITIES, "");
}
String minSdkVersion = (String) parameters.get(PARAM_MIN_SDK_VERSION);
if (minSdkVersion != null && minSdkVersion.length() > 0) {
String usesSdkTemplate = AdtPlugin.readEmbeddedTextFile(TEMPLATE_USES_SDK);
String usesSdk = replaceParameters(usesSdkTemplate, parameters);
manifestTemplate = manifestTemplate.replaceAll(PH_USES_SDK, usesSdk);
} else {
manifestTemplate = manifestTemplate.replaceAll(PH_USES_SDK, "");
}
// Save in the project as UTF-8
InputStream stream = new ByteArrayInputStream(
manifestTemplate.getBytes("UTF-8")); //$NON-NLS-1$
file.create(stream, false /* force */, new SubProgressMonitor(monitor, 10));
}
| public void | addPages()Adds pages to this wizard.
addPage(mMainPage);
| private void | addSampleCode(org.eclipse.core.resources.IProject project, java.lang.String sourceFolder, java.util.Map parameters, java.util.Map stringDictionary, org.eclipse.core.runtime.IProgressMonitor monitor)Creates the package folder and copies the sample code in the project.
// create the java package directories.
IFolder pkgFolder = project.getFolder(sourceFolder);
String packageName = (String) parameters.get(PARAM_PACKAGE);
// The PARAM_ACTIVITY key will be absent if no activity should be created,
// in which case activityName will be null.
String activityName = (String) parameters.get(PARAM_ACTIVITY);
Map<String, Object> java_activity_parameters = parameters;
if (activityName != null) {
if (activityName.indexOf('.") >= 0) {
// There are package names in the activity name. Transform packageName to add
// those sub packages and remove them from activityName.
packageName += "." + activityName; //$NON-NLS-1$
int pos = packageName.lastIndexOf('.");
activityName = packageName.substring(pos + 1);
packageName = packageName.substring(0, pos);
// Also update the values used in the JAVA_FILE_TEMPLATE below
// (but not the ones from the manifest so don't change the caller's dictionary)
java_activity_parameters = new HashMap<String, Object>(parameters);
java_activity_parameters.put(PARAM_PACKAGE, packageName);
java_activity_parameters.put(PARAM_ACTIVITY, activityName);
}
}
String[] components = packageName.split(AndroidConstants.RE_DOT);
for (String component : components) {
pkgFolder = pkgFolder.getFolder(component);
if (!pkgFolder.exists()) {
pkgFolder.create(true /* force */, true /* local */,
new SubProgressMonitor(monitor, 10));
}
}
if (activityName != null) {
// create the main activity Java file
String activityJava = activityName + AndroidConstants.DOT_JAVA;
IFile file = pkgFolder.getFile(activityJava);
if (!file.exists()) {
copyFile(JAVA_ACTIVITY_TEMPLATE, file, java_activity_parameters, monitor);
}
}
// create the layout file
IFolder layoutfolder = project.getFolder(RES_DIRECTORY).getFolder(LAYOUT_DIRECTORY);
IFile file = layoutfolder.getFile(MAIN_LAYOUT_XML);
if (!file.exists()) {
copyFile(LAYOUT_TEMPLATE, file, parameters, monitor);
if (activityName != null) {
stringDictionary.put(STRING_HELLO_WORLD, "Hello World, " + activityName + "!");
} else {
stringDictionary.put(STRING_HELLO_WORLD, "Hello World!");
}
}
| private void | addStringDictionaryFile(org.eclipse.core.resources.IProject project, java.util.Map strings, org.eclipse.core.runtime.IProgressMonitor monitor)Adds the string resource file.
// create the IFile object and check if the file doesn't already exist.
IFile file = project.getFile(RES_DIRECTORY + AndroidConstants.WS_SEP
+ VALUES_DIRECTORY + AndroidConstants.WS_SEP + STRINGS_FILE);
if (!file.exists()) {
// get the Strings.xml template
String stringDefinitionTemplate = AdtPlugin.readEmbeddedTextFile(TEMPLATE_STRINGS);
// get the template for one string
String stringTemplate = AdtPlugin.readEmbeddedTextFile(TEMPLATE_STRING);
// get all the string names
Set<String> stringNames = strings.keySet();
// loop on it and create the string definitions
StringBuilder stringNodes = new StringBuilder();
for (String key : stringNames) {
// get the value from the key
String value = strings.get(key);
// place them in the template
String stringDef = stringTemplate.replace(PARAM_STRING_NAME, key);
stringDef = stringDef.replace(PARAM_STRING_CONTENT, value);
// append to the other string
if (stringNodes.length() > 0) {
stringNodes.append("\n");
}
stringNodes.append(stringDef);
}
// put the string nodes in the Strings.xml template
stringDefinitionTemplate = stringDefinitionTemplate.replace(PH_STRINGS,
stringNodes.toString());
// write the file as UTF-8
InputStream stream = new ByteArrayInputStream(
stringDefinitionTemplate.getBytes("UTF-8")); //$NON-NLS-1$
file.create(stream, false /* force */, new SubProgressMonitor(monitor, 10));
}
| private void | copyFile(java.lang.String resourceFilename, org.eclipse.core.resources.IFile destFile, java.util.Map parameters, org.eclipse.core.runtime.IProgressMonitor monitor)Copies the given file from our resource folder to the new project.
Expects the file to the US-ASCII or UTF-8 encoded.
// Read existing file.
String template = AdtPlugin.readEmbeddedTextFile(
TEMPLATES_DIRECTORY + resourceFilename);
// Replace all keyword parameters
template = replaceParameters(template, parameters);
// Save in the project as UTF-8
InputStream stream = new ByteArrayInputStream(template.getBytes("UTF-8")); //$NON-NLS-1$
destFile.create(stream, false /* force */, new SubProgressMonitor(monitor, 10));
| private boolean | createAndroidProject()Creates the android project.
IWorkspace workspace = ResourcesPlugin.getWorkspace();
final IProject project = workspace.getRoot().getProject(mMainPage.getProjectName());
final IProjectDescription description = workspace.newProjectDescription(project.getName());
final Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put(PARAM_PROJECT, mMainPage.getProjectName());
parameters.put(PARAM_PACKAGE, mMainPage.getPackageName());
parameters.put(PARAM_APPLICATION, STRING_RSRC_PREFIX + STRING_APP_NAME);
parameters.put(PARAM_SDK_TOOLS_DIR, AdtPlugin.getOsSdkToolsFolder());
parameters.put(PARAM_IS_NEW_PROJECT, mMainPage.isNewProject());
parameters.put(PARAM_SRC_FOLDER, mMainPage.getSourceFolder());
parameters.put(PARAM_SDK_TARGET, mMainPage.getSdkTarget());
parameters.put(PARAM_MIN_SDK_VERSION, mMainPage.getMinSdkVersion());
if (mMainPage.isCreateActivity()) {
// 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 = mMainPage.getActivityName();
if (activityName.startsWith(".")) { //$NON-NLS-1$
activityName = activityName.substring(1);
}
parameters.put(PARAM_ACTIVITY, activityName);
}
// 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(STRING_APP_NAME, mMainPage.getApplicationName());
IPath path = mMainPage.getLocationPath();
IPath defaultLocation = Platform.getLocation();
if (!path.equals(defaultLocation)) {
description.setLocation(path);
}
if (mMainPage.isNewProject() && !mMainPage.useDefaultLocation() &&
!validateNewProjectLocationIsEmpty(path)) {
return false;
}
// Create a monitored operation to create the actual project
WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
@Override
protected void execute(IProgressMonitor monitor) throws InvocationTargetException {
createProjectAsync(project, description, monitor, parameters, stringDictionary);
}
};
// Run the operation in a different thread
runAsyncOperation(op);
return true;
| protected NewProjectCreationPage | createMainPage()Creates the wizard page.
Please do NOT override this method.
This is protected so that it can be overridden by unit tests.
However the contract of this class is private and NO ATTEMPT will be made
to maintain compatibility between different versions of the plugin.
return new NewProjectCreationPage(MAIN_PAGE_NAME);
| private void | createProjectAsync(org.eclipse.core.resources.IProject project, org.eclipse.core.resources.IProjectDescription description, org.eclipse.core.runtime.IProgressMonitor monitor, java.util.Map parameters, java.util.Map stringDictionary)Creates the actual project, sets its nature and adds the required folders
and files to it. This is run asynchronously in a different thread.
monitor.beginTask("Create Android Project", 100);
try {
// Create project and open it
project.create(description, new SubProgressMonitor(monitor, 10));
if (monitor.isCanceled()) throw new OperationCanceledException();
project.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(monitor, 10));
// Add the Java and android nature to the project
AndroidNature.setupProjectNatures(project, monitor);
// Create folders in the project if they don't already exist
addDefaultDirectories(project, AndroidConstants.WS_ROOT, DEFAULT_DIRECTORIES, monitor);
String[] sourceFolders = new String[] {
(String) parameters.get(PARAM_SRC_FOLDER),
GEN_SRC_DIRECTORY
};
addDefaultDirectories(project, AndroidConstants.WS_ROOT, sourceFolders, monitor);
// Create the resource folders in the project if they don't already exist.
addDefaultDirectories(project, RES_DIRECTORY, RES_DIRECTORIES, monitor);
// Setup class path: mark folders as source folders
IJavaProject javaProject = JavaCore.create(project);
for (String sourceFolder : sourceFolders) {
setupSourceFolder(javaProject, sourceFolder, monitor);
}
// Mark the gen source folder as derived
IFolder genSrcFolder = project.getFolder(AndroidConstants.WS_ROOT + GEN_SRC_DIRECTORY);
if (genSrcFolder.exists()) {
genSrcFolder.setDerived(true);
}
if (((Boolean) parameters.get(PARAM_IS_NEW_PROJECT)).booleanValue()) {
// Create files in the project if they don't already exist
addManifest(project, parameters, stringDictionary, monitor);
// add the default app icon
addIcon(project, monitor);
// Create the default package components
addSampleCode(project, sourceFolders[0], parameters, stringDictionary, monitor);
// add the string definition file if needed
if (stringDictionary.size() > 0) {
addStringDictionaryFile(project, stringDictionary, monitor);
}
// Set output location
javaProject.setOutputLocation(project.getFolder(BIN_DIRECTORY).getFullPath(),
monitor);
}
Sdk.getCurrent().setProject(project, (IAndroidTarget) parameters.get(PARAM_SDK_TARGET),
null /* apkConfigMap*/);
// Fix the project to make sure all properties are as expected.
// Necessary for existing projects and good for new ones to.
ProjectHelper.fixProject(project);
} catch (CoreException e) {
throw new InvocationTargetException(e);
} catch (IOException e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
}
| public void | init(org.eclipse.ui.IWorkbench workbench, org.eclipse.jface.viewers.IStructuredSelection selection)Initializes this creation wizard using the passed workbench and object
selection. Inherited from org.eclipse.ui.IWorkbenchWizard
setHelpAvailable(false); // TODO have help
setWindowTitle("New Android Project");
setImageDescriptor();
mMainPage = createMainPage();
mMainPage.setTitle("New Android Project");
mMainPage.setDescription("Creates a new Android Project resource.");
| public boolean | performFinish()Performs any actions appropriate in response to the user having pressed
the Finish button, or refuse if finishing now is not permitted: here, it
actually creates the workspace project and then switch to the Java
perspective.
if (!createAndroidProject()) {
return false;
}
// Open the default Java Perspective
OpenJavaPerspectiveAction action = new OpenJavaPerspectiveAction();
action.run();
return true;
| private org.eclipse.jdt.core.IClasspathEntry[] | removeSourceClasspath(org.eclipse.jdt.core.IClasspathEntry[] entries, org.eclipse.core.resources.IContainer folder)Removes the corresponding source folder from the class path entries if
found.
if (folder == null) {
return entries;
}
IClasspathEntry source = JavaCore.newSourceEntry(folder.getFullPath());
int n = entries.length;
for (int i = n - 1; i >= 0; i--) {
if (entries[i].equals(source)) {
IClasspathEntry[] newEntries = new IClasspathEntry[n - 1];
if (i > 0) System.arraycopy(entries, 0, newEntries, 0, i);
if (i < n - 1) System.arraycopy(entries, i + 1, newEntries, i, n - i - 1);
n--;
entries = newEntries;
}
}
return entries;
| private java.lang.String | replaceParameters(java.lang.String str, java.util.Map parameters)Replaces placeholders found in a string with values.
for (Entry<String, Object> entry : parameters.entrySet()) {
if (entry.getValue() instanceof String) {
str = str.replaceAll(entry.getKey(), (String) entry.getValue());
}
}
return str;
| private void | runAsyncOperation(org.eclipse.ui.actions.WorkspaceModifyOperation op)Runs the operation in a different thread and display generated
exceptions.
try {
getContainer().run(true /* fork */, true /* cancelable */, op);
} catch (InvocationTargetException e) {
// The runnable threw an exception
Throwable t = e.getTargetException();
if (t instanceof CoreException) {
CoreException core = (CoreException) t;
if (core.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS) {
// The error indicates the file system is not case sensitive
// and there's a resource with a similar name.
MessageDialog.openError(getShell(), "Error", "Error: Case Variant Exists");
} else {
ErrorDialog.openError(getShell(), "Error", null, core.getStatus());
}
} else {
// Some other kind of exception
MessageDialog.openError(getShell(), "Error", t.getMessage());
}
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
| private void | setImageDescriptor()Returns an image descriptor for the wizard logo.
ImageDescriptor desc = AdtPlugin.getImageDescriptor(PROJECT_LOGO_LARGE);
setDefaultPageImageDescriptor(desc);
| private void | setupSourceFolder(org.eclipse.jdt.core.IJavaProject javaProject, java.lang.String sourceFolder, org.eclipse.core.runtime.IProgressMonitor monitor)Adds the given folder to the project's class path.
IProject project = javaProject.getProject();
// Add "src" to class path
IFolder srcFolder = project.getFolder(sourceFolder);
IClasspathEntry[] entries = javaProject.getRawClasspath();
entries = removeSourceClasspath(entries, srcFolder);
entries = removeSourceClasspath(entries, srcFolder.getParent());
entries = ProjectHelper.addEntryToClasspath(entries,
JavaCore.newSourceEntry(srcFolder.getFullPath()));
javaProject.setRawClasspath(entries, new SubProgressMonitor(monitor, 10));
| private boolean | validateNewProjectLocationIsEmpty(org.eclipse.core.runtime.IPath destination)Before actually creating the project for a new project (as opposed to using an
existing project), we check if the target location is a directory that either does
not exist or is empty.
If it's not empty, ask the user for confirmation.
File f = new File(destination.toOSString());
if (f.isDirectory() && f.list().length > 0) {
return AdtPlugin.displayPrompt("New Android Project",
"You are going to create a new Android Project in an existing, non-empty, directory. Are you sure you want to proceed?");
}
return true;
|
|