/***************************************************************************** * 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.cspec.model; import java.util.Map; import java.util.Stack; import org.eclipse.buckminster.core.KeyConstants; import org.eclipse.buckminster.core.Messages; import org.eclipse.buckminster.core.common.model.ExpandingProperties; import org.eclipse.buckminster.core.cspec.IAttributeFilter; import org.eclipse.buckminster.core.cspec.PathGroup; import org.eclipse.buckminster.core.cspec.builder.AttributeBuilder; import org.eclipse.buckminster.core.cspec.builder.CSpecBuilder; import org.eclipse.buckminster.core.cspec.builder.TopLevelAttributeBuilder; import org.eclipse.buckminster.core.ctype.IComponentType; import org.eclipse.buckminster.core.metadata.model.IModelCache; import org.eclipse.buckminster.core.version.VersionHelper; import org.eclipse.buckminster.runtime.BuckminsterException; 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; /** * The super class for actions, artifacts, and groups * * @author Thomas Hallgren */ public abstract class TopLevelAttribute extends Attribute implements Cloneable { public final static String PROPERTY_PREFIX = "buckminster."; //$NON-NLS-1$ public final static String INSTALLER_HINT_PREFIX = PROPERTY_PREFIX + "install."; //$NON-NLS-1$ public static final String PUBLIC_TAG = "public"; //$NON-NLS-1$ public static final String PRIVATE_TAG = "private"; //$NON-NLS-1$ public static final String DEFINITION_TAG = "definitions"; //$NON-NLS-1$ public static final String DEFINE_TAG = "define"; //$NON-NLS-1$ private final boolean publ; TopLevelAttribute(String name) { super(name); publ = true; } TopLevelAttribute(TopLevelAttributeBuilder builder) { super(builder); publ = builder.isPublic(); } @Override public void addDynamicProperties(Map<String, Object> properties) throws CoreException { String actionOutput; CSpec cspec = getCSpec(); // Create a unique folder name to use as sub-folder in the temporary // area // and under the output root // StringBuilder bld = new StringBuilder(); bld.append(cspec.getName()); Version version = cspec.getVersion(); if (version != null) { bld.append('_'); bld.append(VersionHelper.replaceQualifier(version, null)); } String ctype = cspec.getComponentTypeID(); if (!IComponentType.UNKNOWN.equals(ctype)) { bld.append('-'); bld.append(cspec.getComponentTypeID()); } String uniqueFolder = bld.toString(); String tempRootStr = (String) properties.get(KeyConstants.ACTION_TEMP_ROOT); IPath tempRoot; if (tempRootStr == null) { tempRoot = Path.fromOSString(System.getProperty("java.io.tmpdir")).append("buckminster"); //$NON-NLS-1$ //$NON-NLS-2$ properties.put(KeyConstants.ACTION_TEMP_ROOT, tempRoot.toOSString()); } else tempRoot = Path.fromOSString(tempRootStr); String actionTemp = tempRoot.append(uniqueFolder).append("temp").toPortableString(); //$NON-NLS-1$ String outputRoot = (String) properties.get(KeyConstants.ACTION_OUTPUT_ROOT); if (outputRoot == null) outputRoot = tempRoot.append("build").toOSString(); //$NON-NLS-1$ // Output root must be qualified with component name to avoid // conflicts // actionOutput = Path.fromOSString(outputRoot).append(uniqueFolder).toPortableString(); properties.put(KeyConstants.ACTION_OUTPUT, actionOutput); properties.put(KeyConstants.ACTION_TEMP, actionTemp); properties.put(KeyConstants.ACTION_HOME, cspec.getComponentLocation().toOSString()); properties.putAll(cspec.getComponentIdentifier().getProperties()); } public void appendRelativeFiles(IModelCache ctx, Map<String, Long> fileNames) throws CoreException { PathGroup[] pqs = getPathGroups(ctx, null); int idx = pqs.length; while (--idx >= 0) pqs[idx].appendRelativeFiles(fileNames); } @Override public String getDefaultTag() { return isPublic() ? PUBLIC_TAG : PRIVATE_TAG; } public long getFirstModified(IModelCache ctx, int expectedFileCount, int[] fileCount) throws CoreException { PathGroup[] pqs = getPathGroups(ctx, null); int idx = pqs.length; if (idx == 0) return 0L; if (idx > 1 && expectedFileCount > 0) // // We don't know how to distribute the count // expectedFileCount = -1; long oldest = Long.MAX_VALUE; while (--idx >= 0) { long pgModTime = pqs[idx].getFirstModified(expectedFileCount, fileCount); if (pgModTime < oldest) { oldest = pgModTime; if (oldest == 0) break; } } return oldest; } public long getLastModified(IModelCache ctx, long threshold, int[] fileCount) throws CoreException { PathGroup[] pqs = getPathGroups(ctx, null); int count = 0; int idx = pqs.length; int[] countBin = new int[1]; long newest = 0L; while (--idx >= 0) { countBin[0] = 0; long pgModTime = pqs[idx].getLastModified(threshold, countBin); count += countBin[0]; if (pgModTime > newest) { newest = pgModTime; if (newest > threshold) break; } } fileCount[0] = count; return newest; } @Override public final PathGroup[] getPathGroups(IModelCache ctx, Stack<IAttributeFilter> filters) throws CoreException { PathGroup[] pga; if (filters == null || filters.isEmpty()) { Map<String, PathGroup[]> cache = ctx.getPathGroupsCache(); String qName = getQualifiedName(); pga = cache.get(qName); if (pga == null) { ExpandingProperties<Object> local = new ExpandingProperties<Object>(ctx.getProperties()); addDynamicProperties(local); pga = internalGetPathGroups(ctx, local, filters); cache.put(qName, pga); } } else { // Can't use the cache // ExpandingProperties<Object> local = new ExpandingProperties<Object>(ctx.getProperties()); addDynamicProperties(local); pga = internalGetPathGroups(ctx, local, filters); } return pga; } public IPath getUniquePath(IPath root, IModelCache modelCtx) throws CoreException { IPath uniquePath = null; PathGroup[] groups = getPathGroups(modelCtx, null); if (groups.length == 1) { PathGroup group = groups[0]; IPath[] paths = group.getPaths(); if (paths.length == 1) { IPath base = group.getBase(); if (base == null || !base.isAbsolute()) { if (root == null) root = getCSpec().getComponentLocation(); if (base == null) base = root; else if (!base.isAbsolute()) base = root.append(base); } uniquePath = base.append(paths[0]); } } if (uniquePath == null) throw BuckminsterException.fromMessage(NLS.bind(Messages.Unable_to_determine_a_unique_product_path_for_0, this)); return uniquePath; } @Override public boolean isPublic() { return publ; } @Override protected abstract AttributeBuilder createAttributeBuilder(CSpecBuilder cspecBuilder); protected abstract PathGroup[] internalGetPathGroups(IModelCache ctx, Map<String, ? extends Object> local, Stack<IAttributeFilter> filters) throws CoreException; }