/** * Copyright (c) 2013 by JP Moresmau * This code is made available under the terms of the Eclipse Public License, * version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html */ package net.sf.eclipsefp.haskell.debug.ui.internal.launch; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import net.sf.eclipsefp.haskell.compat.ILaunchManagerCompat; import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescriptionStanza; import net.sf.eclipsefp.haskell.core.util.ResourceUtil; import net.sf.eclipsefp.haskell.debug.core.internal.HaskellDebugCore; import net.sf.eclipsefp.haskell.debug.core.internal.launch.ILaunchAttributes; import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; /** * common code for launching executables and test suite * @author JP Moresmau * */ public abstract class ExecutableOrTestSuiteLaunchOperation extends LaunchOperation { public void launch( final IResource resource, final IProgressMonitor monitor,final PackageDescriptionStanza stanza ) throws CoreException { if( resource != null ) { IProject project = resource.getProject(); if(ResourceUtil.hasHaskellNature (project) ) { Map<String,IFile> executables=getExecutables(project); ILaunchConfiguration configuration = getConfiguration( project,executables,stanza ); if( configuration != null ) { configuration.launch( ILaunchManager.RUN_MODE, monitor ); } } } } protected Map<String,IFile> getExecutables(final IProject project){ /** offer the option to run a test executable without any special options and processing **/ Map<String,IFile> m=new HashMap<>(); m.putAll(ResourceUtil.getProjectExecutables( project )); m.putAll(ResourceUtil.getProjectTestSuites( project )); m.putAll(ResourceUtil.getProjectBenchmarks( project )); return m; } protected ILaunchConfiguration getConfiguration( final IProject project, final Map<String,IFile> executables ,final PackageDescriptionStanza stanza) throws CoreException { List<ILaunchConfiguration> configurations = findConfiguration( project,getConfigTypeName(),stanza ); // match existing configurations with executables Set<String> exesExisting=new HashSet<> (); for (Iterator<ILaunchConfiguration> it=configurations.iterator();it.hasNext();){ ILaunchConfiguration c=it.next(); String exe=getExePath( c ); if (exe!=null && exe.length()>0 && new File(exe).exists()){ exesExisting.add( exe ); } else { it.remove(); } } ILaunchConfiguration result = null; /*IFile exe=null; if (stanza!=null){ exe=ResourceUtil.getExecutableLocation( project, stanza.getName() ); }*/ for( String s:executables.keySet() ) { String exe1=getExePath( executables.get( s ) ); if (!exesExisting.contains(exe1)){ if (stanza==null || stanza.getName().equals(s)){ configurations.add( createConfiguration(project, s ) ); } } } int count = configurations.size(); if( count == 1 ) { // If there is exactly one config associated with the // ICompilationUnit, // return it. result = configurations.get( 0 ); } else if (count>1){ // Otherwise, if there is more than one config associated with the // ICompilationUnit, prompt the user to choose one. result = choose( configurations ); } return result; } private ILaunchConfiguration createConfiguration(final IProject proj, final String stanza ) throws CoreException { ILaunchConfigurationType configType = getConfigType(); String id = createConfigId( stanza ); ILaunchConfigurationWorkingCopy wc = configType.newInstance( null, id ); wc.setAttribute( ILaunchAttributes.STANZA, stanza ); // wc.setAttribute( ILaunchAttributes.EXECUTABLE, exePath ); wc.setAttribute( ILaunchAttributes.WORKING_DIRECTORY, proj.getLocation().toOSString() ); wc.setAttribute( ILaunchAttributes.PROJECT_NAME, proj.getName() ); wc.setAttribute( ILaunchAttributes.SYNC_STREAMS, true ); return wc.doSave(); } private String getExePath( final IFile executable ) { String result = executable.getLocation().toOSString(); if( !new File( result ).exists() ) { String msg = "Could not locate the project executable - supposed to be " + result; //$NON-NLS-1$ HaskellUIPlugin.log( msg, IStatus.ERROR ); } return result; } public static List<ILaunchConfiguration> findConfiguration( final IProject project,final String configTypeName,final PackageDescriptionStanza stanza ) throws CoreException { List<ILaunchConfiguration> result = new LinkedList<>(); ILaunchConfiguration[] configurations = LaunchOperation .getConfigurations( LaunchOperation .getConfigType( configTypeName ) ); IFile exe=null; if (stanza!=null){ exe=ResourceUtil.getExecutableLocation( project, stanza.getName() ); } result = new ArrayList<>( configurations.length ); for( int i = 0; i < configurations.length; i++ ) { ILaunchConfiguration configuration = configurations[ i ]; String thisProject=configuration.getAttribute( ILaunchAttributes.PROJECT_NAME, (String)null ); if (project.getName().equals( thisProject )){ // String exePath = getExePath( file ); String projectName = project.getName(); if (exe!=null){ if (getExePath( configuration ).equals( exe.getLocation().toOSString() )){ result.add( configuration ); } } else { if( getExePath( configuration ).startsWith( project.getLocation().toOSString() ) && HaskellDebugCore.getProjectName( configuration ).equals( projectName ) ) { result.add( configuration ); } } } } return result; } @Override protected String createConfigId( final String stanza ) { //String name = file.getName(); // FIXME: Remove when Galileo is no longer supported. ILaunchManager mgr = getLaunchManager(); return ILaunchManagerCompat.generateLaunchConfigurationName( mgr, stanza ); } }