diff options
Diffstat (limited to 'src/plugins/android/src/com/motorola/studio/android/wizards/project/NewAndroidProjectWizard.java')
-rw-r--r-- | src/plugins/android/src/com/motorola/studio/android/wizards/project/NewAndroidProjectWizard.java | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/src/plugins/android/src/com/motorola/studio/android/wizards/project/NewAndroidProjectWizard.java b/src/plugins/android/src/com/motorola/studio/android/wizards/project/NewAndroidProjectWizard.java new file mode 100644 index 0000000..e44b40e --- /dev/null +++ b/src/plugins/android/src/com/motorola/studio/android/wizards/project/NewAndroidProjectWizard.java @@ -0,0 +1,441 @@ +/* + * 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.wizards.project; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceDescription; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.core.runtime.SubMonitor; +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.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.osgi.util.NLS; +import org.eclipse.ui.INewWizard; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard; +import org.osgi.framework.Bundle; + +import com.android.sdklib.IAndroidTarget; +import com.motorola.studio.android.AndroidPlugin; +import com.motorola.studio.android.common.log.StudioLogger; +import com.motorola.studio.android.common.preferences.DialogWithToggleUtils; +import com.motorola.studio.android.common.utilities.EclipseUtils; +import com.motorola.studio.android.i18n.AndroidNLS; +import com.motorola.studio.android.model.AndroidProject; +import com.motorola.studio.android.obfuscate.ObfuscatorManager; + +/** + * Class that represents the Android New Project Wizard + */ +public class NewAndroidProjectWizard extends BasicNewProjectResourceWizard implements INewWizard +{ + private static final String WIZARD_BANNER = "icons/wizban/newprjwiz.png"; //$NON-NLS-1$ + + protected static final String NATIVE_PAGE_NAME = "native_page"; //$NON-NLS-1$ + + protected static final String SAMPLE_PAGE_NAME = + AndroidNLS.UI_SampleSelectionPage_TitleSourcePage; + + private final AndroidProject project = new AndroidProject(); + + private WizardPage nativePage = null; + + private NewAndroidProjectMainPage mainPage = null; + + private Class<?> nativePageClass = null; + + private Object classInstance = null; + + /* (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#canFinish() + */ + + @Override + public boolean canFinish() + { + boolean canFinish = + (project.getStatus().getSeverity() != IStatus.ERROR) + && !project.needMoreInformation(); + + if ((nativePage != null) && !nativePage.isPageComplete() && project.isAddingNativeSupport()) + { + canFinish = false; + } + + return canFinish; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard#performFinish() + */ + @Override + public boolean performFinish() + { + DoSave doSave = new DoSave(); + + try + { + getContainer().run(false, false, doSave); + } + catch (Exception e) + { + String errMsg = + NLS.bind( + AndroidNLS.EXC_NewAndroidProjectWizard_AnErrorHasOccurredWhenCreatingTheProject, + e.getLocalizedMessage()); + StudioLogger.error(NewAndroidProjectWizard.class, errMsg, e); + + EclipseUtils.showErrorDialog(AndroidNLS.UI_GenericErrorDialogTitle, errMsg, null); + } + boolean success = doSave.isSaved(); + + if (success) + { + // Collecting usage data for statistical purposes + try + { + StudioLogger.collectUsageData(StudioLogger.WHAT_APP_MANAGEMENT_CREATE, + StudioLogger.KIND_APP_MANAGEMENT, this.project.getSourceType().name() + .toLowerCase(), AndroidPlugin.PLUGIN_ID, AndroidPlugin.getDefault() + .getBundle().getVersion().toString()); + } + catch (Throwable e) + { + //Do nothing, but error on the log should never prevent app from working + } + } + + return success; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#performCancel() + */ + @Override + public boolean performCancel() + { + try + { + project.finalize(); + } + catch (Throwable e) + { + StudioLogger.error(NewAndroidProjectWizard.class, e.getLocalizedMessage(), e); + } + return super.performCancel(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard#addPages() + */ + + @SuppressWarnings( + { + "unchecked" + }) + @Override + public void addPages() + { + + classInstance = null; + + try + { + Bundle seqBundle = Platform.getBundle("org.eclipse.sequoyah.android.cdt.build.ui"); //$NON-NLS-1$ + if (seqBundle != null) + { + nativePageClass = + seqBundle + .loadClass("org.eclipse.sequoyah.android.cdt.internal.build.ui.AddNativeProjectPage"); //$NON-NLS-1$ + + Class<Boolean> bClass = boolean.class; + Class[] paramTypes = + { + bClass + }; + + Constructor cs = nativePageClass.getConstructor(paramTypes); + classInstance = cs.newInstance(true); + nativePage = (WizardPage) classInstance; + } + } + catch (Exception e) + { + StudioLogger.error(NewAndroidProjectWizard.class, e.getMessage(), e); + } + + if (nativePage != null) + { + mainPage = new NewAndroidProjectMainPage(project, true); + addPage(mainPage); + addPage(nativePage); + } + else + { + mainPage = new NewAndroidProjectMainPage(project, false); + addPage(mainPage); + } + addPage(new SampleSelectionPage(project)); + + } + + /* (non-Javadoc) + * @see org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard#init(org.eclipse.ui.IWorkbench, org.eclipse.jface.viewers.IStructuredSelection) + */ + @Override + public void init(IWorkbench workbench, IStructuredSelection selection) + { + setWindowTitle(AndroidNLS.UI_NewAndroidProjectWizard_TitleNewProjectWizard); + setNeedsProgressMonitor(true); + setDefaultPageImageDescriptor(AndroidPlugin.getImageDescriptor(WIZARD_BANNER)); + } + + /** + * Implements an IRunnableWithProgress to run the save process + */ + private class DoSave implements IRunnableWithProgress + { + private static final String OPHONE_JAR = "oms.jar"; //$NON-NLS-1$ + + private static final String OPHONESDK_PROMPT_KEY = "OphoneSDK"; //$NON-NLS-1$ + + private boolean saved = false; + + /** + * Returns whether the project was saved/created successfuly. + * + * @return Returns <code>true</code> in case the project is saved/creates successfully. + */ + public boolean isSaved() + { + return saved; + } + + public void run(IProgressMonitor monitor) throws InvocationTargetException, + InterruptedException + { + SubMonitor subMonitor = SubMonitor.convert(monitor, 20); + + subMonitor.beginTask(AndroidNLS.NewAndroidProjectWizard_Message_CreatingAndroidProject, + 10); + + // Gets the auto-building configuration to set it back in the end + final boolean autoBuild = ResourcesPlugin.getWorkspace().isAutoBuilding(); + + final IWorkspaceDescription wsd = ResourcesPlugin.getWorkspace().getDescription(); + wsd.setAutoBuilding(false); + try + { + // Set auto-build off for performance reasons + ResourcesPlugin.getWorkspace().setDescription(wsd); + } + catch (CoreException e) + { + // there is no need to stop the process because auto-build only improves performance, it does not interferes with the new project creation. + StudioLogger.error(NewAndroidProjectWizard.class, + "Error cleaning workspace after project creation: " + e.getMessage()); //$NON-NLS-1$ + } + + // worked 1 + subMonitor.worked(1); + + saved = project.save(getContainer(), subMonitor); + updatePerspective(); + + IProject newProject = + ResourcesPlugin.getWorkspace().getRoot().getProject(project.getName()); + + addOphoneSDK(newProject, subMonitor); + + try + { + newProject.build(IncrementalProjectBuilder.CLEAN_BUILD, subMonitor); + } + catch (Exception e1) + { + // even if the build fais, the project could still be created, therefore it must continue + StudioLogger.error(NewAndroidProjectWizard.class, + "Sleep error when cleaning workspace after project creation: " //$NON-NLS-1$ + + e1.getMessage()); + } + + // worked 4 + subMonitor.worked(3); + + wsd.setAutoBuilding(autoBuild); + try + { + // rollback the auto-building setting to the original state + ResourcesPlugin.getWorkspace().setDescription(wsd); + } + catch (CoreException e) + { + // the auto-building does not interfere with the project creation, therefore in case it fails, the process may contine + StudioLogger.error(NewAndroidProjectWizard.class, + "Error cleaning workspace after project creation: " + e.getMessage()); //$NON-NLS-1$ + } + + // worked 5 + subMonitor.worked(1); + + if ((nativePage != null) && project.isAddingNativeSupport() && saved) + { + try + { + Class<IWorkbenchWindow> workbenchClass = IWorkbenchWindow.class; + Class<IProject> projectClass = IProject.class; + Class<IProgressMonitor> progressMonitorClass = IProgressMonitor.class; + + IProject createdProject = + ResourcesPlugin.getWorkspace().getRoot().getProject(project.getName()); + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + + QualifiedName libQN = + new QualifiedName(AndroidPlugin.PLUGIN_ID, + AndroidPlugin.LIB_LOCATION_PROPERTY); + + //get library name field from wizard + Method getLibraryName = + nativePageClass.getMethod("getLibraryName", (Class[]) null); //$NON-NLS-1$ + getLibraryName.setAccessible(true); + Object returnValue = getLibraryName.invoke(classInstance, (Object[]) null); + + //set project library name property + createdProject.setPersistentProperty(libQN, returnValue.toString()); + + // worked 6 + subMonitor.worked(1); + + Object[] performFinishMethodArguments = + { + window, createdProject, subMonitor.newChild(4) + }; + + Class<?>[] performFinishMethodParameterTypes = + { + workbenchClass, projectClass, progressMonitorClass + }; + + //invoke page perform finish that will add native support to the brand new project + Method performFinish = nativePageClass.getMethod("performFinish", //$NON-NLS-1$ + performFinishMethodParameterTypes); + performFinish.setAccessible(true); + + returnValue = performFinish.invoke(classInstance, performFinishMethodArguments); + + //update success flag + saved = saved && (Boolean) returnValue; + } + catch (Exception e) + { + // the project may be in a inconsistent state - throw an exception + saved = false; + StudioLogger.error(NewAndroidProjectWizard.class, e.getMessage(), e); + throw new InvocationTargetException(e); + } + } + + //add proguard file inside project + try + { + if (project.needToObfuscate()) + { + ObfuscatorManager.obfuscate(newProject, subMonitor.newChild(10)); + } + newProject.refreshLocal(IResource.DEPTH_INFINITE, subMonitor); + } + catch (Exception e) + { + StudioLogger.error(NewAndroidProjectWizard.class, e.getMessage(), e); + throw new InvocationTargetException(e); + } + } + + private void addOphoneSDK(IProject p, IProgressMonitor monitor) + { + IAndroidTarget sdkTarget = project.getSdkTarget(); + File platformLocation = new File(sdkTarget.getLocation()); + File[] listFiles = platformLocation.listFiles(); + + boolean found = false; + int i = 0; + File file = null; + while (!found && (i < listFiles.length)) + { + file = listFiles[i]; + if (file.getName().equals(OPHONE_JAR)) + { + found = true; + } + i++; + } + + if (found) + { + boolean addClasspath = + DialogWithToggleUtils.showQuestion(OPHONESDK_PROMPT_KEY, + AndroidNLS.NewAndroidProjectWizard_OPhonePromptTitle, + AndroidNLS.NewAndroidProjectWizard_OPhonePromptMessage); + + if (addClasspath) + { + IJavaProject javaProject = JavaCore.create(p); + if ((javaProject != null) && javaProject.exists()) + { + try + { + javaProject.open(monitor); + IClasspathEntry[] rawClasspath = javaProject.getRawClasspath(); + IClasspathEntry[] newClasspath = + new IClasspathEntry[rawClasspath.length + 1]; + + System.arraycopy(rawClasspath, 0, newClasspath, 0, rawClasspath.length); + newClasspath[newClasspath.length - 1] = + JavaCore.newLibraryEntry(new Path(file.getAbsolutePath()), + null, null); + javaProject.setRawClasspath(newClasspath, monitor); + } + catch (JavaModelException e) + { + StudioLogger.error(NewAndroidProjectWizard.class, + "Error while setting up the oms.jar on the project classpath: " //$NON-NLS-1$ + + e.getMessage()); + } + } + } + } + } + } +} |