/******************************************************************************* * 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.materializer; import java.util.Map; import org.eclipse.buckminster.core.Messages; import org.eclipse.buckminster.core.RMContext; import org.eclipse.buckminster.core.common.model.ExpandingProperties; import org.eclipse.buckminster.core.cspec.IComponentIdentifier; import org.eclipse.buckminster.core.cspec.IComponentName; import org.eclipse.buckminster.core.cspec.IComponentRequest; import org.eclipse.buckminster.core.cspec.model.ComponentIdentifier; import org.eclipse.buckminster.core.cspec.model.ComponentName; import org.eclipse.buckminster.core.cspec.model.ComponentRequest; import org.eclipse.buckminster.core.ctype.IComponentType; import org.eclipse.buckminster.core.helpers.UnmodifiableMapUnion; import org.eclipse.buckminster.core.metadata.model.BOMNode; import org.eclipse.buckminster.core.metadata.model.BillOfMaterials; import org.eclipse.buckminster.core.metadata.model.Resolution; import org.eclipse.buckminster.core.mspec.IMaterializationNode; import org.eclipse.buckminster.core.mspec.model.MaterializationSpec; import org.eclipse.buckminster.core.query.model.ComponentQuery; import org.eclipse.buckminster.core.reader.IReaderType; import org.eclipse.buckminster.runtime.BuckminsterException; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.equinox.p2.metadata.Version; import org.eclipse.osgi.util.NLS; /** * @author Thomas Hallgren */ public class MaterializationContext extends RMContext { private final BillOfMaterials bom; private final MaterializationSpec materializationSpec; private final MaterializationStatistics statistics = new MaterializationStatistics(); private boolean rebootNeeded = false; private boolean tagsInitialized = false; public MaterializationContext(BillOfMaterials bom, MaterializationSpec mspec) { super(mspec.getProperties()); this.bom = bom; this.materializationSpec = mspec; } public MaterializationContext(BillOfMaterials bom, MaterializationSpec mspec, RMContext context) { super(new UnmodifiableMapUnion<String, Object>(mspec.getProperties(), context), context); this.bom = bom; this.materializationSpec = mspec; } /** * Returns the designated full path to the installed artifact for the * resolution. This is a shortcut for * * <pre> * getInstallLocation(resolution).append(getLeafArtifact(resolution)) * </pre> * * @param resolution * The resolution for which we want the artifact location * @return An absolute path in the local file system. * @throws CoreException */ public IPath getArtifactLocation(Resolution resolution) throws CoreException { IPath installLocation = getInstallLocation(resolution); IPath leafArtifact = getLeafArtifact(resolution); if (leafArtifact == null) installLocation = installLocation.addTrailingSeparator(); else installLocation = installLocation.append(leafArtifact); return installLocation; } public BillOfMaterials getBillOfMaterials() { return bom; } @Override public ComponentQuery getComponentQuery() { return bom.getQuery(); } /** * Returns the install location for the resolution as specified in the * {@link MaterializationSpec} or the default location if it is not * specified. * * @param resolution * The resolution for which we want the install location * @return An absolute path in the local file system. * @throws CoreException */ public IPath getInstallLocation(Resolution resolution) throws CoreException { IReaderType rd = materializationSpec.getMaterializer(resolution).getMaterializationReaderType(resolution); IPath relativeLocation = rd.getInstallLocation(resolution, this); if (relativeLocation == null) { IComponentType cType = resolution.getComponentType(); if (cType != null) relativeLocation = cType.getRelativeLocation(); } if (relativeLocation != null) { IPath tmp = expand(relativeLocation); if (tmp.isAbsolute()) return tmp; } IMaterializationNode node = materializationSpec.getMatchingNode(resolution); IPath nodeLocation = null; boolean useRootDefault = true; if (node != null) { nodeLocation = node.getInstallLocation(); String materializerId = node.getMaterializerID(); useRootDefault = (materializerId == null || materializerId.equals(materializationSpec.getMaterializerID())); if (nodeLocation != null) { if (relativeLocation != null) relativeLocation = nodeLocation.append(relativeLocation); else relativeLocation = nodeLocation; IPath tmp = expand(relativeLocation); if (tmp.isAbsolute()) return tmp; } } IPath location = null; if (useRootDefault) location = materializationSpec.getInstallLocation(); if (location == null) location = materializationSpec.getMaterializer(resolution).getDefaultInstallRoot(this, resolution); if (relativeLocation != null) location = location.append(relativeLocation); return expand(location); } public IPath getLeafArtifact(Resolution resolution) throws CoreException { MaterializationSpec mspec = getMaterializationSpec(); IPath leaf = mspec.getLeafArtifact(resolution); boolean isExpand = mspec.isExpand(resolution); if (leaf != null) { // MSpec always take precedence // if (isExpand) leaf = leaf.addTrailingSeparator(); return leaf; } IReaderType rd = mspec.getMaterializer(resolution).getMaterializationReaderType(resolution); if (isExpand) // // We only name files, not expanded folders // return null; leaf = rd.getLeafArtifact(resolution, this); if (leaf == null) { // No filename is available, let's use a name built from // <componentname>_<version> // IComponentIdentifier ci = resolution.getComponentIdentifier(); StringBuilder nameBld = new StringBuilder(ci.getName()); Version version = ci.getVersion(); if (version != null) { nameBld.append('_'); nameBld.append(version); } nameBld.append(".dat"); //$NON-NLS-1$ leaf = Path.fromPortableString(nameBld.toString()); if (leaf.segmentCount() > 1) leaf = leaf.removeFirstSegments(leaf.segmentCount() - 1); } return leaf; } public MaterializationSpec getMaterializationSpec() { return materializationSpec; } public MaterializationStatistics getMaterializationStatistics() { return statistics; } public int getMaxParallelJobs() { int maxParallelJobs = materializationSpec.getMaxParallelJobs(); if (maxParallelJobs == -1) maxParallelJobs = MaterializationJob.getMaxParallelJobs(); return maxParallelJobs; } @Override public Map<String, ? extends Object> getProperties(ComponentName cName) { Map<String, ? extends Object> p = super.getProperties(cName); IMaterializationNode node = materializationSpec.getMatchingNode(cName); return node == null ? p : new UnmodifiableMapUnion<String, Object>(node.getProperties(), p); } public Map<String, ? extends Object> getProperties(Resolution resolution) { Map<String, ? extends Object> p = super.getProperties(resolution.getComponentIdentifier()); IMaterializationNode node = materializationSpec.getMatchingNode(resolution); return node == null ? p : new UnmodifiableMapUnion<String, Object>(node.getProperties(), p); } public String getSuffixedName(Resolution resolution, String remoteName) throws CoreException { MaterializationSpec mspec = getMaterializationSpec(); IComponentName cName = resolution.getComponentIdentifier(); if (!(resolution.isUnpack() || mspec.isUnpack(resolution))) return null; String name = mspec.getSuffix(resolution); if (name == null) name = remoteName; if (name == null) { IReaderType rd = resolution.getProvider().getReaderType(); IPath leaf = rd.getLeafArtifact(resolution, this); if (leaf == null || leaf.segmentCount() == 0) throw BuckminsterException.fromMessage(NLS.bind(Messages.Unable_to_determine_suffix_for_unpack_of_0, cName)); name = leaf.segment(0); } return name; } public IPath getWorkspaceLocation(Resolution resolution) throws CoreException { IPath nodeLocation = null; ComponentIdentifier ci = resolution.getComponentIdentifier(); IMaterializationNode node = materializationSpec.getMatchingNode(resolution); if (node != null) { nodeLocation = node.getWorkspaceLocation(); if (nodeLocation != null) { nodeLocation = Path.fromOSString(ExpandingProperties.expand(getProperties(resolution), nodeLocation.toOSString(), 0)); IPath tmp = expand(nodeLocation); if (tmp.isAbsolute()) return tmp; } } IPath rootLocation = materializationSpec.getWorkspaceLocation(); if (rootLocation == null) { if (nodeLocation != null) // // At this point the nodeLocation must be relative so this // is illegal. // throw BuckminsterException.fromMessage(NLS.bind(Messages.WorkspaceLocation_0_in_node_matching_1_cannot_be_relative_unless, nodeLocation, ci)); // Default to location of current workspace // return ResourcesPlugin.getWorkspace().getRoot().getLocation(); } return expand((nodeLocation == null) ? rootLocation : rootLocation.append(nodeLocation)); } /** * If the target platform materializer installs things into the current * runtime, this flag will be set to <code>true</code>. * * @return <code>true</code> if a materializer altered the current runtime * platform. */ public boolean isRebootNeeded() { return rebootNeeded; } /** * Set by the target platform materializer when it installs new features * into the default target platform (the one currently in use). * * @param flag */ public void setRebootNeeded(boolean flag) { rebootNeeded = flag; } @Override protected void initializeAllTagInfos() { if (!tagsInitialized) { addTagInfosFromBom(null); tagsInitialized = true; } } @Override protected void initializeTagInfo(IComponentRequest request) { addTagInfosFromBom(request); } private void addTagInfosFromBom(IComponentRequest request) { addTagInfosFromNode(bom.getQuery().getTagInfo(), bom, request); } private void addTagInfosFromNode(String tagInfo, BOMNode node, IComponentRequest request) { ComponentRequest nodeRequest = node.getRequest(); if (hasTagInfo(nodeRequest)) // Tag info already generated return; Resolution res = node.getResolution(); if (res == null || IReaderType.ECLIPSE_PLATFORM.equals(res.getProvider().getReaderTypeId())) return; addTagInfo(nodeRequest, tagInfo); if (node.getRequest().equals(request)) return; String childTagInfo = res.getCSpec().getTagInfo(tagInfo); for (BOMNode child : node.getChildren()) addTagInfosFromNode(childTagInfo, child, request); } private IPath expand(IPath path) { return Path.fromOSString(ExpandingProperties.expand(this, path.toOSString(), 0)); } }