/******************************************************************************* * 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.io.IOException; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.emf.common.notify.impl.AdapterImpl; import org.eclipse.emf.ecore.EObject; import org.omg.CORBA.ORB; import org.omg.PortableServer.POA; import org.omg.PortableServer.POAPackage.ServantNotActive; import org.omg.PortableServer.POAPackage.WrongPolicy; import CF.FileSystem; import CF.FileSystemHelper; import CF.FileSystemPOA; import CF.FileSystemPOATie; import CF.ResourceFactoryOperations; import gov.redhawk.core.filemanager.filesystem.JavaFileSystem; import gov.redhawk.core.resourcefactory.AbstractResourceFactoryProvider; import gov.redhawk.core.resourcefactory.ComponentDesc; import gov.redhawk.core.resourcefactory.ResourceDesc; import gov.redhawk.core.resourcefactory.ResourceFactoryPlugin; import gov.redhawk.ide.debug.SpdResourceFactory; import gov.redhawk.ide.debug.ui.ScaDebugUiPlugin; import gov.redhawk.ide.sdr.SdrPackage; import gov.redhawk.ide.sdr.SdrRoot; import gov.redhawk.ide.sdr.ui.SdrUiPlugin; import gov.redhawk.model.sca.commands.ScaModelCommand; import gov.redhawk.sca.util.MutexRule; import gov.redhawk.sca.util.OrbSession; import mil.jpeojtrs.sca.spd.SoftPkg; /** * Provides descriptions of resources in the SDRROOT which can be launched in the sandbox. */ public class SdrResourceFactoryProvider extends AbstractResourceFactoryProvider { private static final MutexRule RULE = new MutexRule(SdrResourceFactoryProvider.class); private static final String SDR_CATEGORY = "SDR"; private class SPDListener extends AdapterImpl { @Override public void notifyChanged(final org.eclipse.emf.common.notify.Notification msg) { if (disposed) { if (msg.getNotifier() instanceof Notifier) { ((Notifier) msg.getNotifier()).eAdapters().remove(this); } return; } if (msg.getFeature() == SdrPackage.Literals.SOFT_PKG_REGISTRY__COMPONENTS) { switch (msg.getEventType()) { case Notification.ADD: try { SoftPkg spd = (SoftPkg) msg.getNewValue(); SpdResourceFactory resFactory = SpdResourceFactory.createResourceFactory(spd); addResource(spd, resFactory); } catch (IllegalArgumentException e) { ScaDebugUiPlugin.log(new Status(IStatus.WARNING, ScaDebugUiPlugin.PLUGIN_ID, "Invalid SPD file was not added to the sandbox", e)); } break; case Notification.ADD_MANY: MultiStatus status = new MultiStatus(ScaDebugUiPlugin.PLUGIN_ID, 0, "Invalid SPD file(s) were not added to the sandbox", null); for (final Object obj : (Collection< ? >) msg.getNewValue()) { SoftPkg spd = (SoftPkg) obj; try { SpdResourceFactory resFactory = SpdResourceFactory.createResourceFactory(spd); addResource(spd, resFactory); } catch (IllegalArgumentException e) { status.add(new Status(IStatus.WARNING, ScaDebugUiPlugin.PLUGIN_ID, e.toString(), e)); } } if (!status.isOK()) { ScaDebugUiPlugin.log(status); } break; case Notification.REMOVE: removeResource((SoftPkg) msg.getOldValue()); break; case Notification.REMOVE_MANY: for (final Object obj : (Collection< ? >) msg.getOldValue()) { removeResource((SoftPkg) obj); } break; default: break; } } } }; private OrbSession session; private final Map<EObject, ResourceDesc> resourceMap = Collections.synchronizedMap(new HashMap<EObject, ResourceDesc>()); private SdrRoot root; private SPDListener componentsListener; private SPDListener devicesListener; private SPDListener serviceListener; private boolean disposed; public SdrResourceFactoryProvider() { SdrUiPlugin plugin = SdrUiPlugin.getDefault(); this.root = plugin.getTargetSdrRoot(); if (this.root == null) { return; } IPath domPath = plugin.getTargetSdrDomPath(); DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() { @Override public boolean accept(Path entry) { // Accept directories that don't start with a dot return Files.isDirectory(entry) && !entry.getFileName().toString().startsWith("."); } }; if (domPath != null && domPath.toFile().exists()) { try { for (Path path : Files.newDirectoryStream(domPath.toFile().toPath(), filter)) { addVirtualMount(path); } } catch (IOException e) { ScaDebugUiPlugin.log( new Status(IStatus.ERROR, ScaDebugUiPlugin.PLUGIN_ID, "Error while mounting SDRROOT/dom directories into sandbox file manager", e)); } } this.componentsListener = new SPDListener(); this.devicesListener = new SPDListener(); this.serviceListener = new SPDListener(); ScaModelCommand.execute(this.root, new ScaModelCommand() { @Override public void execute() { MultiStatus status = new MultiStatus(ScaDebugUiPlugin.PLUGIN_ID, 0, "Invalid SPD file(s) were not added to the sandbox", null); List<SoftPkg> spds = new ArrayList<>(SdrResourceFactoryProvider.this.root.getComponentsContainer().getComponents()); spds.addAll(SdrResourceFactoryProvider.this.root.getDevicesContainer().getComponents()); spds.addAll(SdrResourceFactoryProvider.this.root.getServicesContainer().getComponents()); for (final SoftPkg spd : spds) { try { SpdResourceFactory resFactory = SpdResourceFactory.createResourceFactory(spd); addResource(spd, resFactory); } catch (IllegalArgumentException e) { status.add(new Status(IStatus.WARNING, ScaDebugUiPlugin.PLUGIN_ID, e.toString(), e)); } } SdrResourceFactoryProvider.this.root.getComponentsContainer().eAdapters().add(SdrResourceFactoryProvider.this.componentsListener); SdrResourceFactoryProvider.this.root.getDevicesContainer().eAdapters().add(SdrResourceFactoryProvider.this.devicesListener); SdrResourceFactoryProvider.this.root.getServicesContainer().eAdapters().add(SdrResourceFactoryProvider.this.serviceListener); if (!status.isOK()) { ScaDebugUiPlugin.log(status); } } }); } /** * Adds a virtual mount for a location in the file system * @param dir * @throws CoreException */ private void addVirtualMount(Path dir) { String mountPoint = dir.getFileSystem().getSeparator() + dir.getFileName().toString(); if (session == null) { session = OrbSession.createSession(ResourceFactoryPlugin.ID); } ORB orb = session.getOrb(); POA poa; try { poa = session.getPOA(); } catch (CoreException e) { ScaDebugUiPlugin.log(e); return; } FileSystemPOA fsPoa = new FileSystemPOATie(new JavaFileSystem(orb, poa, dir.toFile())); try { FileSystem domDepsFs = FileSystemHelper.narrow(poa.servant_to_reference(fsPoa)); addFileSystemMount(domDepsFs, mountPoint); } catch (ServantNotActive | WrongPolicy e) { ScaDebugUiPlugin.log(new Status(IStatus.ERROR, ScaDebugUiPlugin.PLUGIN_ID, "Unable to create virtual mount " + mountPoint, e)); } } private void addResource(final SoftPkg spd, final ResourceFactoryOperations factory) { ComponentDesc desc = new ComponentDesc(spd, factory); desc.setCategory(SDR_CATEGORY); SdrResourceFactoryProvider.this.resourceMap.put(spd, desc); addResourceDesc(desc); } private void removeResource(final EObject resource) { final ResourceDesc desc = this.resourceMap.get(resource); if (desc != null) { removeResourceDesc(desc); } } @Override public void dispose() { Job.getJobManager().beginRule(RULE, null); try { if (disposed) { return; } disposed = true; } finally { Job.getJobManager().endRule(RULE); } // Stop listening for changes ScaModelCommand.execute(this.root, new ScaModelCommand() { @Override public void execute() { root.getComponentsContainer().eAdapters().remove(componentsListener); root.getDevicesContainer().eAdapters().remove(devicesListener); root.getServicesContainer().eAdapters().remove(serviceListener); } }); this.root = null; // Remove resource descriptions synchronized (this.resourceMap) { for (final ResourceDesc desc : this.resourceMap.values()) { removeResourceDesc(desc); } this.resourceMap.clear(); } // Remove file system mounts for (String mount : getFileSystemMounts().keySet()) { removeFileSystemMount(mount); } // Dispose session if (session != null) { session.dispose(); session = null; } } }