/******************************************************************************* * 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.util; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.resources.IResource; 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.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.emf.common.util.URI; import org.osgi.framework.Bundle; import gov.redhawk.ide.sdr.IdeSdrActivator; import mil.jpeojtrs.sca.spd.Dependency; import mil.jpeojtrs.sca.spd.Implementation; import mil.jpeojtrs.sca.spd.SoftPkg; import mil.jpeojtrs.sca.spd.SoftPkgRef; import mil.jpeojtrs.sca.spd.SpdPackage; import mil.jpeojtrs.sca.util.ScaEcoreUtils; /** * @since 8.2 */ public abstract class AbstractEnvMap implements IEnvMap { /** * @since 10.0 */ protected void addToPath(Set<String> path, Implementation impl) throws CoreException { String relativeCodePath = ScaEcoreUtils.getFeature(impl, SpdPackage.Literals.IMPLEMENTATION__CODE, SpdPackage.Literals.CODE__LOCAL_FILE, SpdPackage.Literals.LOCAL_FILE__NAME); if (impl.eResource() != null) { String newPath = createPath(relativeCodePath, impl.eResource().getURI()); if (newPath != null) { path.add(newPath); } } } /** * Create and return an appropriate absolute file path using the relative path and the SPD's URI * @param relativeCodePath The location relative to the SPD's base location * @param spdUri The SPD's URI * @return The appropriate path, or null if none * @throws CoreException * @since 10.0 */ protected abstract String createPath(String relativeCodePath, URI spdUri) throws CoreException; protected String getAbsolutePath(URI pathUri) throws CoreException { if (pathUri.isPlatformPlugin()) { String bundleId = pathUri.segment(1); Bundle bundle = Platform.getBundle(bundleId); IPath path = new Path(pathUri.toPlatformString(true)); path = path.removeFirstSegments(1); URL url = FileLocator.find(bundle, path, null); if (url != null) { try { url = FileLocator.toFileURL(url); return new File(url.toURI()).getAbsolutePath(); } catch (IOException e) { throw new CoreException(new Status(Status.ERROR, IdeSdrActivator.PLUGIN_ID, "Failed to find bundle file: " + pathUri, e)); } catch (URISyntaxException e) { throw new CoreException(new Status(Status.ERROR, IdeSdrActivator.PLUGIN_ID, "Failed to find bundle file: " + pathUri, e)); } } else { throw new CoreException(new Status(Status.ERROR, IdeSdrActivator.PLUGIN_ID, "Failed to find bundle file: " + pathUri, null)); } } else if (pathUri.isPlatformResource()) { IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(pathUri.toPlatformString(true))); if (resource != null) { return "${workspace_loc:" + resource.getFullPath() + "}"; } } else { IFileStore store = EFS.getStore(java.net.URI.create(pathUri.toString())); if (store.fetchInfo().exists()) { File localStore = store.toLocalFile(0, null); return localStore.getAbsolutePath(); } } return null; } /** * Gets the list of shared library implementations which are dependencies of this implementation. The list does * not contain duplicates, and the ordering is intended to match the core framework's traversal. * <p/> * A dependency tree is traversed in pre-order, depth-first. The list of dependencies within an implementation is * processed in reverse order. * <p/> * The first implementation of a given dependency is always selected as the one to be used (we don't evaluate * whether one implementation is more suitable than another). * @param impl * @return * @throws CoreException A referenced dependency cannot be found/loaded * @since 10.1 */ public static List<Implementation> getDependencyImplementations(final Implementation impl) throws CoreException { if (impl == null) { return Collections.emptyList(); } // Get the SPDs which are dependencies of our starting implementation LinkedList<SoftPkg> depQueue = new LinkedList<SoftPkg>(); for (Dependency dep : impl.getDependency()) { if (dep.getSoftPkgRef() != null) { SoftPkgRef spdRef = dep.getSoftPkgRef(); SoftPkg spd = spdRef.getSoftPkg(); if (spd == null) { String errorMsg = String.format("Unable to find / load softpkg dependency '%s' (dependency of softpkg '%s', implementation '%s')", spdRef.getLocalFile().getName(), impl.getSoftPkg().getName(), impl.getId()); throw new CoreException(new Status(IStatus.ERROR, IdeSdrActivator.PLUGIN_ID, errorMsg)); } // Prevent circular self-reference if (spd.equals(impl.getSoftPkg())) { continue; } depQueue.push(spd); } } // Work off dependencies in pre-order, depth-first Set<SoftPkg> visitedSpds = new HashSet<SoftPkg>(); List<Implementation> depImpls = new ArrayList<Implementation>(); while (depQueue.size() > 0) { SoftPkg currentSpd = depQueue.pop(); // Prevent circular recursion if (visitedSpds.contains(currentSpd)) { continue; } visitedSpds.add(currentSpd); // We choose the first implementation, and add to the result list (pre-order) Implementation currentImpl = currentSpd.getImplementation().get(0); if (!currentImpl.isSharedLibrary()) { continue; } depImpls.add(currentImpl); // Push the selected implementation's SPD dependencies on the stack (depth-first) for (Dependency currentImplDep : currentImpl.getDependency()) { if (currentImplDep.getSoftPkgRef() != null) { SoftPkgRef spdRef = currentImplDep.getSoftPkgRef(); SoftPkg depSpd = spdRef.getSoftPkg(); if (depSpd == null) { String errorMsg = String.format("Unable to find / load softpkg dependency '%s' (dependency of softpkg '%s', implementation '%s')", spdRef.getLocalFile().getName(), currentImpl.getSoftPkg().getName(), currentImpl.getId()); throw new CoreException(new Status(IStatus.ERROR, IdeSdrActivator.PLUGIN_ID, errorMsg)); } depQueue.push(depSpd); } } } return depImpls; } }