blob: 6c7825112a008454f7bcb45de878722a16127f17 [file] [log] [blame]
/*
* Copyright (c) 2014-2017 Eike Stepper (Loehne, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.oomph.targlets.impl;
import org.eclipse.oomph.base.impl.ModelElementImpl;
import org.eclipse.oomph.p2.P2Factory;
import org.eclipse.oomph.p2.Requirement;
import org.eclipse.oomph.p2.VersionSegment;
import org.eclipse.oomph.p2.core.P2Util;
import org.eclipse.oomph.resources.ResourcesUtil;
import org.eclipse.oomph.targlets.FeatureGenerator;
import org.eclipse.oomph.targlets.TargletPackage;
import org.eclipse.oomph.targlets.util.VersionGenerator;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.equinox.internal.p2.metadata.IRequiredCapability;
import org.eclipse.equinox.internal.p2.metadata.InstallableUnit;
import org.eclipse.equinox.internal.p2.metadata.OSGiVersion;
import org.eclipse.equinox.internal.p2.metadata.RequiredCapability;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IRequirement;
import org.eclipse.equinox.p2.metadata.MetadataFactory;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.metadata.VersionRange;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.publisher.AdviceFileAdvice;
import org.eclipse.equinox.p2.publisher.IPublisherInfo;
import org.eclipse.equinox.p2.publisher.PublisherInfo;
import org.eclipse.equinox.p2.publisher.eclipse.Feature;
import org.eclipse.equinox.p2.publisher.eclipse.FeaturesAction;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>Feature Generator</b></em>'.
* <!-- end-user-doc -->
*
* @generated
*/
public class FeatureGeneratorImpl extends ModelElementImpl implements FeatureGenerator
{
private static final IPath MANIFEST_PATH = new Path(FEATURE_XML);
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected FeatureGeneratorImpl()
{
super();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass()
{
return TargletPackage.Literals.FEATURE_GENERATOR;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public void generateIUs(IProject project, final String qualifierReplacement, final Map<String, Version> iuVersions, final EList<IInstallableUnit> result)
throws Exception
{
ResourcesUtil.runWithFile(project, MANIFEST_PATH, new ResourcesUtil.RunnableWithFile()
{
public void run(File projectFolder, File file) throws Exception
{
FeatureGeneratorAction action = new FeatureGeneratorAction();
action.generateIUs(projectFolder, qualifierReplacement, iuVersions, result);
}
});
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
@SuppressWarnings("unchecked")
public Object eInvoke(int operationID, EList<?> arguments) throws InvocationTargetException
{
switch (operationID)
{
case TargletPackage.FEATURE_GENERATOR___GENERATE_IUS__IPROJECT_STRING_MAP_ELIST:
try
{
generateIUs((IProject)arguments.get(0), (String)arguments.get(1), (Map<String, Version>)arguments.get(2), (EList<IInstallableUnit>)arguments.get(3));
return null;
}
catch (Throwable throwable)
{
throw new InvocationTargetException(throwable);
}
}
return super.eInvoke(operationID, arguments);
}
/**
* @author Eike Stepper
*/
private static final class FeatureGeneratorAction extends FeaturesAction
{
public FeatureGeneratorAction()
{
super((File[])null);
setPublisherInfo(new PublisherInfo());
}
public void generateIUs(File projectFolder, String qualifierReplacement, final Map<String, Version> ius, EList<IInstallableUnit> result) throws Exception
{
Feature[] features = getFeatures(new File[] { projectFolder });
if (features == null || features.length == 0)
{
return;
}
Feature feature = features[0];
String version = feature.getVersion();
feature.setVersion(VersionGenerator.replaceQualifier(version, qualifierReplacement));
createAdviceFileAdvice(feature, info);
feature.setEnvironment("", "", "", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
List<IInstallableUnit> childIUs = Collections.emptyList();
InstallableUnit iu = (InstallableUnit)createGroupIU(feature, childIUs, info);
List<IRequirement> requirements = iu.getRequirements();
String licenseFeature = feature.getLicenseFeature();
String licenseFeatureVersion = feature.getLicenseFeatureVersion();
boolean hasLicenseFeature = licenseFeature != null && licenseFeatureVersion != null;
int size = requirements.size();
IRequirement[] newRequirements = new IRequirement[size + (hasLicenseFeature ? 1 : 0)];
if (hasLicenseFeature)
{
VersionRange osgiRange;
Version osgiVersion = OSGiVersion.create(licenseFeatureVersion);
if (osgiVersion.equals(OSGiVersion.emptyVersion))
{
osgiRange = VersionRange.emptyRange;
}
else
{
osgiRange = new VersionRange(osgiVersion, true, osgiVersion, true);
VersionRange adjustedRange = adjustQualifier(osgiRange);
if (adjustedRange != null)
{
osgiRange = adjustedRange;
}
}
String namespace = IInstallableUnit.NAMESPACE_IU_ID;
String name = licenseFeature + Requirement.FEATURE_SUFFIX;
IRequirement requirement = MetadataFactory.createRequirement(namespace, name, osgiRange, null, true, false);
newRequirements[size] = requirement;
iu.setProperty(FeatureGenerator.PROP_REQUIRED_LICENCSE_FEATURE_ID, name);
iu.setProperty(FeatureGenerator.PROP_REQUIRED_LICENCSE_FEATURE_VERSION_RANGE, osgiRange.toString());
}
// Adjust childIU requirements to support possible .qualifier specifications
if (qualifierReplacement != null)
{
for (int i = 0; i < size; i++)
{
IRequirement requirement = requirements.get(i);
if (requirement instanceof RequiredCapability && P2Util.isSimpleRequiredCapability(requirement))
{
RequiredCapability capability = (RequiredCapability)requirement;
final VersionRange originalRange = capability.getRange();
final VersionRange adjustedRange = adjustQualifier(originalRange);
final String namespace = capability.getNamespace();
final String name = capability.getName();
final IMatchExpression<IInstallableUnit> filter = capability.getFilter();
final boolean optional = capability.getMin() == 0;
final boolean multiple = capability.getMax() > 1;
if (adjustedRange != null)
{
requirement = MetadataFactory.createRequirement(namespace, name, adjustedRange, filter, optional, multiple);
}
else
{
requirement = new IRequiredCapability()
{
private IRequirement delegate;
private VersionRange versionRange;
private IRequirement getDelegate()
{
if (delegate == null)
{
delegate = MetadataFactory.createRequirement(namespace, name, getRange(), filter, optional, multiple);
}
return delegate;
}
public String getName()
{
return name;
}
public String getNamespace()
{
return namespace;
}
public VersionRange getRange()
{
if (versionRange == null)
{
Version version = ius.get(name);
if (version != null)
{
versionRange = P2Factory.eINSTANCE.createVersionRange(version, VersionSegment.MICRO);
}
else
{
versionRange = originalRange;
}
}
return versionRange;
}
public int getMin()
{
return getDelegate().getMin();
}
public int getMax()
{
return getDelegate().getMax();
}
public IMatchExpression<IInstallableUnit> getFilter()
{
return getDelegate().getFilter();
}
public IMatchExpression<IInstallableUnit> getMatches()
{
return getDelegate().getMatches();
}
public boolean isMatch(IInstallableUnit iu)
{
return getDelegate().isMatch(iu);
}
public boolean isGreedy()
{
return getDelegate().isGreedy();
}
public String getDescription()
{
return getDelegate().getDescription();
}
@Override
public String toString()
{
if (delegate != null)
{
return delegate.toString();
}
return name + " " + versionRange; //$NON-NLS-1$
}
};
}
}
newRequirements[i] = requirement;
}
iu.setRequiredCapabilities(newRequirements);
}
result.add(iu);
InstallableUnitDescription[] otherDescriptions = processAdditionalInstallableUnitsAdvice(iu, info);
if (otherDescriptions != null)
{
for (InstallableUnitDescription otherDescription : otherDescriptions)
{
IInstallableUnit otherIU = MetadataFactory.createInstallableUnit(otherDescription);
result.add(otherIU);
}
}
}
private void createAdviceFileAdvice(Feature feature, IPublisherInfo publisherInfo)
{
// assume p2.inf is co-located with feature.xml
String location = feature.getLocation();
if (location != null)
{
String groupId = getTransformedId(feature.getId(), /* isPlugin */false, /* isGroup */true);
AdviceFileAdvice advice = new AdviceFileAdvice(groupId, Version.parseVersion(feature.getVersion()), new Path(location), new Path("p2.inf")); //$NON-NLS-1$
if (advice.containsAdvice())
{
publisherInfo.addAdvice(advice);
}
}
}
private static String getTransformedId(String original, boolean isPlugin, boolean isGroup)
{
return isPlugin ? original : original + (isGroup ? Requirement.FEATURE_SUFFIX : ".feature.jar"); //$NON-NLS-1$
}
private static VersionRange adjustQualifier(VersionRange range)
{
if (!VersionRange.emptyRange.equals(range))
{
Version minimum = range.getMinimum();
if (minimum instanceof OSGiVersion)
{
OSGiVersion osgiMinimum = (OSGiVersion)minimum;
if (osgiMinimum.equals(range.getMaximum()))
{
minimum = OSGiVersion.createOSGi(osgiMinimum.getMajor(), osgiMinimum.getMinor(), osgiMinimum.getMicro());
Version maximum = OSGiVersion.createOSGi(osgiMinimum.getMajor(), osgiMinimum.getMinor(), osgiMinimum.getMicro() + 1);
return new VersionRange(minimum, true, maximum, false);
}
}
}
return null;
}
}
} // FeatureGeneratorImpl