/******************************************************************************* * Copyright (c) 2013, 2014 Red Hat, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Red Hat Inc. - initial API and implementation and/or initial documentation *******************************************************************************/ package org.eclipse.thym.ui.launch; import java.io.IOException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.ILaunchShortcut; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.thym.core.HybridProject; import org.eclipse.thym.core.HybridProjectLaunchConfigConstants; import org.eclipse.thym.ui.HybridUI; import org.eclipse.thym.ui.internal.cordova.RequirementsUtility; import org.eclipse.thym.ui.internal.status.StatusManager; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.ResourceUtil; /** * General hybrid mobile project launch shortcut. * * @author Gorkem Ercan * */ public abstract class HybridProjectLaunchShortcut implements ILaunchShortcut{ @Override public void launch(ISelection selection, String mode) { IStructuredSelection ssel = (IStructuredSelection) selection; Object selected = ssel.getFirstElement(); if(selected instanceof IAdaptable){ IAdaptable adaptable = (IAdaptable) selected; IProject project = (IProject)adaptable.getAdapter(IProject.class); if(project == null ){ IResource resource = (IResource) adaptable.getAdapter(IResource.class); if(resource != null ){ project = resource.getProject(); } } if(project != null){ launch(project); }else{ showEmptyError("Unable to determine a project to launch from selection."); } } } @Override public void launch(IEditorPart editor, String mode) { IFile file = ResourceUtil.getFile(editor.getEditorInput()); if (file != null) { IProject project = file.getProject(); launch(project); } else{ showEmptyError("Unable to determine the project to launch for from the editor."); } } private void launch(IProject project) { try { HybridProject hp = HybridProject.getHybridProject(project); if(!validateBuildToolsReady() || !shouldProceedWithLaunch(hp) || !RequirementsUtility.checkCordovaRequirements(hp) ){ return; } ILaunchConfiguration launchConfig = findOrCreateLaunchConfiguration(project); ILaunchConfigurationWorkingCopy wc = launchConfig.getWorkingCopy(); updateLaunchConfiguration(wc); launchConfig = wc.doSave(); DebugUITools.launch(launchConfig, "run"); } catch (CoreException e) { if (e.getCause() instanceof IOException) { Status status = new Status(IStatus.ERROR, HybridUI.PLUGIN_ID, "Unable to complete the build for target plarform", e.getCause()); StatusManager.handle(status); }else{ StatusManager.handle(e); } } } private void showEmptyError(String message){ MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Launch Failed", message); } /** * Creates a new launch configuration for the given project if one does not exists. * * @param project * @return * @throws CoreException */ private ILaunchConfiguration findOrCreateLaunchConfiguration(IProject project) throws CoreException{ ILaunchManager lm = getLaunchManager(); ILaunchConfigurationType configType = getLaunchConfigurationType(); ILaunchConfiguration[] confs = lm.getLaunchConfigurations(configType); for (ILaunchConfiguration configuration : confs) { if(isCorrectLaunchConfiguration(project, configuration)){ return configuration; } } return createLaunchConfiguration(project); } private ILaunchConfiguration createLaunchConfiguration(IProject project) throws CoreException{ ILaunchConfigurationWorkingCopy wc = getLaunchConfigurationType().newInstance(null, getLaunchManager().generateLaunchConfigurationName(getLaunchConfigurationNamePrefix(project))); wc.setAttribute(HybridProjectLaunchConfigConstants.ATTR_BUILD_SCOPE, project.getName()); return wc.doSave(); } private ILaunchManager getLaunchManager(){ return DebugPlugin.getDefault().getLaunchManager(); } private ILaunchConfigurationType getLaunchConfigurationType(){ ILaunchManager lm = DebugPlugin.getDefault().getLaunchManager(); String launchTypeID = getLaunchConfigurationTypeID(); Assert.isNotNull(launchTypeID); ILaunchConfigurationType configType = lm.getLaunchConfigurationType(launchTypeID); return configType; } protected boolean isCorrectLaunchConfiguration(IProject project, ILaunchConfiguration config) throws CoreException{ String projName = config.getAttribute(HybridProjectLaunchConfigConstants.ATTR_BUILD_SCOPE, (String)null); if(project.getName().equals(projName)){ return true; } return false; } /** * Invoked before commencing with the launch to give platform a chance * to check if the prerequisites for a build are in place. * Implementors should throw a {@link CoreException} with a * Status message. * * @return true if the tools are installed and ready * * @throws CoreException if build tools are not working properly or * does not exist */ protected abstract boolean validateBuildToolsReady() throws CoreException; /** * Return the launchConfiguratonType ID. Which will be used to * create a launch configuration. * @return launchConfig id */ protected abstract String getLaunchConfigurationTypeID(); /** * Last chance for implementors to abort the launch. Default * implementation checks the validity of the project. * * @param project * @return */ protected boolean shouldProceedWithLaunch(HybridProject project){ return project != null; } /** * Return the name prefix to be used when a name is generated * for this launch configuration. * * @return a launch configuration name */ protected abstract String getLaunchConfigurationNamePrefix(IProject project); /** * Update the launch configuration with platform implementation specific values. * * @param wc */ protected void updateLaunchConfiguration(ILaunchConfigurationWorkingCopy wc){ } }