| /* |
| * 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()); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |