From cc8b91d87312276d763ef82591c9cda5ea1c0418 Mon Sep 17 00:00:00 2001 From: Tobias Oberlies Date: Mon, 24 Sep 2012 16:13:54 +0200 Subject: 388566 Publish osgi.ee capabilities of a.jre IUs - Read org.osgi.framework.system.capabilities from profile files and publish osgi.ee generic capabilities as capabilities of the "a.jre" IUs in the p2 namespace "osgi.ee" Bug: 388566 JREAction: Publish osgi.ee capabilities in 'a.jre' IUs --- .../equinox/internal/p2/publisher/Messages.java | 10 ++- .../internal/p2/publisher/messages.properties | 10 ++- .../equinox/p2/publisher/actions/JREAction.java | 95 +++++++++++++++++++++- .../p2/tests/publisher/actions/JREActionTest.java | 31 +++++++ .../p2/tests/publisher/actions/StatusMatchers.java | 49 +++++++++++ .../ee-capability-syntax-test.profile | 18 ++++ 6 files changed, 208 insertions(+), 5 deletions(-) create mode 100644 bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/StatusMatchers.java create mode 100644 bundles/org.eclipse.equinox.p2.tests/testData/JREActionTest/invalidOsgiEE/ee-capability-syntax-test.profile diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/Messages.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/Messages.java index 45342b967..9a938b8cc 100644 --- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/Messages.java +++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/Messages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2011 IBM Corporation and others. All rights reserved. This + * Copyright (c) 2007, 2012 IBM Corporation 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 @@ -37,9 +37,17 @@ public class Messages extends NLS { public static String message_resultException; public static String message_publisherArguments; + public static String message_problemsWhilePublishingEE; + public static String message_problemsWhileParsingProfileProperty; + public static String message_eeIgnoringNamespace; + public static String message_eeInvalidVersionAttribute; + public static String message_eeMissingNameAttribute; + public static String message_eeMissingVersionAttribute; + public static String exception_artifactRepoNoAppendDestroysInput; public static String error_rootIU_generation; + static { // load message values from bundle file NLS.initializeMessages(BUNDLE_NAME, Messages.class); diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/messages.properties b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/messages.properties index 2cc00ea2d..dd655204b 100644 --- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/messages.properties +++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2007, 2011 IBM Corporation and others. +# Copyright (c) 2007, 2012 IBM Corporation 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 @@ -23,11 +23,17 @@ exception_invalidSiteReferenceInFeature=Invalid site reference {0} in feature {1 exception_repoMustBeURL=Repository location ({0}) must be a URL. exception_sourcePath=Source location ({0}) must be a valid file-system path. exception_nonExistingJreLocationFile=Provided location to JRE \"{0}\" does not exist on the file system. +message_eeIgnoringNamespace=Ignoring unknown capability namespace ''{0}'' +message_eeInvalidVersionAttribute=Syntax error in version ''{0}'' +message_eeMissingNameAttribute=Attribute ''osgi.ee'' is missing for entry {0} +message_eeMissingVersionAttribute=Attribute ''version:List'' is missing for execution environment ''{0}'' message_generatingMetadata = Generating metadata for {0}. message_generationCompleted = Generation completed with success [{0} seconds]. message_noSimpleconfigurator = Could not find simpleconfigurator bundle. message_resultException=Product publishing ended with the following exception: message_publisherArguments=Product publisher application was executed with the following arguments: +message_problemsWhileParsingProfileProperty=Problems while parsing profile property {0} +message_problemsWhilePublishingEE=Problems while publishing execution environment {0} exception_artifactRepoNoAppendDestroysInput = Not appending to artifact repository ({0}) may destroy input files. error_rootIU_generation = Could not generate root IU {0}, {1}, {2}.. -exception_errorLoadingProductFile = An error has occurred while loading product file {0}. Exception details: {1}. \ No newline at end of file +exception_errorLoadingProductFile = An error has occurred while loading product file {0}. Exception details: {1}. diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/actions/JREAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/actions/JREAction.java index dae3d059a..ae10c179e 100644 --- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/actions/JREAction.java +++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/actions/JREAction.java @@ -28,6 +28,7 @@ import org.eclipse.equinox.spi.p2.publisher.PublisherHelper; import org.eclipse.osgi.util.ManifestElement; import org.eclipse.osgi.util.NLS; import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; public class JREAction extends AbstractPublisherAction { private static final String DEFAULT_JRE_NAME = "a.jre"; //$NON-NLS-1$ @@ -38,25 +39,41 @@ public class JREAction extends AbstractPublisherAction { private static final String PROFILE_TARGET_VERSION = "org.eclipse.jdt.core.compiler.codegen.targetPlatform"; //$NON-NLS-1$ private static final String PROFILE_SYSTEM_PACKAGES = "org.osgi.framework.system.packages"; //$NON-NLS-1$ + public static final String NAMESPACE_OSGI_EE = "osgi.ee"; //$NON-NLS-1$ + private File jreLocation; private String environment; private Map profileProperties; + private MultiStatus resultStatus; public JREAction(File location) { this.jreLocation = location; } public JREAction(String environment) { - this.environment = environment; } public IStatus perform(IPublisherInfo publisherInfo, IPublisherResult results, IProgressMonitor monitor) { + String problemMessage = NLS.bind(Messages.message_problemsWhilePublishingEE, jreLocation != null ? jreLocation : environment); + resultStatus = new MultiStatus(Activator.ID, 0, problemMessage, null); + initialize(publisherInfo); IArtifactDescriptor artifact = createJREData(results); if (artifact != null) publishArtifact(artifact, new File[] {jreLocation}, null, publisherInfo, createRootPrefixComputer(jreLocation)); - return Status.OK_STATUS; + + if (resultStatus.isOK()) + return Status.OK_STATUS; + return resultStatus; + } + + private static Status newErrorStatus(String message, Exception exception) { + return new Status(IStatus.ERROR, Activator.ID, message, exception); + } + + private static Status newWarningStatus(String message) { + return new Status(IStatus.WARNING, Activator.ID, message, null); } /** @@ -116,6 +133,7 @@ public class JREAction extends AbstractPublisherAction { List result = new ArrayList(); result.add(PublisherHelper.createSelfCapability(id, version)); generateProvidedPackages(result); + generateOsgiEESystemCapabilities(result); return result; } @@ -137,6 +155,79 @@ public class JREAction extends AbstractPublisherAction { } } + void generateOsgiEESystemCapabilities(List result) { + String message = NLS.bind(Messages.message_problemsWhileParsingProfileProperty, Constants.FRAMEWORK_SYSTEMCAPABILITIES); + MultiStatus parsingStatus = new MultiStatus(Activator.ID, 0, message, null); + + String systemCapabilities = profileProperties.get(Constants.FRAMEWORK_SYSTEMCAPABILITIES); + parseSystemCapabilities(systemCapabilities, parsingStatus, result); + + // result contains the valid entries, parsingStatus the invalid entries + if (!parsingStatus.isOK()) + resultStatus.add(parsingStatus); + } + + static void parseSystemCapabilities(String systemCapabilities, MultiStatus parsingStatus, List parsingResult) { + if (systemCapabilities == null || (systemCapabilities.trim().length() == 0)) { + return; + } + + try { + ManifestElement[] eeEntries = ManifestElement.parseHeader(Constants.FRAMEWORK_SYSTEMCAPABILITIES, systemCapabilities); + parseSystemCapabilities(eeEntries, parsingStatus, parsingResult); + + } catch (BundleException e) { + parsingStatus.add(newErrorStatus(e.getLocalizedMessage(), e)); + } + } + + private static void parseSystemCapabilities(ManifestElement[] systemCapabilities, MultiStatus parsingStatus, List parsingResult) { + for (int capabilityIx = 0; capabilityIx < systemCapabilities.length; capabilityIx++) { + ManifestElement systemCapability = systemCapabilities[capabilityIx]; + + // this is general manifest syntax: a "manifest element" can have multiple "value components" -> all attributes apply to each value component (=namespace) + String[] namespaces = systemCapability.getValueComponents(); + for (int namespaceIx = 0; namespaceIx < namespaces.length; namespaceIx++) { + String namespace = namespaces[namespaceIx]; + + if ("osgi.ee".equals(namespace)) { // this is the OSGi capability namespace "osgi.ee" //$NON-NLS-1$ + parseEECapability(systemCapability, parsingStatus, parsingResult); + + } else { + parsingStatus.add(newWarningStatus(NLS.bind(Messages.message_eeIgnoringNamespace, namespace))); + continue; + } + } + } + } + + private static void parseEECapability(ManifestElement eeCapability, MultiStatus parsingStatus, List parsingResult) { + String eeName = eeCapability.getAttribute("osgi.ee"); // this is an attribute required for capabilities in the "osgi.ee" namespace //$NON-NLS-1$ + if (eeName == null) { + parsingStatus.add(newErrorStatus(NLS.bind(Messages.message_eeMissingNameAttribute, eeCapability), null)); + return; + } + + String[] eeVersions = ManifestElement.getArrayFromList(eeCapability.getAttribute("version:List")); //$NON-NLS-1$ + if (eeVersions == null) { + parsingStatus.add(newErrorStatus(NLS.bind(Messages.message_eeMissingVersionAttribute, eeName), null)); + return; + } + + for (int versionIx = 0; versionIx < eeVersions.length; versionIx++) { + String rawVersion = eeVersions[versionIx]; + try { + Version parsedVersion = Version.parseVersion(rawVersion); + + // complete record -> store + parsingResult.add(MetadataFactory.createProvidedCapability(NAMESPACE_OSGI_EE, eeName, parsedVersion)); + + } catch (IllegalArgumentException e) { + parsingStatus.add(newErrorStatus(NLS.bind(Messages.message_eeInvalidVersionAttribute, rawVersion), e)); + } + } + } + private void generateJREIUData(InstallableUnitDescription iu) { if (profileProperties == null || profileProperties.size() == 0) return; //got nothing diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/JREActionTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/JREActionTest.java index d26bc773c..6faa8d567 100644 --- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/JREActionTest.java +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/JREActionTest.java @@ -12,16 +12,22 @@ package org.eclipse.equinox.p2.tests.publisher.actions; import static org.easymock.EasyMock.expect; +import static org.eclipse.equinox.p2.tests.publisher.actions.StatusMatchers.errorStatus; +import static org.eclipse.equinox.p2.tests.publisher.actions.StatusMatchers.statusWithMessageWhich; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertThat; +import static org.junit.matchers.JUnitMatchers.containsString; import static org.junit.matchers.JUnitMatchers.hasItem; import java.io.*; import java.util.*; import java.util.zip.ZipInputStream; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.equinox.internal.p2.core.helpers.FileUtils; import org.eclipse.equinox.internal.p2.metadata.ArtifactKey; +import org.eclipse.equinox.internal.p2.metadata.ProvidedCapability; import org.eclipse.equinox.p2.metadata.*; import org.eclipse.equinox.p2.publisher.IPublisherInfo; import org.eclipse.equinox.p2.publisher.IPublisherResult; @@ -130,6 +136,31 @@ public class JREActionTest extends ActionTest { } } + public void testOsgiEECapabilities() { + // added for bug 388566 + testAction = new JREAction("JavaSE-1.7"); + testAction.perform(publisherInfo, publisherResult, new NullProgressMonitor()); + Collection capabilities = getPublishedCapabilitiesOf("a.jre.javase"); + assertThat(capabilities, hasItem((IProvidedCapability) new ProvidedCapability("osgi.ee", "JavaSE", Version.parseVersion("1.7")))); + assertThat(capabilities, hasItem((IProvidedCapability) new ProvidedCapability("osgi.ee", "JavaSE", Version.parseVersion("1.5")))); + assertThat(capabilities, hasItem((IProvidedCapability) new ProvidedCapability("osgi.ee", "OSGi/Minimum", Version.parseVersion("1.0")))); + assertThat(capabilities, not(hasItem((IProvidedCapability) new ProvidedCapability("osgi.ee", "J2SE", Version.parseVersion("1.5"))))); + } + + public void testInvalidOsgiEECapabilitySpec() { + testAction = new JREAction(new File(TestActivator.getTestDataFolder(), "JREActionTest/invalidOsgiEE/ee-capability-syntax-test.profile")); + IStatus status = testAction.perform(publisherInfo, publisherResult, new NullProgressMonitor()); + assertThat(status, is(errorStatus())); + + IStatus eeStatus = status.getChildren()[0]; + assertThat(eeStatus.getMessage(), containsString("org.osgi.framework.system.capabilities")); + assertThat(Arrays.asList(eeStatus.getChildren()), hasItem(statusWithMessageWhich(containsString("'osgi.ee' is missing")))); + assertThat(Arrays.asList(eeStatus.getChildren()), hasItem(statusWithMessageWhich(containsString("'version:List' is missing")))); + assertThat(Arrays.asList(eeStatus.getChildren()), hasItem(statusWithMessageWhich(containsString("error in version '1.a.invalidversion'")))); + assertThat(Arrays.asList(eeStatus.getChildren()), hasItem(statusWithMessageWhich(containsString("unknown capability namespace 'other.namespace'")))); + assertThat(eeStatus.getChildren().length, is(4)); + } + private void verifyMetadataIU(String id, int expectedProvidedPackages, Version jreVersion) { IInstallableUnit foo = getPublishedUnit(id); diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/StatusMatchers.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/StatusMatchers.java new file mode 100644 index 000000000..db2451f86 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/StatusMatchers.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2012 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 org.eclipse.core.runtime.IStatus; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.junit.internal.matchers.TypeSafeMatcher; + +public class StatusMatchers { + + public static Matcher errorStatus() { + return new TypeSafeMatcher() { + + public void describeTo(Description description) { + description.appendText("a status with severity ERROR"); + } + + @Override + public boolean matchesSafely(IStatus item) { + return item.matches(IStatus.ERROR); + } + }; + } + + public static Matcher statusWithMessageWhich(final Matcher messageMatcher) { + return new TypeSafeMatcher() { + + public void describeTo(Description description) { + description.appendText("a status with a message which is "); + description.appendDescriptionOf(messageMatcher); + } + + @Override + public boolean matchesSafely(IStatus item) { + return messageMatcher.matches(item.getMessage()); + } + }; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/JREActionTest/invalidOsgiEE/ee-capability-syntax-test.profile b/bundles/org.eclipse.equinox.p2.tests/testData/JREActionTest/invalidOsgiEE/ee-capability-syntax-test.profile new file mode 100644 index 000000000..9662e3a65 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/testData/JREActionTest/invalidOsgiEE/ee-capability-syntax-test.profile @@ -0,0 +1,18 @@ +############################################################################### +# Copyright (c) 2012 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 +############################################################################### + +# the first entry has a valid syntax (there are two value components), but the second value component "other.namespace" is ignored +org.osgi.framework.system.capabilities = \ + osgi.ee; other.namespace; version:List="1.0"; osgi.ee="JavaSE",\ + osgi.ee; osgi.ee="JavaSE"; version:List="1.a.invalidversion",\ + osgi.ee; osgi.ee="OSGi/Minimum",\ + osgi.ee; version:List="2.0,2.1" +osgi.java.profile.name = EECapabilitySyntaxTest -- cgit v1.2.3