/******************************************************************************* * 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.debug.internal; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.model.ILaunchConfigurationDelegate2; import org.eclipse.debug.core.model.LaunchConfigurationDelegate; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.FeatureMap.Entry; import CF.DataType; import gov.redhawk.ide.debug.LocalSca; import gov.redhawk.ide.debug.LocalScaWaveform; import gov.redhawk.ide.debug.SadLauncherUtil; import gov.redhawk.ide.debug.ScaDebugPlugin; import gov.redhawk.model.sca.ScaAbstractProperty; import gov.redhawk.model.sca.ScaComponent; import gov.redhawk.model.sca.ScaFactory; import gov.redhawk.model.sca.ScaWaveform; import gov.redhawk.model.sca.util.StartJob; import gov.redhawk.sca.launch.ScaLaunchConfigurationConstants; import gov.redhawk.sca.launch.ScaLaunchConfigurationUtil; import gov.redhawk.sca.util.SubMonitor; import mil.jpeojtrs.sca.partitioning.ComponentProperties; import mil.jpeojtrs.sca.partitioning.PartitioningPackage; import mil.jpeojtrs.sca.prf.AbstractPropertyRef; import mil.jpeojtrs.sca.sad.ExternalProperty; import mil.jpeojtrs.sca.sad.SadComponentInstantiation; import mil.jpeojtrs.sca.sad.SadPackage; import mil.jpeojtrs.sca.sad.SoftwareAssembly; import mil.jpeojtrs.sca.spd.SoftPkg; import mil.jpeojtrs.sca.util.ScaEcoreUtils; import mil.jpeojtrs.sca.util.ScaResourceFactoryUtil; /** * An Eclipse launch delegate which handles launching a SoftwareAssembly locally in the Sandbox. */ public class LocalWaveformLaunchDelegate extends LaunchConfigurationDelegate implements ILaunchConfigurationDelegate2 { /** * Map of component's properties<br/> * Key --> component instantiation ID<br /> * Value --> DataType property</br> */ private final Map<String, List<DataType>> componentPropertyMap = new HashMap<String, List<DataType>>(); private static final int WORK_GET_LOCAL_SCA = 1, WORK_FETCH_PROPS = 1, WORK_CREATE_WAVEFORM = 10, WORK_UPDATE_AC = 1; private static final EStructuralFeature[] SAD_TO_ASSEMBLY_CONTROLLER_SPD = new EStructuralFeature[] { SadPackage.Literals.SOFTWARE_ASSEMBLY__ASSEMBLY_CONTROLLER, SadPackage.Literals.ASSEMBLY_CONTROLLER__COMPONENT_INSTANTIATION_REF, PartitioningPackage.Literals.COMPONENT_INSTANTIATION_REF__INSTANTIATION, PartitioningPackage.Literals.COMPONENT_INSTANTIATION__PLACEMENT, PartitioningPackage.Literals.COMPONENT_PLACEMENT__COMPONENT_FILE_REF, PartitioningPackage.Literals.COMPONENT_FILE_REF__FILE, PartitioningPackage.Literals.COMPONENT_FILE__SOFT_PKG }; @Override public void launch(final ILaunchConfiguration configuration, final String mode, final ILaunch launch, final IProgressMonitor monitor) throws CoreException { SubMonitor progress = SubMonitor.convert(monitor, WORK_GET_LOCAL_SCA + WORK_FETCH_PROPS + WORK_CREATE_WAVEFORM + WORK_UPDATE_AC); final Map<String, String> implMap = SadLauncherUtil.getImplementationMap(configuration); final Resource sadResource = ScaResourceFactoryUtil.createResourceSet().getResource(ScaLaunchConfigurationUtil.getProfileURI(configuration), true); final SoftwareAssembly sad = SoftwareAssembly.Util.getSoftwareAssembly(sadResource); // Validate all XML before doing anything else IStatus status = SadLauncherUtil.validateAllXML(sad); if (!status.isOK()) { throw new CoreException(status); } // Clear property map componentPropertyMap.clear(); // Load waveform properties from the sad.xml final ScaWaveform scaWaveform = ScaFactory.eINSTANCE.createScaWaveform(); scaWaveform.setProfileObj(sad); scaWaveform.fetchProperties(progress.newChild(WORK_FETCH_PROPS)); // Load user override values for the waveform ScaLaunchConfigurationUtil.loadProperties(configuration, scaWaveform); updateAssemblyControllerProperties(sad, scaWaveform, progress.newChild(WORK_UPDATE_AC)); if (sad.getExternalProperties() != null) { updateExternalProperties(sad, scaWaveform); } updateNonExternalProperties(sad); final LocalSca localSca = ScaDebugPlugin.getInstance().getLocalSca(progress.newChild(WORK_GET_LOCAL_SCA)); final LocalApplicationFactory factory = new LocalApplicationFactory(implMap, localSca, mode, launch, componentPropertyMap); try { final SimpleDateFormat dateFormat = new SimpleDateFormat("DDD_HHmmssSSS"); final LocalScaWaveform app = factory.create(sad, sad.getName() + "_" + dateFormat.format(new Date()), progress.newChild(WORK_CREATE_WAVEFORM)); boolean start = configuration.getAttribute(ScaLaunchConfigurationConstants.ATT_START, ScaLaunchConfigurationConstants.DEFAULT_VALUE_ATT_START); if (start) { final StartJob job = new StartJob(app.getName(), app); job.schedule(); } } catch (CoreException e) { launch.terminate(); throw e; } } /** * Update assembly controller properties to reflect <i>"user > sad > prf"</i>, where user provided values take * precedence over sad.xml values, which take precedence over prf.xml values. * * @param sad * @param scaWaveform * @param progress */ private void updateAssemblyControllerProperties(SoftwareAssembly sad, ScaWaveform scaWaveform, SubMonitor progress) { // Find the assembly controller SPD SoftPkg assemblySoftPkg = ScaEcoreUtils.getFeature(sad, LocalWaveformLaunchDelegate.SAD_TO_ASSEMBLY_CONTROLLER_SPD); // Load assembly controllers properties from the prf.xml final ScaComponent assemblyController = ScaFactory.eINSTANCE.createScaComponent(); assemblyController.setProfileObj(assemblySoftPkg); assemblyController.fetchProperties(progress); // Update assembly controllers properties List<DataType> acProps = new ArrayList<DataType>(); for (ScaAbstractProperty< ? > prop : assemblyController.getProperties()) { DataType property = scaWaveform.getProperty(prop.getId()).getProperty(); acProps.add(property); } String controllerInstId = sad.getAssemblyController().getComponentInstantiationRef().getInstantiation().getId(); componentPropertyMap.put(controllerInstId, acProps); } /** * Update external properties to reflect <i>"user > sad > prf"</i>, where user provided values take * precedence over sad.xml values, which take precedence over prf.xml values. * * @param sad * @param scaWaveform */ private void updateExternalProperties(SoftwareAssembly sad, ScaWaveform scaWaveform) { for (ExternalProperty extProp : sad.getExternalProperties().getProperties()) { SadComponentInstantiation inst = sad.getComponentInstantiation(extProp.getCompRefID()); // We've already added all of the assembly controller's properties, so skip this if (SoftwareAssembly.Util.isAssemblyController(inst)) { continue; } // Check if we've previously recorded properties against this component List<DataType> externalProps; if (componentPropertyMap.get(inst.getId()) != null) { externalProps = componentPropertyMap.get(inst.getId()); } else { externalProps = new ArrayList<DataType>(); } // Get the updated component property DataType dt = scaWaveform.getProperty(extProp.getExternalPropID()).getProperty(); // We need the DataType ID to be the PRF_ID, not the ExternalPropID. // This matters when the ApplicationFactory is creating the launch configuration. dt.id = extProp.getPropID(); externalProps.add(dt); componentPropertyMap.put(inst.getId(), externalProps); } } /** * At this point, we have only updated values for properties that belong to the assembly controller, or that are * marked explicitly as external. We need to check for property value overrides in the sad.xml for non-external * properties. * @param comp */ private void updateNonExternalProperties(final SoftwareAssembly sad) { List<SadComponentInstantiation> instantiations = sad.getAllComponentInstantiations(); for (SadComponentInstantiation comp : instantiations) { // Check what properties we've previously recorded against this component List<DataType> props = this.componentPropertyMap.get(comp.getId()); if (props == null) { props = new ArrayList<DataType>(); } // Pulling out all the properties ID's from the previous list for easy comparison below List<String> modifiedProps = new ArrayList<String>(); for (DataType prop : props) { modifiedProps.add(prop.id); } // If this is null, then that means there is no sad.xml override final ComponentProperties instProps = comp.getComponentProperties(); if (instProps == null) { continue; } // Look for non-external properties and make sure these get added to the componentPropertyMap for (final Entry entry : instProps.getProperties()) { if (!(entry.getValue() instanceof AbstractPropertyRef< ? >)) { continue; } AbstractPropertyRef< ? > ref = (AbstractPropertyRef< ? >) entry.getValue(); if (!modifiedProps.contains(ref.getRefID()) && ref.getProperty() != null) { props.add(new DataType(ref.getRefID(), ref.toAny())); } } this.componentPropertyMap.put(comp.getId(), props); } } }