/***************************************************************************** * Copyright (c) 2006-2013, Cloudsmith Inc. * The code, documentation and other materials contained herein have been * licensed under the Eclipse Public License - v 1.0 by the copyright holder * listed above, as the Initial Contributor under such license. The text of * such license is available at www.eclipse.org. *****************************************************************************/ package org.eclipse.buckminster.core.internal.actor; import java.io.File; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Stack; import org.eclipse.buckminster.core.CorePlugin; import org.eclipse.buckminster.core.Messages; import org.eclipse.buckminster.core.actor.IActionContext; import org.eclipse.buckminster.core.cspec.IAttributeFilter; import org.eclipse.buckminster.core.cspec.ICSpecData; import org.eclipse.buckminster.core.cspec.PathGroup; import org.eclipse.buckminster.core.cspec.model.Action; import org.eclipse.buckminster.core.cspec.model.ActionArtifact; import org.eclipse.buckminster.core.cspec.model.Attribute; import org.eclipse.buckminster.core.cspec.model.CSpec; import org.eclipse.buckminster.core.cspec.model.ComponentRequest; import org.eclipse.buckminster.core.cspec.model.Group; import org.eclipse.buckminster.core.cspec.model.Prerequisite; import org.eclipse.buckminster.core.cspec.model.TopLevelAttribute; import org.eclipse.buckminster.runtime.BuckminsterException; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubProgressMonitor; /** * @author kolwing * */ public class PerformContext implements IActionContext { private static PathGroup[] normalizePathGroups(PathGroup[] pathGroups) throws CoreException { if (pathGroups.length == 0) return pathGroups; HashMap<IPath, ArrayList<IPath>> newPathGroups = new HashMap<IPath, ArrayList<IPath>>(); for (PathGroup pathGroup : pathGroups) { IPath base = pathGroup.getBase(); ArrayList<IPath> currentGroup = newPathGroups.get(base); if (currentGroup == null) { currentGroup = new ArrayList<IPath>(); newPathGroups.put(base, currentGroup); } for (IPath path : pathGroup.getPaths()) currentGroup.add(path); } ArrayList<PathGroup> normalized = new ArrayList<PathGroup>(); for (Map.Entry<IPath, ArrayList<IPath>> entry : newPathGroups.entrySet()) { ArrayList<IPath> paths = entry.getValue(); normalizePaths(paths); normalized.add(new PathGroup(entry.getKey(), paths.toArray(new IPath[paths.size()]))); } return normalized.toArray(new PathGroup[normalized.size()]); } private static void normalizePaths(ArrayList<IPath> paths) { // Remove all paths that has a parent path in the array // int topDown = paths.size(); while (--topDown >= 0) { IPath path = paths.get(topDown); if (path.segmentCount() == 1 && ".".equals(path.lastSegment())) //$NON-NLS-1$ { paths.clear(); return; } int top = paths.size(); for (int idx = 0; idx < top; ++idx) { if (idx != topDown && paths.get(idx).isPrefixOf(path)) { paths.remove(topDown); break; } } } } private static PathGroup[] trimNonExistentBases(PathGroup[] pathGroups) throws CoreException { if (pathGroups.length == 0) return pathGroups; ArrayList<PathGroup> existentBases = new ArrayList<PathGroup>(); for (PathGroup pathGroup : pathGroups) { File file = pathGroup.getBase().toFile().getAbsoluteFile(); if (file.exists()) existentBases.add(pathGroup); else CorePlugin.getLogger().debug("Base: %s: No such file or directory", file); //$NON-NLS-1$ } return existentBases.toArray(new PathGroup[existentBases.size()]); } final static String PRODUCT_PREFIX = TopLevelAttribute.PROPERTY_PREFIX + "product."; //$NON-NLS-1$ final static String REQUIREMENT_PREFIX = TopLevelAttribute.PROPERTY_PREFIX + "requirement."; //$NON-NLS-1$ private final IProgressMonitor cancellationMonitor; private final Action action; private final PrintStream errorStream; private final GlobalContext globalCtx; private final PrintStream outputStream; private final Map<String, ? extends Object> properties; public PerformContext(GlobalContext globalCtx, Action action, PrintStream out, PrintStream err, IProgressMonitor cancellationMonitor) throws CoreException { this.globalCtx = globalCtx; this.action = action; this.properties = globalCtx.getExecutionProperties(action); this.outputStream = out; this.errorStream = err; this.cancellationMonitor = cancellationMonitor; } @Override public void addPrerequisitePathGroups(Map<String, PathGroup[]> pgas) throws CoreException { Collection<Prerequisite> prereqs = action.getPrerequisites(); if (prereqs.size() == 0) return; CSpec cspec = action.getCSpec(); IPath prereqRebase = action.getPrerequisiteRebase(); if (prereqRebase != null) { prereqRebase = PerformManager.expandPath(properties, prereqRebase); if (prereqRebase.isAbsolute()) throw BuckminsterException.fromMessage(Messages.Action_prerequisite_base_can_not_be_absolute); prereqRebase = cspec.getComponentLocation().append(prereqRebase); } String mainRQ = REQUIREMENT_PREFIX + action.getName(); String prefix = mainRQ + '.'; ArrayList<PathGroup> allRequiredPaths = new ArrayList<PathGroup>(); Stack<IAttributeFilter> filters = null; for (Prerequisite prereq : prereqs) { Attribute ag = prereq.getReferencedAttribute(cspec, this); PathGroup[] paths; if (ag == null) paths = new PathGroup[0]; else { if (prereq.isPatternFilter()) { if (filters == null) filters = new Stack<IAttributeFilter>(); filters.push(prereq); paths = ag.getPathGroups(this, filters); filters.pop(); } else paths = ag.getPathGroups(this, filters); paths = normalizePathGroups(paths); paths = trimNonExistentBases(paths); if (!prereq.isExternal()) { if (prereqRebase != null) paths = Group.rebase(prereqRebase, paths); } } String alias = prereq.getAlias(); if (alias != null) pgas.put(alias, paths); else pgas.put(prefix + prereq, paths); for (PathGroup path : paths) allRequiredPaths.add(path); } if (allRequiredPaths.size() > 0) { PathGroup[] pathGroups = normalizePathGroups(allRequiredPaths.toArray(new PathGroup[allRequiredPaths.size()])); String alias = action.getPrerequisitesAlias(); if (alias != null) pgas.put(alias, pathGroups); else pgas.put(mainRQ, pathGroups); } } public void addProductPathGroup(Map<String, PathGroup[]> pgas) throws CoreException { List<ActionArtifact> productArtifacts = action.getProductArtifacts(); if (productArtifacts.size() == 0) { PathGroup[] product = action.getPathGroups(this, null); if (product.length > 0) { PathGroup[] pathGroups = normalizePathGroups(product); String alias = action.getProductAlias(); if (alias != null) pgas.put(alias, pathGroups); else pgas.put(PRODUCT_PREFIX + action.getName(), pathGroups); } } else { for (ActionArtifact productArtifact : productArtifacts) { PathGroup[] pathGroups = normalizePathGroups(productArtifact.getPathGroups(this, null)); String alias = productArtifact.getAlias(); if (alias != null) pgas.put(alias, pathGroups); else pgas.put(PRODUCT_PREFIX + productArtifact.getName(), pathGroups); } } } @Override public CSpec findCSpec(ICSpecData ownerCSpec, ComponentRequest request) throws CoreException { return globalCtx.findCSpec(ownerCSpec, request); } /* * (non-Javadoc) * * @see org.eclipse.buckminster.core.actor.IActionContext#getAction() */ @Override public final Action getAction() { return action; } @Override public Collection<CSpec> getAllFoundCSpecs() { return globalCtx.getAllFoundCSpecs(); } @Override public IProgressMonitor getCancellationMonitor() { return new SubProgressMonitor(cancellationMonitor, 1); } /* * (non-Javadoc) * * @see * org.eclipse.buckminster.core.actor.IActionContext#getComponentLocation() */ @Override public IPath getComponentLocation() throws CoreException { return getCSpec().getComponentLocation(); } /* * (non-Javadoc) * * @see org.eclipse.buckminster.core.actor.IActionContext#getCSpec() */ @Override public CSpec getCSpec() throws CoreException { return action.getCSpec(); } /* * (non-Javadoc) * * @see org.eclipse.buckminster.core.actor.IActionContext#getErrorStream() */ @Override public final PrintStream getErrorStream() { return errorStream; } @Override public final GlobalContext getGlobalContext() { return globalCtx; } @Override public Map<String, PathGroup[]> getNamedPathGroupArrays() throws CoreException { HashMap<String, PathGroup[]> pgas = new HashMap<String, PathGroup[]>(); addPrerequisitePathGroups(pgas); addProductPathGroup(pgas); return pgas; } @Override public final PrintStream getOutputStream() { return outputStream; } @Override public Map<String, PathGroup[]> getPathGroupsCache() { return globalCtx.getPathGroupsCache(); } @Override public IProject getProject() throws CoreException { IPath cloc = getComponentLocation(); for (IProject p : ResourcesPlugin.getWorkspace().getRoot().getProjects()) if (cloc.equals(p.getLocation())) return p; return null; } @Override public final Map<String, ? extends Object> getProperties() { return properties; } @Override public boolean isForced() { return globalCtx.isForcedExecution() || action.isAlways(); } @Override public boolean isQuiet() { return globalCtx.isQuietExecution(); } @Override public File makeAbsolute(File file) throws CoreException { if (!file.isAbsolute()) file = getComponentLocation().append(file.toString()).toFile(); return file; } @Override public IPath makeAbsolute(IPath path) throws CoreException { if (!path.isAbsolute()) path = getComponentLocation().append(path); return path; } }