summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKatya Todorova2011-07-21 12:57:59 (EDT)
committer Tobias Oberlies2011-07-22 10:34:45 (EDT)
commit0871174a5a8e7f8962f0abb7403b5569aead827c (patch)
treec4aa39fc464e97dfc9643615d5a8eeec5728ab24
parentf7592660fae6b295848c69ec4d735c089198c490 (diff)
downloadrt.equinox.p2-0871174a5a8e7f8962f0abb7403b5569aead827c.zip
rt.equinox.p2-0871174a5a8e7f8962f0abb7403b5569aead827c.tar.gz
rt.equinox.p2-0871174a5a8e7f8962f0abb7403b5569aead827c.tar.bz2
325622 Introduce "type" attribute in product definitions
The product publisher now accepts the attribute type="mixed", indicating that the product's content is defined via both features and products.
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/IProductDescriptor.java8
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/Messages.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/ProductContentType.java62
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/ProductFile.java55
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/messages.properties2
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/ProductAction.java38
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/AllTests.java1
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/ProductContentTypeTest.java167
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/EmptyContentType.product13
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/InvalidContentType.product13
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/MixedContentProduct.product13
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/NoContentType.product13
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/OverrideUseFeaturesAttr.product13
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/OverrideUseFeaturesAttr2.product13
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/ProductWithBundle.product13
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/ProductWithFeature.product13
16 files changed, 393 insertions, 46 deletions
diff --git a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/IProductDescriptor.java b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/IProductDescriptor.java
index e3bfbba..721ee3b 100644
--- a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/IProductDescriptor.java
+++ b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/IProductDescriptor.java
@@ -7,6 +7,7 @@
* Contributors:
* Code 9 - initial API and implementation
* EclipseSource - ongoing development
+ * SAP AG - ongoing development
******************************************************************************/
package org.eclipse.equinox.internal.p2.publisher.eclipse;
@@ -81,11 +82,16 @@ public interface IProductDescriptor {
public String getProductName();
/**
- * Specifies whether this product was built using features or not.
+ * Specifies whether this product was built using features only or not.
*/
public boolean useFeatures();
/**
+ * Specifies what kind of installable units (e.g. bundles, features or everything) are included in the product.
+ */
+ public ProductContentType getProductContentType();
+
+ /**
* Returns the version of the product.
*/
public String getVersion();
diff --git a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/Messages.java b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/Messages.java
index 0acc6c2..f469e80 100644
--- a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/Messages.java
+++ b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/Messages.java
@@ -8,6 +8,7 @@
* Contributors:
* IBM - Initial API and implementation
* SAP AG - consolidation of publishers for PDE formats
+ * SAP AG - ongoing development
*******************************************************************************/
package org.eclipse.equinox.internal.p2.publisher.eclipse;
@@ -20,6 +21,7 @@ public class Messages extends NLS {
public static String exception_missingElement;
public static String exception_featureParse;
public static String exception_productParse;
+ public static String exception_invalidProductContentType;
// feature parsing
public static String feature_parse_invalidIdOrVersion;
diff --git a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/ProductContentType.java b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/ProductContentType.java
new file mode 100644
index 0000000..d8be6e9
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/ProductContentType.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SAP AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher.eclipse;
+
+import java.util.*;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Enumeration for all types of installable items which are accepted in a product.
+ */
+public enum ProductContentType {
+
+ BUNDLES("bundles"), // only bundles are accepted in the product //$NON-NLS-1$
+ FEATURES("features"), // only features are accepted in the product //$NON-NLS-1$
+ MIXED("mixed"); // all kinds of installable units are accepted in the product //$NON-NLS-1$
+
+ private String contentTypeString;
+ private static Map<String, ProductContentType> mappings = new HashMap<String, ProductContentType>();
+
+ static {
+ mappings.put("bundles", BUNDLES); //$NON-NLS-1$
+ mappings.put("features", FEATURES); //$NON-NLS-1$
+ mappings.put("mixed", MIXED); //$NON-NLS-1$
+ }
+
+ private ProductContentType(String contentTypeString) {
+ this.contentTypeString = contentTypeString;
+ }
+
+ @Override
+ public String toString() {
+ return contentTypeString;
+ }
+
+ /**
+ * Parses a string to the content type which can be included in the product.
+ * @param typeAsString input string to be parsed
+ * @return the content type which can be included in the product.
+ * @throws IllegalArgumentException if <code>typeAsString</code> is not a valid for a product content type
+ */
+ public static ProductContentType toProductContentType(String typeAsString) throws IllegalArgumentException {
+ ProductContentType result = mappings.get(typeAsString.toLowerCase(Locale.ENGLISH));
+ if (result == null)
+ throw new IllegalArgumentException(NLS.bind(Messages.exception_invalidProductContentType, typeAsString, getAllowedSetOfValues()));
+ return result;
+ }
+
+ /**
+ * @return set of all possible values for a product content type
+ */
+ public static Set<String> getAllowedSetOfValues() {
+ return mappings.keySet();
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/ProductFile.java b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/ProductFile.java
index 51d8711..ce0b654 100644
--- a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/ProductFile.java
+++ b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/ProductFile.java
@@ -10,43 +10,25 @@
* Code 9 - Additional function and fixes
* EclipseSource - ongoing development
* Felix Riegger (SAP AG) - consolidation of publishers for PDE formats (bug 331974)
+ * SAP AG - ongoing development
*******************************************************************************/
package org.eclipse.equinox.internal.p2.publisher.eclipse;
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.io.*;
+import java.util.*;
import java.util.Map.Entry;
-import java.util.Properties;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
+import javax.xml.parsers.*;
+import org.eclipse.core.runtime.*;
import org.eclipse.equinox.frameworkadmin.BundleInfo;
-import org.eclipse.equinox.internal.p2.core.helpers.CollectionUtils;
-import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
-import org.eclipse.equinox.internal.p2.core.helpers.URLUtil;
+import org.eclipse.equinox.internal.p2.core.helpers.*;
import org.eclipse.equinox.p2.metadata.IVersionedId;
import org.eclipse.equinox.p2.metadata.VersionedId;
import org.eclipse.equinox.p2.publisher.eclipse.FeatureEntry;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.internal.publishing.Activator;
-import org.xml.sax.Attributes;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
+import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
/**
@@ -68,6 +50,7 @@ public class ProductFile extends DefaultHandler implements IProductDescriptor {
protected static final String ATTRIBUTE_VERSION = "version"; //$NON-NLS-1$
protected static final String ATTRIBUTE_ID = "id"; //$NON-NLS-1$
private static final String ATTRIBUTE_UID = "uid"; //$NON-NLS-1$
+ private static final String ATTRIBUTE_CONTENT_TYPE = "type"; //$NON-NLS-1$
private static final String PROPERTY_ECLIPSE_APPLICATION = "eclipse.application"; //$NON-NLS-1$
private static final String PROPERTY_ECLIPSE_PRODUCT = "eclipse.product"; //$NON-NLS-1$
@@ -157,7 +140,7 @@ public class ProductFile extends DefaultHandler implements IProductDescriptor {
private String platformConfigPath = null;
private String id = null;
private String uid = null;
- private boolean useFeatures = false;
+ private ProductContentType productContentType = null;
protected List<FeatureEntry> plugins = new ArrayList<FeatureEntry>();
protected List<FeatureEntry> fragments = new ArrayList<FeatureEntry>();
private final List<FeatureEntry> features = new ArrayList<FeatureEntry>();
@@ -407,7 +390,7 @@ public class ProductFile extends DefaultHandler implements IProductDescriptor {
* false otherwise.
*/
public boolean useFeatures() {
- return useFeatures;
+ return productContentType == ProductContentType.FEATURES;
}
/**
@@ -788,9 +771,18 @@ public class ProductFile extends DefaultHandler implements IProductDescriptor {
application = attributes.getValue(ATTRIBUTE_APPLICATION);
if (attributes.getIndex(ATTRIBUTE_INCLUDE_LAUNCHERS) >= 0)
includeLaunchers = Boolean.valueOf(attributes.getValue(ATTRIBUTE_INCLUDE_LAUNCHERS));
- String use = attributes.getValue("useFeatures"); //$NON-NLS-1$
- if (use != null)
- useFeatures = Boolean.valueOf(use).booleanValue();
+ String contentTypeString = attributes.getValue(ATTRIBUTE_CONTENT_TYPE);
+ if (contentTypeString != null)
+ productContentType = ProductContentType.toProductContentType(contentTypeString);
+ if (productContentType == null) { // useFeatures attribute is taken into account only if the contentType attribute is missing
+ String use = attributes.getValue("useFeatures"); //$NON-NLS-1$
+ // for backward compatibility with the old behavior
+ if (use != null && Boolean.valueOf(use).booleanValue())
+ productContentType = ProductContentType.FEATURES;
+ else
+ productContentType = ProductContentType.BUNDLES;
+ }
+
version = attributes.getValue(ATTRIBUTE_VERSION);
}
@@ -881,4 +873,7 @@ public class ProductFile extends DefaultHandler implements IProductDescriptor {
addIcon(OS_MACOSX, attributes.getValue(ATTRIBUTE_ICON));
}
+ public ProductContentType getProductContentType() {
+ return productContentType;
+ }
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/messages.properties b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/messages.properties
index 1b27f22..b6dff80 100644
--- a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/messages.properties
+++ b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/internal/p2/publisher/eclipse/messages.properties
@@ -8,12 +8,14 @@
# Contributors:
# IBM Corporation - initial API and implementation
# SAP AG - consolidation of publishers for PDE formats
+# SAP AG - ongoing development
###############################################################################
### exception
exception_missingElement = Unable to find element: {0}.
exception_featureParse = Problems parsing the feature {0}.
exception_productParse = Problems parsing the product file {0}.
+exception_invalidProductContentType=Provided value \"{0}\" for product content type is not valid. Allowed values are {1}
### feature parsing
feature_parse_invalidIdOrVersion= Invalid ID \"{0}\" or version \"{1}\" encountered.
diff --git a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/ProductAction.java b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/ProductAction.java
index 35222d7..8c5bec5 100644
--- a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/ProductAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/ProductAction.java
@@ -14,11 +14,11 @@ package org.eclipse.equinox.p2.publisher.eclipse;
import java.io.File;
import java.util.*;
import org.eclipse.core.runtime.*;
-import org.eclipse.equinox.internal.p2.publisher.eclipse.IProductDescriptor;
-import org.eclipse.equinox.internal.p2.publisher.eclipse.Messages;
+import org.eclipse.equinox.internal.p2.publisher.eclipse.*;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.publisher.*;
import org.eclipse.equinox.p2.publisher.actions.*;
+import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.internal.publishing.Activator;
public class ProductAction extends AbstractPublisherAction {
@@ -123,21 +123,29 @@ public class ProductAction extends AbstractPublisherAction {
private void createRootAdvice() {
Collection<IVersionedId> list;
- if (product.useFeatures()) {
- // TODO: We need a real namespace here
- list = versionElements(listElements(product.getFeatures(), ".feature.group"), IInstallableUnit.NAMESPACE_IU_ID); //$NON-NLS-1$
-
- if (!product.getBundles(true).isEmpty()) {
- finalStatus.add(new Status(IStatus.INFO, Activator.ID, Messages.bundlesInProductFileIgnored));
- }
- } else {
- //TODO: We need a real namespace here
- list = versionElements(listElements(product.getBundles(true), null), IInstallableUnit.NAMESPACE_IU_ID);
+ switch (product.getProductContentType()) { // add new case for each new content type included in product
+ case MIXED : // include all content types
+ list = versionElements(listElements(product.getFeatures(), ".feature.group"), IInstallableUnit.NAMESPACE_IU_ID); //$NON-NLS-1$
+ list.addAll(versionElements(listElements(product.getBundles(true), null), IInstallableUnit.NAMESPACE_IU_ID));
+ break;
+ case FEATURES : // include features only
+ list = versionElements(listElements(product.getFeatures(), ".feature.group"), IInstallableUnit.NAMESPACE_IU_ID); //$NON-NLS-1$
+
+ if (!product.getBundles(true).isEmpty()) {
+ finalStatus.add(new Status(IStatus.INFO, Activator.ID, Messages.bundlesInProductFileIgnored));
+ }
+ break;
+ case BUNDLES : // include bundles only
+ list = versionElements(listElements(product.getBundles(true), null), IInstallableUnit.NAMESPACE_IU_ID);
- if (!product.getFeatures().isEmpty()) {
- finalStatus.add(new Status(IStatus.INFO, Activator.ID, Messages.featuresInProductFileIgnored));
- }
+ if (!product.getFeatures().isEmpty()) {
+ finalStatus.add(new Status(IStatus.INFO, Activator.ID, Messages.featuresInProductFileIgnored));
+ }
+ break;
+ default :
+ throw new IllegalStateException(NLS.bind(Messages.exception_invalidProductContentType, product.getProductContentType().toString(), ProductContentType.getAllowedSetOfValues().toString()));
}
+
info.addAdvice(new RootIUAdvice(list));
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/AllTests.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/AllTests.java
index d5d9543..d8dd352 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/AllTests.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/AllTests.java
@@ -37,6 +37,7 @@ public class AllTests extends TestCase {
suite.addTestSuite(ProductActionTest.class);
suite.addTestSuite(ProductActionTestMac.class);
suite.addTestSuite(ProductActionWithAdviceFileTest.class);
+ suite.addTestSuite(ProductContentTypeTest.class);
suite.addTestSuite(ProductFileAdviceTest.class);
suite.addTestSuite(ProductFileTest.class);
suite.addTestSuite(RootFilesActionTest.class);
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/ProductContentTypeTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/ProductContentTypeTest.java
new file mode 100644
index 0000000..c096d32
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/ProductContentTypeTest.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SAP AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.publisher.actions;
+
+import java.io.File;
+import java.util.*;
+import org.eclipse.equinox.internal.p2.publisher.eclipse.ProductFile;
+import org.eclipse.equinox.p2.metadata.*;
+import org.eclipse.equinox.p2.publisher.*;
+import org.eclipse.equinox.p2.publisher.eclipse.ProductAction;
+import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
+import org.eclipse.equinox.p2.tests.TestData;
+
+/**
+ * Test product publishing when the <code>type</code> attribute in the .product file
+ * and how its semantics replaces the <code>useFeatures</code> attribute.
+ * Verify that all the installable units, expected to be included in the product, are published as its requirements.
+ */
+public class ProductContentTypeTest extends AbstractProvisioningTest {
+
+ private static final String TEST_DATA_FOLDER = "ProductContentTypeTest";
+ private static final String flavor = "tooling";
+
+ private List<IInstallableUnit> cusList;
+ private IInstallableUnit featureIU = createIU("TestFeature.feature.group");
+ private IInstallableUnit bundleIU = createIU("TestBundle");
+
+ public void setUp() throws Exception {
+ initCUsList();
+ }
+
+ /**
+ * Publish product with attribute <code>type="bundles"</code>.
+ * Check that the generated product IU
+ * requires the default CU list + CU for the product + bundle IU.
+ */
+ public void test01PublishWithBundle() throws Exception {
+ testTemplate("ProductWithBundle.product", "1", cusList.size() + 2, bundleIU);
+ }
+
+ /**
+ * Publish product with attribute <code>type="features"</code>.
+ * Check that the generated product IU
+ * requires the default CU list + CU for the product + feature IU.
+ */
+ public void test02PublishWithFeature() throws Exception {
+ testTemplate("ProductWithFeature.product", "1", cusList.size() + 2, featureIU);
+ }
+
+ /**
+ * Publish product with attribute <code>type="mixed"</code>.
+ * Check that the generated product IU
+ * requires the default CU list + CU for the product + bundle IU + feature IU.
+ */
+ public void test03PublishWithMixedContent() throws Exception {
+ testTemplate("MixedContentProduct.product", "1", cusList.size() + 3, bundleIU, featureIU);
+ }
+
+ /**
+ * Publish product with invalid value for attribute <code>type</code>.
+ */
+ public void test04PublishWithInvalidContentType() throws Exception {
+ File productFileLocation = TestData.getFile(TEST_DATA_FOLDER, "InvalidContentType.product");
+ try {
+ new ProductFile(productFileLocation.toString());
+ fail("Parsing of product file with invalid content type was successful");
+ } catch (IllegalArgumentException iae) {
+ // success
+ }
+ }
+
+ /**
+ * Publish product with attribute <code>type=""</code>.
+ */
+ public void test05PublishWithEmptyContentType() throws Exception {
+ File productFileLocation = TestData.getFile(TEST_DATA_FOLDER, "EmptyContentType.product");
+ try {
+ new ProductFile(productFileLocation.toString());
+ fail("Parsing of product file with empty content type was successful");
+ } catch (IllegalArgumentException iae) {
+ // success
+ }
+ }
+
+ /**
+ * Publish product with attributes <code>type="bundles"</code> and <code>useFeatures="true"</code>.
+ * Check that the generated product IU
+ * requires the default CU list + CU for the product + bundle IU.
+ */
+ public void test06OverrideUseFeaturesAttr() throws Exception {
+ testTemplate("OverrideUseFeaturesAttr.product", "1", cusList.size() + 2, bundleIU);
+ }
+
+ /**
+ * Publish product with attributes <code>type="mixed"</code> and <code>useFeatures="true"</code>.
+ * Check that the generated product IU
+ * requires the default CU list + CU for the product + bundle IU + feature IU.
+ */
+ public void test07OverrideUseFeaturesAttr2() throws Exception {
+ testTemplate("OverrideUseFeaturesAttr2.product", "1", cusList.size() + 3, bundleIU, featureIU);
+ }
+
+ private void initCUsList() {
+ cusList = new ArrayList<IInstallableUnit>();
+ cusList.add(createIU(flavor + ".source.default"));
+ cusList.add(createIU(flavor + ".osgi.bundle.default"));
+ cusList.add(createIU(flavor + ".org.eclipse.update.feature.default"));
+ cusList.add(createIU("a.jre.javase", Version.create("1.6.0")));
+ cusList.add(createIU("config.a.jre.javase", Version.create("1.6.0")));
+ }
+
+ private void testTemplate(String productFileName, String productVersion, int expectedRequirementsSize, IInstallableUnit... requiredInstallableUnits) throws Exception {
+
+ File productFileLocation = TestData.getFile(TEST_DATA_FOLDER, productFileName);
+ IInstallableUnit productIU = publishProduct(productFileLocation, productFileName);
+ Collection<IRequirement> requirements = productIU.getRequirements();
+ assertEquals("Requirements count doed not match", expectedRequirementsSize, requirements.size());
+ verifyRequirementsForConfigurationUnits(requirements, productFileName, productVersion);
+ for (IInstallableUnit iu : requiredInstallableUnits) {
+ assertTrue("Installable unit " + iu.getId() + " is not included in the requirements", verifyRequirement(requirements, iu));
+ }
+ }
+
+ private IInstallableUnit publishProduct(final File productFileLocation, final String productIUName) throws Exception {
+ ProductFile productFile = new ProductFile(productFileLocation.toString());
+ ProductAction testAction = new ProductAction(null, productFile, flavor, null);
+ IPublisherResult publisherResult = new PublisherResult();
+ testAction.perform(new PublisherInfo(), publisherResult, null);
+ Collection<IInstallableUnit> ius = publisherResult.getIUs(productIUName, IPublisherResult.NON_ROOT);
+ assertEquals(1, ius.size());
+ return ius.iterator().next();
+ }
+
+ private void verifyRequirementsForConfigurationUnits(Collection<IRequirement> requirements, String productName, String productVersion) {
+
+ List<IInstallableUnit> cusListCopy = new ArrayList<IInstallableUnit>(cusList);
+ cusListCopy.add(createIU(flavor + productName + ".configuration", Version.create(productVersion)));
+ for (Iterator<IInstallableUnit> cusIterator = cusListCopy.iterator(); cusIterator.hasNext();) {
+ IInstallableUnit cu = cusIterator.next();
+ if (verifyRequirement(requirements, cu)) {
+ cusIterator.remove();
+ }
+ }
+
+ assertTrue("Some of the default configuration units are not included in the product - " + cusListCopy, cusListCopy.isEmpty());
+ }
+
+ private boolean verifyRequirement(Collection<IRequirement> requirements, IInstallableUnit iu) {
+
+ for (Iterator<IRequirement> iterator = requirements.iterator(); iterator.hasNext();) {
+ IRequirement requirement = iterator.next();
+ if (requirement.isMatch(iu)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/EmptyContentType.product b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/EmptyContentType.product
new file mode 100644
index 0000000..8a7737c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/EmptyContentType.product
@@ -0,0 +1,13 @@
+<product name="EmptyContentType" id="EmptyContentType.product" version="1" type="" includeLaunchers="false">
+
+ <configIni use="default">
+ </configIni>
+
+ <plugins>
+ <plugin id="TestBundle"/>
+ </plugins>
+
+ <features>
+ <feature id="TestFeature"/>
+ </features>
+</product> \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/InvalidContentType.product b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/InvalidContentType.product
new file mode 100644
index 0000000..d47288e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/InvalidContentType.product
@@ -0,0 +1,13 @@
+<product name="InvalidContentType" id="InvalidContentType.product" version="1" type="you can put anything you want here except a valid content type" includeLaunchers="false">
+
+ <configIni use="default">
+ </configIni>
+
+ <plugins>
+ <plugin id="TestBundle"/>
+ </plugins>
+
+ <features>
+ <feature id="TestFeature"/>
+ </features>
+</product>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/MixedContentProduct.product b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/MixedContentProduct.product
new file mode 100644
index 0000000..6297b4e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/MixedContentProduct.product
@@ -0,0 +1,13 @@
+<product name="MixedContentProduct" id="MixedContentProduct.product" version="1" type="mixed" includeLaunchers="false">
+
+ <configIni use="default">
+ </configIni>
+
+ <plugins>
+ <plugin id="TestBundle"/>
+ </plugins>
+
+ <features>
+ <feature id="TestFeature"/>
+ </features>
+</product>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/NoContentType.product b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/NoContentType.product
new file mode 100644
index 0000000..f72a955
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/NoContentType.product
@@ -0,0 +1,13 @@
+<product name="MixedContentProduct" id="MixedContentProduct.product" version="1" includeLaunchers="false">
+
+ <configIni use="default">
+ </configIni>
+
+ <plugins>
+ <plugin id="TestBundle"/>
+ </plugins>
+
+ <features>
+ <feature id="TestFeature"/>
+ </features>
+</product>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/OverrideUseFeaturesAttr.product b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/OverrideUseFeaturesAttr.product
new file mode 100644
index 0000000..3d2691c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/OverrideUseFeaturesAttr.product
@@ -0,0 +1,13 @@
+<product name="OverrideUseFeaturesAttr" id="OverrideUseFeaturesAttr.product" version="1" useFeatures="true" type="bundles" includeLaunchers="false">
+
+ <configIni use="default">
+ </configIni>
+
+ <plugins>
+ <plugin id="TestBundle"/>
+ </plugins>
+
+ <features>
+ <feature id="TestFeature"/>
+ </features>
+</product>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/OverrideUseFeaturesAttr2.product b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/OverrideUseFeaturesAttr2.product
new file mode 100644
index 0000000..c85e0bb
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/OverrideUseFeaturesAttr2.product
@@ -0,0 +1,13 @@
+<product name="OverrideUseFeaturesAttr2" id="OverrideUseFeaturesAttr2.product" version="1" useFeatures="true" type="mixed" includeLaunchers="false">
+
+ <configIni use="default">
+ </configIni>
+
+ <plugins>
+ <plugin id="TestBundle"/>
+ </plugins>
+
+ <features>
+ <feature id="TestFeature"/>
+ </features>
+</product>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/ProductWithBundle.product b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/ProductWithBundle.product
new file mode 100644
index 0000000..fe40c13
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/ProductWithBundle.product
@@ -0,0 +1,13 @@
+<product name="ProductWithBundle" id="ProductWithBundle.product" version="1" type="bundles" includeLaunchers="false">
+
+ <configIni use="default">
+ </configIni>
+
+ <plugins>
+ <plugin id="TestBundle"/>
+ </plugins>
+
+ <features>
+ <feature id="TestFeature"/>
+ </features>
+</product>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/ProductWithFeature.product b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/ProductWithFeature.product
new file mode 100644
index 0000000..867a1f3
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/ProductContentTypeTest/ProductWithFeature.product
@@ -0,0 +1,13 @@
+<product name="ProductWithFeature" id="ProductWithFeature.product" version="1" type="features" includeLaunchers="false">
+
+ <configIni use="default">
+ </configIni>
+
+ <plugins>
+ <plugin id="TestBundle"/>
+ </plugins>
+
+ <features>
+ <feature id="TestFeature"/>
+ </features>
+</product>