/*******************************************************************************
* This file is protected by Copyright.
* Please refer to the COPYRIGHT file distributed with this source distribution.
*
* This file is part of REDHAWK IDE.
*
* 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
*******************************************************************************/
package gov.redhawk.ide.sdr.ui.export;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.externaltools.internal.IExternalToolConstants;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
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.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.emf.common.ui.dialogs.DiagnosticDialog;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreValidator;
import org.eclipse.emf.transaction.RunnableWithResult;
import org.eclipse.emf.transaction.RunnableWithResult.Impl;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.osgi.service.prefs.BackingStoreException;
import gov.redhawk.ide.RedhawkIdeActivator;
import gov.redhawk.ide.codegen.CodegenUtil;
import gov.redhawk.ide.codegen.ImplementationSettings;
import gov.redhawk.ide.natures.ScaComponentProjectNature;
import gov.redhawk.ide.natures.ScaNodeProjectNature;
import gov.redhawk.ide.natures.ScaWaveformProjectNature;
import gov.redhawk.ide.sdr.ui.SdrUiPlugin;
import gov.redhawk.model.sca.util.ModelUtil;
import mil.jpeojtrs.sca.dcd.DcdPackage;
import mil.jpeojtrs.sca.dcd.DeviceConfiguration;
import mil.jpeojtrs.sca.sad.SadPackage;
import mil.jpeojtrs.sca.sad.SoftwareAssembly;
import mil.jpeojtrs.sca.scd.ComponentType;
import mil.jpeojtrs.sca.scd.SoftwareComponent;
import mil.jpeojtrs.sca.spd.Implementation;
import mil.jpeojtrs.sca.spd.SoftPkg;
import mil.jpeojtrs.sca.spd.SpdPackage;
import mil.jpeojtrs.sca.util.ScaResourceFactoryUtil;
/**
* @since 3.1
*/
@SuppressWarnings("restriction")
public class ExportUtils {
private ExportUtils() {
}
/**
* Exports waveforms from the specified project using the provided exporter.
* @param proj The project to search for waveforms
* @param exporter The IScaExporter to use
* @param monitor The progress monitor to use for reporting progress to the user. It is the caller's responsibility
* to call done() on the given monitor. Accepts null, indicating that no progress should be reported and
* that the operation cannot be canceled.
* @since 2.0
*/
public static void exportWaveform(final IProject proj, final IScaExporter exporter, final IProgressMonitor monitor) throws CoreException, IOException {
if (!proj.hasNature(ScaWaveformProjectNature.ID)) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Project missing required nature"));
}
if (!ExportUtils.checkProject(proj)) {
return;
}
// Find .sad.xml files
final List<IResource> sadFiles = new ArrayList<IResource>();
for (final IResource child : proj.members()) {
if (child.getName().endsWith(SadPackage.FILE_EXTENSION)) {
sadFiles.add(child);
}
}
final SubMonitor progress = SubMonitor.convert(monitor, "Exporting waveforms", sadFiles.size() * 2);
for (final IResource sadFile : sadFiles) {
// Load the SAD file
final ResourceSet resourceSet = ScaResourceFactoryUtil.createResourceSet();
final Resource resource = resourceSet.getResource(URI.createURI(sadFile.getLocationURI().toString()), true);
final SoftwareAssembly sad = ModelUtil.getSoftwareAssembly(resource);
// Validate name
String name = sad.getName();
if (name == null || name.isEmpty()) {
throw new CoreException(
new Status(IStatus.ERROR, SdrUiPlugin.PLUGIN_ID, "Cannot export a project with an empty name. Check the project's SAD file."));
}
// Validate against the ecore model
if (!validateEcore(sad, sad.getName())) {
return;
}
// Make directory & copy SAD file
final IPath outputFolder = new Path("dom/waveforms").append(name.replace('.', File.separatorChar));
exporter.mkdir(outputFolder, progress.newChild(1));
exporter.write(sadFile, outputFolder.append(sadFile.getName()), progress.newChild(1));
}
progress.done();
}
private static boolean validateEcore(EObject object, String projectName) {
// Get all resource contents, we are validating everything
TreeIterator<EObject> allContents = object.eResource().getAllContents();
boolean modelIsValid = true;
BasicDiagnostic diagnostic = new BasicDiagnostic();
while (allContents.hasNext()) {
boolean validatorResult = EcoreValidator.INSTANCE.validate(allContents.next(), diagnostic, null);
// Update flag only once if error found. But we need to cycle through everything so we
// can display multiple errors at once via BasicDiagnostic.getChildren()
modelIsValid = modelIsValid && validatorResult;
}
if (!modelIsValid) {
boolean exportProject = showWarningDialog(projectName, diagnostic);
if (!exportProject) {
// User chose not to continue export
return false;
}
}
return true;
}
/**
* @return false if the user wants to cancel the export operation
*/
private static boolean showWarningDialog(final String projectName, final BasicDiagnostic diagnostic) {
// Dialog has to be in the UI thread. Update the static variable since Runnable is a void return.
Impl<Boolean> runnable = new RunnableWithResult.Impl<Boolean>() {
public void run() {
setResult(true);
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
Dialog warnDialog = new DiagnosticDialog(shell, "Invalid Model", null, diagnostic, Diagnostic.ERROR | Diagnostic.WARNING) {
@Override
protected Control createMessageArea(final Composite composite) {
this.message = "Errors have been detected in " + projectName + ". Do you want to continue export to Target SDR?";
return super.createMessageArea(composite);
}
@Override
protected void createButtonsForButtonBar(final Composite parent) {
// create Yes, No and Details buttons
createButton(parent, IDialogConstants.OK_ID, IDialogConstants.YES_LABEL, true);
createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.NO_LABEL, true);
createDetailsButton(parent);
}
};
if (warnDialog.open() == IDialogConstants.CANCEL_ID) {
setResult(false);
}
}
};
Display.getDefault().syncExec(runnable);
return runnable.getResult();
}
/**
* Exports components from the specified project using the provided exporter.
*
* @param proj The project to search for components
* @param exporter The IScaExporter to use
* @param monitor The progress monitor to use for reporting progress to the user. It is the caller's responsibility
* to call done() on the given monitor. Accepts null, indicating that no progress should be reported and
* that the operation cannot be canceled.
* @since 2.0
*/
public static void exportComponent(final IProject proj, final IScaExporter exporter, final IProgressMonitor monitor) throws CoreException, IOException {
if (!proj.hasNature(ScaComponentProjectNature.ID)) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Project missing required nature"));
}
if (!ExportUtils.checkProject(proj)) {
return;
}
if (useBuildSH(proj)) {
buildSH(monitor, proj);
} else {
ExportUtils.basicExportComponent(proj, exporter, true, monitor);
}
}
/**
* Exports nodes from the specified project using the provided exporter.
* @param proj The project to search for nodes
* @param exporter The IScaExporter to use
* @param monitor The progress monitor to use for reporting progress to the user. It is the caller's responsibility
* to call done() on the given monitor. Accepts null, indicating that no progress should be reported and
* that the operation cannot be canceled.
* @since 2.0
*/
public static void exportNode(final IProject proj, final IScaExporter exporter, final IProgressMonitor monitor) throws CoreException, IOException {
if (!proj.hasNature(ScaNodeProjectNature.ID)) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Project missing required nature"));
}
if (!ExportUtils.checkProject(proj)) {
return;
}
// Find node files
final List<IResource> dcdFiles = new ArrayList<IResource>();
for (final IResource child : proj.members()) {
if (child.getName().endsWith(DcdPackage.FILE_EXTENSION)) {
dcdFiles.add(child);
}
}
final SubMonitor progress = SubMonitor.convert(monitor, "Exporting nodes", dcdFiles.size() * 2);
for (final IResource dcdFile : dcdFiles) {
// Load the DCD file
final ResourceSet resourceSet = ScaResourceFactoryUtil.createResourceSet();
final Resource resource = resourceSet.getResource(URI.createURI(dcdFile.getLocationURI().toString()), true);
final DeviceConfiguration dcd = ModelUtil.getDeviceConfiguration(resource);
// Validate name
String name = dcd.getName();
if (name == null || name.isEmpty()) {
throw new CoreException(
new Status(IStatus.ERROR, SdrUiPlugin.PLUGIN_ID, "Cannot export a project with an empty name. Check the project's DCD file."));
}
// Validate against the ecore model
if (!validateEcore(dcd, dcd.getName())) {
return;
}
// Make directory & copy DCD file
final IPath outputFolder = new Path("dev/nodes").append(name.replace('.', File.separatorChar));
exporter.mkdir(outputFolder, progress.newChild(1));
exporter.write(dcdFile, outputFolder.append(dcdFile.getName()), progress.newChild(1));
}
progress.done();
}
/**
* @return System environment overridden with preference values
* @since 4.0
*/
public static Map<String, String> getEnv() {
Map<String, String> env = new HashMap<String, String>(System.getenv());
IPath targetSDRPath = SdrUiPlugin.getDefault().getTargetSdrPath();
env.put("SDRROOT", targetSDRPath.toOSString());
IPath ossiehome = RedhawkIdeActivator.getDefault().getRuntimePath();
env.put("OSSIEHOME", ossiehome.toOSString());
if (env.containsKey("CLASSPATH")) {
env.put("CLASSPATH", ossiehome.toOSString() + "/lib/*:" + env.get("CLASSPATH"));
} else {
env.put("CLASSPATH", ossiehome.toOSString() + "/lib/*");
}
if (env.containsKey("PYTHONPATH")) {
if (Platform.ARCH_X86_64.equals(Platform.getOSArch())) {
env.put("PYTHONPATH", ossiehome.toOSString() + "/lib64/python:" + ossiehome.toOSString() + "/lib/python:" + env.get("PYTHONPATH"));
} else {
env.put("PYTHONPATH", ossiehome.toOSString() + "/lib/python:" + env.get("PYTHONPATH"));
}
} else {
if (Platform.ARCH_X86_64.equals(Platform.getOSArch())) {
env.put("PYTHONPATH", ossiehome.toOSString() + "/lib64/python:" + ossiehome.toOSString() + "/lib/python");
} else {
env.put("PYTHONPATH", ossiehome.toOSString() + "/lib/python");
}
}
if (env.containsKey("LD_LIBRARY_PATH")) {
if (Platform.ARCH_X86_64.equals(Platform.getOSArch())) {
env.put("LD_LIBRARY_PATH", ossiehome.toOSString() + "/lib64:" + ossiehome.toOSString() + "/lib:" + env.get("LD_LIBRARY_PATH"));
} else {
env.put("LD_LIBRARY_PATH", ossiehome.toOSString() + "/lib:" + env.get("LD_LIBRARY_PATH"));
}
} else {
if (Platform.ARCH_X86_64.equals(Platform.getOSArch())) {
env.put("LD_LIBRARY_PATH", ossiehome.toOSString() + "/lib64:" + ossiehome.toOSString() + "/lib");
} else {
env.put("LD_LIBRARY_PATH", ossiehome.toOSString() + "/lib");
}
}
if (env.containsKey("PATH")) {
env.put("PATH", ossiehome.toOSString() + "/bin/:" + env.get("PATH"));
} else {
env.put("PATH", ossiehome.toOSString() + "/bin/");
}
return env;
}
/**
* Shared by {@link #exportDevice(IProject, IScaExporter, IProgressMonitor)},
* {@link #exportComponent(IProject, IScaExporter, IProgressMonitor)}, and
* {@link #exportNode(IProject, IScaExporter, IProgressMonitor)} to perform common export functions.
*
* @param proj The project to search for software packages
* @param exporter The IScaExporter to use
* @param includeCode If code should be copied with the component
* @param monitor The progress monitor to use for reporting progress to the user. It is the caller's responsibility
* to call done() on the given monitor. Accepts null, indicating that no progress should be reported and
* that the operation cannot be canceled.
*/
private static void basicExportComponent(final IProject proj, final IScaExporter exporter, final boolean includeCode, final IProgressMonitor monitor)
throws CoreException, IOException {
if (!proj.hasNature(ScaComponentProjectNature.ID)) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Project missing required nature"));
}
// Find .spd.xml files
final List<IResource> spds = new ArrayList<IResource>();
for (final IResource child : proj.members()) {
if (child.getName().endsWith(SpdPackage.FILE_EXTENSION)) {
spds.add(child);
}
}
final SubMonitor allComponentsProgress = SubMonitor.convert(monitor, "Exporting SPD resources...", spds.size());
final int SPD_WORK = 1;
final int PRF_WORK = 1;
final int SCD_WORK = 1;
final int MKDIR_WORK = 1;
final int IMPL_WORK = 96;
for (final IResource spdResource : spds) {
final SubMonitor progress = allComponentsProgress.newChild(1);
progress.beginTask("Exporting resources of " + spdResource.getName(), SPD_WORK + PRF_WORK + SCD_WORK + IMPL_WORK + MKDIR_WORK);
// Now load the SPD file and copy the prf and scd files, if any
final ResourceSet resourceSet = ScaResourceFactoryUtil.createResourceSet();
final Resource resource = resourceSet.getResource(URI.createURI(spdResource.getLocationURI().toString()), true);
final SoftPkg softPkg = ModelUtil.getSoftPkg(resource);
IPath outputFolder = null;
ComponentType type = ComponentType.OTHER;
if ((softPkg.getDescriptor() != null) && (softPkg.getDescriptor().getComponent() != null)) {
final SoftwareComponent component = softPkg.getDescriptor().getComponent();
type = SoftwareComponent.Util.getWellKnownComponentType(component);
}
switch (type) {
case DEVICE:
outputFolder = new Path("dev/devices");
break;
case DEVICE_MANAGER:
outputFolder = new Path("dev/nodes");
break;
case DOMAIN_MANAGER:
outputFolder = new Path("dom/mgr");
break;
case EVENT_SERVICE:
case SERVICE:
outputFolder = new Path("dev/services");
break;
case FILE_MANAGER:
case FILE_SYSTEM:
case LOG:
case NAMING_SERVICE:
case RESOURCE:
case OTHER:
case RESOURCE_FACTORY:
outputFolder = new Path("dom/components");
break;
default:
throw new CoreException(new Status(IStatus.ERROR, SdrUiPlugin.PLUGIN_ID, "Unknown component type: " + type));
}
final IPath spdRootPath = spdResource.getFullPath().removeLastSegments(1);
// If we were told to include code make sure at least one implementation has generated code.
if (includeCode) {
if (!ExportUtils.checkProjectImplsForExport(softPkg, spdRootPath)) {
return;
}
}
outputFolder = outputFolder.append(proj.getName().replace('.', File.separatorChar));
// Copy the SPD File
final IPath spdOutputPath = outputFolder.append(spdResource.getName());
IResource prfResource = null;
IPath prfOutputPath = null;
if (softPkg.getPropertyFile() != null) {
final IPath prfPath = new Path(softPkg.getPropertyFile().getLocalFile().getName());
if (prfPath.isAbsolute()) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Cannot export absolute path localfile paths"));
}
prfResource = ExportUtils.getWorkspaceResource(spdRootPath.append(prfPath));
if (prfResource == null) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Expected file " + prfPath + " does not exist"));
}
prfOutputPath = outputFolder.append(prfPath);
}
IResource scdResourcePath = null;
IPath scdOutputPath = null;
if (softPkg.getDescriptor() != null) {
final IPath scdPath = new Path(softPkg.getDescriptor().getLocalfile().getName());
if (scdPath.isAbsolute()) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Cannot export absolute path localfile paths"));
}
scdResourcePath = ExportUtils.getWorkspaceResource(spdRootPath.append(scdPath));
if (scdResourcePath == null) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Expected file " + scdPath + " does not exist"));
}
scdOutputPath = outputFolder.append(scdPath);
}
progress.setWorkRemaining(IMPL_WORK);
boolean useExporter = true;
if (softPkg.getImplementation() != null) {
int implWork = softPkg.getImplementation().size() * (PRF_WORK + ((includeCode) ? IMPL_WORK : 0)); // SUPPRESS
// CHECKSTYLE
// INLINE
progress.setWorkRemaining(implWork);
for (final Implementation impl : softPkg.getImplementation()) {
useExporter &= ExportUtils.exportImpl(exporter, includeCode, progress.newChild(1), outputFolder, spdRootPath, impl);
implWork -= (PRF_WORK + ((includeCode) ? IMPL_WORK : 0)); // SUPPRESS CHECKSTYLE INLINE
progress.setWorkRemaining(implWork);
}
}
if (useExporter) {
exporter.mkdir(outputFolder, progress.newChild(MKDIR_WORK));
exporter.write(spdResource, spdOutputPath, progress.newChild(SPD_WORK));
if (prfResource != null) {
exporter.write(prfResource, prfOutputPath, progress.newChild(PRF_WORK));
}
if (scdResourcePath != null) {
exporter.write(scdResourcePath, scdOutputPath, progress.newChild(SCD_WORK));
}
}
}
}
private static boolean exportImpl(final IScaExporter exporter, final boolean includeCode, final SubMonitor progress, IPath outputFolder,
final IPath spdRootPath, final Implementation impl) throws CoreException, IOException {
progress.beginTask("Exporting Implementation " + impl.getId(), 1);
ImplementationSettings implSettings = CodegenUtil.getImplementationSettings(impl);
String outputDir = implSettings.getOutputDir();
IResource outputDirResource = ExportUtils.getWorkspaceResource(spdRootPath.append(outputDir));
if (useInstallImplScript(outputDirResource)) {
installImpl(progress, impl.getId(), (IContainer) outputDirResource);
return false;
}
final String localFileName = impl.getCode().getLocalFile().getName();
final IPath codeLocalFile;
if (localFileName != null) {
codeLocalFile = new Path(localFileName);
} else {
codeLocalFile = null;
}
if (codeLocalFile != null && codeLocalFile.isAbsolute()) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Cannot export absolute 'localfile' paths"));
}
final IResource srcPath = ExportUtils.getWorkspaceResource(spdRootPath.append(codeLocalFile));
IPath outputPath;
if (includeCode) {
// Check if the path exists, there may be multiple implementations in this, only one needs to be built
if ((srcPath != null) && srcPath.exists()) {
outputPath = outputFolder.append(codeLocalFile);
exporter.write(srcPath, outputPath, progress.newChild(1));
}
}
if (impl.getPropertyFile() != null) {
final IPath prfPath = new Path(impl.getPropertyFile().getLocalFile().getName());
if (prfPath.isAbsolute()) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Cannot export absolute path property paths"));
}
final IResource srcPrfPath = ExportUtils.getWorkspaceResource(spdRootPath.append(prfPath));
if (srcPrfPath == null) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Expected file " + prfPath + " does not exist"));
}
outputPath = outputFolder.append(prfPath);
exporter.write(srcPrfPath, outputPath, progress.newChild(1));
}
return true;
}
private static void installImpl(IProgressMonitor monitor, String name, IContainer implSourceContainer) throws CoreException, IOException {
String configTypeId = IExternalToolConstants.ID_PROGRAM_LAUNCH_CONFIGURATION_TYPE;
final ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
final String launchConfigName = launchManager.generateLaunchConfigurationName("Build install implementation " + name);
final ILaunchConfigurationType configType = launchManager.getLaunchConfigurationType(configTypeId);
final ILaunchConfigurationWorkingCopy retVal = configType.newInstance(null, launchConfigName);
retVal.setAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true);
retVal.setAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, ExportUtils.getEnv());
retVal.setAttribute(IExternalToolConstants.ATTR_BUILDER_ENABLED, false);
retVal.setAttribute(IExternalToolConstants.ATTR_BUILD_SCOPE, "${none}");
retVal.setAttribute(IExternalToolConstants.ATTR_BUILDER_SCOPE, "${none}");
retVal.setAttribute(IExternalToolConstants.ATTR_SHOW_CONSOLE, true);
URL fileUrl = FileLocator.toFileURL(FileLocator.find(SdrUiPlugin.getDefault().getBundle(), new Path("resources/installImpl.sh"), null));
try {
File file = new File(fileUrl.toURI());
if (!file.canExecute()) {
file.setExecutable(true);
}
retVal.setAttribute(IExternalToolConstants.ATTR_LOCATION, file.getAbsolutePath());
} catch (URISyntaxException e1) {
throw new CoreException(new Status(IStatus.ERROR, SdrUiPlugin.PLUGIN_ID, "Failed to find install script.", e1));
}
retVal.setAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY, implSourceContainer.getLocation().toOSString());
ILaunch launch = retVal.launch("run", monitor, false);
while (!launch.isTerminated()) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// PASS
}
if (monitor.isCanceled()) {
launch.terminate();
break;
}
}
if (launch.getProcesses()[0].getExitValue() != 0) {
throw new CoreException(new Status(IStatus.ERROR, SdrUiPlugin.PLUGIN_ID,
"Install script returned with error code " + launch.getProcesses()[0].getExitValue() + "\n\nSee console output for details.", null));
}
}
private static boolean useInstallImplScript(IResource outputDir) {
if (outputDir instanceof IContainer) {
IContainer container = (IContainer) outputDir;
return container.getFile(new Path("reconf")).exists() || container.getFile(new Path("configure")).exists()
|| container.getFile(new Path("Makefile")).exists();
}
return false;
}
private static boolean useBuildSH(IProject project) {
if (project.getFile(new Path("build.sh")).exists()) {
IScopeContext projectScope = new ProjectScope(project);
IEclipsePreferences node = projectScope.getNode(SdrUiPlugin.PLUGIN_ID);
return node.getBoolean("useBuild.sh", false);
}
return false;
}
/**
* Sets a preference on the project to enable the use of build.sh for installing to the SDRROOT.
* @since 4.0
*/
public static void setUseBuildSH(@NonNull IProject project) {
IScopeContext projectScope = new ProjectScope(project);
IEclipsePreferences node = projectScope.getNode(SdrUiPlugin.PLUGIN_ID);
node.putBoolean("useBuild.sh", true);
try {
node.flush();
} catch (BackingStoreException e) {
SdrUiPlugin.getDefault().logError("Unable to enable useBuild.sh project preference for " + project, e);
}
}
/**
* Invokes "build.sh install" for a project.
* @param progress
* @param project
* @throws CoreException
* @throws IOException
* @throws DebugException
*/
private static void buildSH(final IProgressMonitor progress, IProject project) throws CoreException, IOException, DebugException {
String configTypeId = IExternalToolConstants.ID_PROGRAM_LAUNCH_CONFIGURATION_TYPE;
final ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
final String launchConfigName = launchManager.generateLaunchConfigurationName("Build Install " + project.getName());
final ILaunchConfigurationType configType = launchManager.getLaunchConfigurationType(configTypeId);
final ILaunchConfigurationWorkingCopy retVal = configType.newInstance(null, launchConfigName);
retVal.setAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true);
retVal.setAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, ExportUtils.getEnv());
retVal.setAttribute(IExternalToolConstants.ATTR_BUILDER_ENABLED, false);
retVal.setAttribute(IExternalToolConstants.ATTR_BUILD_SCOPE, "${none}");
retVal.setAttribute(IExternalToolConstants.ATTR_BUILDER_SCOPE, "${none}");
retVal.setAttribute(IExternalToolConstants.ATTR_SHOW_CONSOLE, true);
URL fileUrl = FileLocator.toFileURL(FileLocator.find(SdrUiPlugin.getDefault().getBundle(), new Path("resources/install.sh"), null));
try {
File file = new File(fileUrl.toURI());
if (!file.canExecute()) {
file.setExecutable(true);
}
retVal.setAttribute(IExternalToolConstants.ATTR_LOCATION, file.getAbsolutePath());
} catch (URISyntaxException e1) {
throw new CoreException(new Status(IStatus.ERROR, SdrUiPlugin.PLUGIN_ID, "Failed to find install script.", e1));
}
retVal.setAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY, project.getLocation().toOSString());
ILaunch launch = retVal.launch("run", progress, false);
while (!launch.isTerminated()) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// PASS
}
if (progress.isCanceled()) {
launch.terminate();
break;
}
}
if (launch.getProcesses()[0].getExitValue() != 0) {
throw new CoreException(new Status(IStatus.ERROR, SdrUiPlugin.PLUGIN_ID,
"Install script returned with error code " + launch.getProcesses()[0].getExitValue() + "\n\nSee console output for details.", null));
}
}
/**
* Checks the implementations within the soft pkg provided to see if any implementations have not been generated.
* If an implementation has not been generated, or no implementations exist at all, the user is asked whether or not
* to continue. True is returned if the user wishes to continue or all implementations were found, false is returned
* if the user has chosen to cancel the export.
*
* @param softPkg The Soft Pkg for this project
* @param spdRootPath The full path to the SPD resource. May be found by:
* spdResource.getFullPath().removeLastSegments(1)
* @return False if the user has chosen to stop the export, True otherwise.
* @throws CoreException
*/
private static boolean checkProjectImplsForExport(SoftPkg softPkg, IPath spdRootPath) throws CoreException {
final String projectName = ModelUtil.getProject(softPkg).getProject().getName();
if (softPkg.getImplementation() != null && softPkg.getImplementation().size() != 0) {
for (final Implementation impl : softPkg.getImplementation()) {
final String localFileName = impl.getCode().getLocalFile().getName();
final IPath codeLocalFile;
if (localFileName != null) {
codeLocalFile = new Path(localFileName);
} else {
codeLocalFile = null;
}
if (codeLocalFile != null && codeLocalFile.isAbsolute()) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Cannot export absolute path localfile paths"));
}
final IResource srcPath = ExportUtils.getWorkspaceResource(spdRootPath.append(codeLocalFile));
// Check if the path exists, there may be multiple implementations in this, only one needs to be built
if ((srcPath == null) || !srcPath.exists()) {
final String inProjStr = "in project '" + projectName + "' ";
final boolean[] shouldExport = { false };
Display.getDefault().syncExec(new Runnable() {
@Override
public void run() {
shouldExport[0] = MessageDialog.openQuestion(null, "File does not exist",
"The file '" + localFileName + "' " + inProjStr + "does not exist, export implementation anyway?");
}
});
if (!shouldExport[0]) {
SdrUiPlugin.getDefault().logError(
"Expected file '" + codeLocalFile + "' " + inProjStr + "does not exist, not exporting implementation");
return false;
}
}
}
} else {
final boolean[] shouldExport = { false };
Display.getDefault().syncExec(new Runnable() {
@Override
public void run() {
shouldExport[0] = MessageDialog.openQuestion(null, "No Implementations Found",
"No Implementations were found in " + projectName + ", export anyway?");
}
});
if (!shouldExport[0]) {
SdrUiPlugin.getDefault().logError("No implementations found in " + projectName + ", not exporting project");
return false;
}
}
return true;
}
private static IResource getWorkspaceResource(final IPath path) {
return ResourcesPlugin.getWorkspace().getRoot().findMember(path);
}
/**
* This checks a project for errors and prompts the user to continue if any are found.
*
* @param proj the project to check
* @return true if there are no errors or the user still wants to export
* @throws CoreException
*/
private static boolean checkProject(final IProject proj) throws CoreException {
final int maxSeverity = proj.findMaxProblemSeverity(IMarker.PROBLEM, true, 2);
boolean retVal = true;
if (maxSeverity == IMarker.SEVERITY_ERROR) {
final boolean[] continueExport = { true };
Display.getDefault().syncExec(new Runnable() {
@Override
public void run() {
continueExport[0] = MessageDialog.openQuestion(null, "Project has errors", "Project '" + proj.getName() + "' has errors. Export anyway?");
}
});
if (!continueExport[0]) {
retVal = false;
}
}
return retVal;
}
}