/** * 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.model.sca.util; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.Job; import org.omg.CORBA.BAD_OPERATION; import org.omg.CORBA.SystemException; import CF.Application; import CF.DataType; import CF.DeviceAssignmentType; import CF.InvalidFileName; import CF.InvalidProfile; import CF.ApplicationFactoryPackage.CreateApplicationError; import CF.ApplicationFactoryPackage.CreateApplicationInsufficientCapacityError; import CF.ApplicationFactoryPackage.CreateApplicationRequestError; import CF.ApplicationFactoryPackage.InvalidInitConfiguration; import CF.DomainManagerPackage.ApplicationAlreadyInstalled; import CF.DomainManagerPackage.ApplicationInstallationError; import CF.DomainManagerPackage.ApplicationUninstallationError; import CF.DomainManagerPackage.InvalidIdentifier; import CF.LifeCyclePackage.ReleaseError; import CF.ResourcePackage.StartError; import gov.redhawk.model.sca.RefreshDepth; import gov.redhawk.model.sca.ScaDomainManager; import gov.redhawk.model.sca.ScaFactory; import gov.redhawk.model.sca.ScaModelPlugin; import gov.redhawk.model.sca.ScaWaveform; import gov.redhawk.model.sca.ScaWaveformFactory; import gov.redhawk.model.sca.commands.ScaModelCommandWithResult; import gov.redhawk.sca.util.Debug; import gov.redhawk.sca.util.SilentJob; import mil.jpeojtrs.sca.util.CFErrorFormatter; /** * @since 14.0 */ public class LaunchWaveformJob extends SilentJob { private static final Debug DEBUG = new Debug(ScaModelPlugin.ID, "launch/waveform"); private final ScaDomainManager domMgr; private final String waveformName; private final IPath waveformPath; private final DeviceAssignmentType[] deviceAssn; private final DataType[] configProps; private final boolean autoStart; private final boolean uninstallExistingApplicationFactory; private final Object waitLock; private ScaWaveform waveform = null; public LaunchWaveformJob(final ScaDomainManager domMgr, final String waveformName, final IPath waveformPath, final DeviceAssignmentType[] deviceAssn, final DataType[] configProps, final boolean autoStart, final Object waitLock) { this(domMgr, waveformName, waveformPath, deviceAssn, configProps, autoStart, waitLock, false); } /** * @since 20.0 */ public LaunchWaveformJob(final ScaDomainManager domMgr, final String waveformName, final IPath waveformPath, final DeviceAssignmentType[] deviceAssn, final DataType[] configProps, final boolean autoStart, final Object waitLock, final boolean uninstallExistingAppFactory) { super("Launching waveform " + waveformName); this.domMgr = domMgr; this.waveformName = waveformName; this.waveformPath = waveformPath; this.deviceAssn = deviceAssn; this.configProps = configProps; this.autoStart = autoStart; this.uninstallExistingApplicationFactory = uninstallExistingAppFactory; this.waitLock = waitLock; this.setSystem(true); this.setUser(false); this.setPriority(Job.LONG); } public ScaWaveform getWaveform() { return this.waveform; } @Override protected IStatus runSilent(final IProgressMonitor m) { // Track whether we installed the ApplicationFactory ourselves. final SubMonitor subMonitor = SubMonitor.convert(m, "Launching Application: " + this.waveformName, IProgressMonitor.UNKNOWN); ScaWaveformFactory factory = null; boolean installedAppFactory = false; try { final String profilePath = this.waveformPath.toPortableString(); try { // Create waveform using the new CF.DomainManager#createApplication() method final Application app = domMgr.createApplication(profilePath, this.waveformName, this.configProps, this.deviceAssn); final String ior = app.toString(); waveform = ScaModelCommandWithResult.execute(domMgr, new ScaModelCommandWithResult<ScaWaveform>() { @Override public void execute() { if (domMgr != null) { // Check to be sure someone else didn't already add the waveform for (ScaWaveform w : domMgr.getWaveforms()) { if (ior.equals(w.getIor())) { setResult(w); return; } } ScaWaveform newWaveform = ScaFactory.eINSTANCE.createScaWaveform(); newWaveform.setCorbaObj(app); domMgr.getWaveforms().add(newWaveform); setResult(newWaveform); } } }); subMonitor.worked(1); } catch (BAD_OPERATION exception) { // IDE-1109: It's possible to get here if domain is pre-2.0, fall back to old method for launching waveforms // use existing Application Factory if exists, since only ONE can exist per Waveform profilePath in Domain for (final ScaWaveformFactory temp : LaunchWaveformJob.this.domMgr.fetchWaveformFactories(null, RefreshDepth.SELF)) { // TODO: Better progress monitor if (temp.getProfile().equals(profilePath)) { factory = temp; } } // unless power user specified to uninstall existing Application Factory if (factory != null && uninstallExistingApplicationFactory) { try { this.domMgr.uninstallScaWaveformFactory(factory); factory = null; } catch (ApplicationUninstallationError | InvalidIdentifier | SystemException ex) { DEBUG.catching("Failed to uninstall existing Waveform factory before launching a waveform.", ex); return new Status(Status.ERROR, ScaModelPlugin.ID, "Failed to uninstall existing Waveform factory before launching a waveform: " + waveformName, ex); } } //////////////////// // INSTALL WAVEFORM (Application) Factory subMonitor.subTask("Installing REDHAWK Waveform Factory: " + profilePath); while (factory == null) { DEBUG.message("Installing REDHAWK Waveform Factory..."); if (subMonitor.isCanceled()) { throw new OperationCanceledException(); } try { factory = this.domMgr.installScaWaveformFactory(profilePath); installedAppFactory = true; } catch (final ApplicationAlreadyInstalled e) { String errorMsg = "The domain manager reports the application factory is already installed, but it was not found. " + "Another installed waveform may be using the same softwareassembly id in its XML file."; return new Status(Status.ERROR, ScaModelPlugin.ID, errorMsg, e); } } subMonitor.worked(1); if (subMonitor.isCanceled()) { throw new OperationCanceledException(); } Assert.isNotNull(factory, "Failed to get/install REDHAWK Waveform Factory"); //////////////////// // CREATE WAVEFORM final IProgressMonitor createMonitor = subMonitor.newChild(1); createMonitor.beginTask("Creating Waveform (application): " + this.waveformName, IProgressMonitor.UNKNOWN); this.waveform = factory.createWaveform(createMonitor, LaunchWaveformJob.this.waveformName, LaunchWaveformJob.this.configProps, LaunchWaveformJob.this.deviceAssn); if (subMonitor.isCanceled()) { throw new OperationCanceledException(); } } if (this.autoStart) { try { waveform.start(); } catch (StartError e) { return new Status(Status.ERROR, ScaModelPlugin.ID, CFErrorFormatter.format(e, "waveform " + waveformName), e); } } if (subMonitor.isCanceled()) { throw new OperationCanceledException(); } } catch (final InvalidProfile e) { return StatusFactory.createStatus(e, ScaModelPlugin.ID, this.waveformName); } catch (final InvalidFileName e) { return StatusFactory.createStatus(e, ScaModelPlugin.ID, this.waveformName); } catch (final ApplicationInstallationError e) { return StatusFactory.createStatus(e, ScaModelPlugin.ID, this.waveformName); } catch (final CreateApplicationError e) { return StatusFactory.createStatus(e, ScaModelPlugin.ID, this.waveformName); } catch (final CreateApplicationRequestError e) { return StatusFactory.createStatus(e, ScaModelPlugin.ID, this.waveformName); } catch (final InvalidInitConfiguration e) { return StatusFactory.createStatus(e, ScaModelPlugin.ID, this.waveformName); } catch (final SystemException e) { return StatusFactory.createStatus(e, ScaModelPlugin.ID, this.waveformName); } catch (CreateApplicationInsufficientCapacityError e) { return StatusFactory.createStatus(e, ScaModelPlugin.ID, this.waveformName); } finally { // If we installed the ApplicationFactory above, uninstall it to prevent // future conflicts if the user changes the SAD. try { if (subMonitor.isCanceled()) { // the user requested a cancel...so let's release the app if (this.waveform != null) { try { this.waveform.releaseObject(); } catch (final ReleaseError e) { // PASS } this.waveform = null; } } if (installedAppFactory && factory != null) { DEBUG.message("Uninstall waveform factory = {0}", factory); try { this.domMgr.uninstallScaWaveformFactory(factory); } catch (ApplicationUninstallationError | InvalidIdentifier | SystemException ex) { if (DEBUG.enabled) { DEBUG.catching("Failed to uninstall existing Waveform factory before launching a waveform.", ex); } } } } finally { synchronized (this.waitLock) { this.waitLock.notifyAll(); } subMonitor.done(); } } return Status.OK_STATUS; } }