/*******************************************************************************
* 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.pde.tasks;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.eclipse.buckminster.core.cspec.model.ComponentIdentifier;
import org.eclipse.buckminster.core.ctype.IComponentType;
import org.eclipse.buckminster.core.version.VersionHelper;
import org.eclipse.buckminster.pde.cspecgen.feature.CSpecFromFeature;
import org.eclipse.buckminster.pde.internal.FeatureModelReader;
import org.eclipse.buckminster.pde.internal.model.EditableFeatureModel;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.equinox.p2.metadata.IVersionedId;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.metadata.VersionedId;
import org.eclipse.pde.core.IModelChangedEvent;
import org.eclipse.pde.core.IModelChangedListener;
import org.eclipse.pde.internal.core.ifeature.IFeature;
import org.eclipse.pde.internal.core.ifeature.IFeatureChild;
import org.eclipse.pde.internal.core.ifeature.IFeatureImport;
import org.eclipse.pde.internal.core.ifeature.IFeaturePlugin;
@SuppressWarnings("restriction")
public class FeatureConsolidator extends GroupConsolidator implements IModelChangedListener {
private final EditableFeatureModel featureModel;
public FeatureConsolidator(File inputFile, File outputFile, File propertiesFile, List<File> featuresAndBundles, String qualifier,
boolean generateVersionSuffix, int maxVersionSuffixLength, int significantDigits) throws CoreException {
super(outputFile, propertiesFile, featuresAndBundles, qualifier, generateVersionSuffix, maxVersionSuffixLength, significantDigits);
featureModel = FeatureModelReader.readEditableFeatureModel(inputFile);
featureModel.addModelChangedListener(this);
}
@Override
public void modelChanged(IModelChangedEvent event) {
featureModel.setDirty(true);
}
public void run() throws CoreException, FileNotFoundException {
IFeature feature = featureModel.getFeature();
String id = feature.getId();
IFeatureChild sourceRef = null;
Map<String, Version[]> featureVers = getFeatureVersions();
ArrayList<ComponentIdentifier> deps = new ArrayList<ComponentIdentifier>();
for (IFeatureChild ref : feature.getIncludedFeatures()) {
String vstr = ref.getVersion();
String refId = ref.getId();
String refIdWOS = CSpecFromFeature.getIdWithoutSource(refId);
if (refIdWOS != null && refIdWOS.equals(id)) {
// This feature includes the source feature of itself
sourceRef = ref;
continue;
}
Version version = findBestVersion(featureVers, id, "feature", refId, vstr); //$NON-NLS-1$
if (version != null) {
ComponentIdentifier cid = new ComponentIdentifier(refId, IComponentType.ECLIPSE_FEATURE, version);
deps.add(cid);
String nvstr = cid.getVersion().toString();
if (!nvstr.equals(vstr))
ref.setVersion(nvstr);
}
}
Map<String, Version[]> pluginVers = getPluginVersions();
for (IFeaturePlugin ref : feature.getPlugins()) {
String vstr = ref.getVersion();
String refId = ref.getId();
Version version = findBestVersion(pluginVers, id, "plugin", refId, vstr); //$NON-NLS-1$
if (version != null) {
ComponentIdentifier cid = new ComponentIdentifier(refId, IComponentType.OSGI_BUNDLE, version);
deps.add(cid);
String nvstr = cid.getVersion().toString();
if (!nvstr.equals(vstr))
ref.setVersion(nvstr);
}
}
consolidateFeatureVersion(deps);
if (sourceRef != null)
sourceRef.setVersion(feature.getVersion());
featureModel.save(getOutputFile());
}
private void consolidateFeatureVersion(List<ComponentIdentifier> deps) throws CoreException {
IFeature feature = featureModel.getFeature();
String versionStr = feature.getVersion();
if (versionStr == null)
return;
Version version;
try {
version = Version.parseVersion(versionStr);
} catch (IllegalArgumentException e) {
return;
}
if (versionStr.endsWith(PROPERTY_QUALIFIER)) {
ComponentIdentifier ci = new ComponentIdentifier(feature.getId(), IComponentType.ECLIPSE_FEATURE, version);
Version newVersion = replaceQualifier(ci, deps);
if (newVersion != null && !version.equals(newVersion)) {
String newVersionStr = newVersion.toString();
feature.setVersion(newVersionStr);
if (isContextReplacement()) {
int lastDot = versionStr.lastIndexOf("."); //$NON-NLS-1$
featureModel.setContextQualifierLength(newVersionStr.length() - lastDot - 1);
}
version = newVersion;
}
if (isUsingGenerator(ci))
return;
}
if (featureModel.getContextQualifierLength() == -1)
return;
IFeatureChild[] features = feature.getIncludedFeatures();
List<IVersionedId> featureList;
if (features.length == 0)
featureList = Collections.emptyList();
else {
featureList = new ArrayList<IVersionedId>(features.length);
for (IFeatureChild f : features)
featureList.add(new VersionedId(f.getId(), f.getVersion()));
}
IFeatureImport[] bundles = feature.getImports();
List<IVersionedId> bundleList;
if (features.length == 0)
bundleList = Collections.emptyList();
else {
bundleList = new ArrayList<IVersionedId>(bundles.length);
for (IFeatureImport f : bundles)
bundleList.add(new VersionedId(f.getId(), f.getVersion()));
}
String suffix = generateFeatureVersionSuffix(featureList, bundleList);
if (suffix == null)
return;
String qualifier = VersionHelper.getQualifier(version);
if (qualifier == null)
qualifier = suffix;
else {
StringBuilder bld = new StringBuilder();
bld.append(qualifier, 0, featureModel.getContextQualifierLength());
bld.append('-');
bld.append(suffix);
qualifier = bld.toString();
}
feature.setVersion(VersionHelper.replaceQualifier(version, qualifier).toString());
}
}