diff --git a/org.eclipse.xtext.tests/src/org/eclipse/xtext/util/MergeableManifest2Test.java b/org.eclipse.xtext.tests/src/org/eclipse/xtext/util/MergeableManifest2Test.java index c1a79d8b1..d32d9e8da 100644 --- a/org.eclipse.xtext.tests/src/org/eclipse/xtext/util/MergeableManifest2Test.java +++ b/org.eclipse.xtext.tests/src/org/eclipse/xtext/util/MergeableManifest2Test.java @@ -389,11 +389,6 @@ public class MergeableManifest2Test { assertEquals("Signature-Version: 1.0" + NL, write("Signature-Version: 1.0" + NL)); } - @Test - public void write_oneMainEntry_missingVersion() throws Exception { - assertEquals("", write("test: 0\n")); - } - @Test public void write_oneMainEntry_afterVersion() throws Exception { assertEquals("Manifest-Version: 1.0" + NL + "test: 0" + NL, @@ -1396,7 +1391,7 @@ public class MergeableManifest2Test { // @formatter:on MergeableManifest2 manifest = newManifest(content); manifest.addRequiredBundles(""); - + assertEquals(expected, write(manifest)); } @@ -1424,7 +1419,7 @@ public class MergeableManifest2Test { // @formatter:on MergeableManifest2 manifest = newManifest(content); manifest.addRequiredBundles("org.eclipse.xtext.util;bundle-version=\"1.0\""); - + assertEquals(expected, write(manifest)); } @@ -1452,7 +1447,94 @@ public class MergeableManifest2Test { // @formatter:on MergeableManifest2 manifest = newManifest(content); manifest.addRequiredBundles("org.eclipse.xtext;bundle-version=\"1.0\""); - + + assertEquals(expected, write(manifest)); + } + + @Test + public void readWrite_BundleManifestVersion() throws Exception { + // @formatter:off + String content = + "Bundle-ManifestVersion: 2" + NL + + "Bundle-Name: org.mealy.ui" + NL + + "Bundle-Vendor: My Company" + NL + + "Bundle-Version: 1.0.0.qualifier" + NL + + "Bundle-SymbolicName: org.mealy.ui; singleton:=true" + NL + + "Bundle-ActivationPolicy: lazy" + NL + + "Require-Bundle: org.mealy,org.mealy.ide,org.eclipse.xtext.ui,org.eclipse" + NL + + " .xtext.ui.shared,org.eclipse.xtext.ui.codetemplates.ui,org.eclipse.ui.e" + NL + + " ditors;bundle-version=\"3.5.0\",org.eclipse.ui.ide;bundle-version=\"3.5.0\"" + NL + + " ,org.eclipse.ui,org.eclipse.compare,org.eclipse.xtext.builder,org.eclip" + NL + + " se.xtext.xbase.lib;bundle-version=\"2.14.0\",org.eclipse.xtend.lib;bundle" + NL + + " -version=\"2.14.0\";resolution:=optional,org.eclipse.ui.console;bundle-ve" + NL + + " rsion=\"3.8.100\"" + NL + + "Import-Package: org.apache.log4j" + NL + + "Bundle-RequiredExecutionEnvironment: JavaSE-11" + NL + + "Automatic-Module-Name: org.mealy.ui" + NL + + "Export-Package: org.mealy.ui.internal,org.mealy.ui.quickfix,org.mealy.ui" + NL + + " .contentassist" + NL + + "Bundle-Activator: org.mealy.ui.internal.MealyActivator" + NL + + "Bundle-ClassPath: lib/mealyMachine-1.0-SNAPSHOT.jar," + NL + + " ." + NL; + // @formatter:on + MergeableManifest2 manifest = newManifest(content); + + assertEquals(content, write(manifest)); + } + + @Test + public void replicate_issue_1120_linebreaks_inside_bundle_version_or_name() throws Exception { + // @formatter:off + String content = + "Manifest-Version: 1.0" + NL + + "Automatic-Module-Name: org.hello.ui" + NL + + "Bundle-ManifestVersion: 2" + NL + + "Bundle-Name: org.hello.ui" + NL + + "Bundle-Vendor: My Company" + NL + + "Bundle-Version: 1.0.0.qualifier" + NL + + "Bundle-SymbolicName: org.hello.ui; singleton:=true" + NL + + "Bundle-ActivationPolicy: lazy" + NL + + "Require-Bundle: org.hello,org.hello.ide,org.eclipse.xtext.ui,org.eclipse" + NL + + " .xtext.ui.shared,org.eclipse.xtext.ui.codetemplates.ui,org.eclipse.ui.e" + NL + + " ditors;bundle-version=\"3.5.0\",org.eclipse.ui.ide;bundle-version=\"3.5.0\"" + NL + + " ,org.eclipse.ui,org.eclipse.compare,org.eclipse.xtext.builder,org.eclip" + NL + + " se.xtext.xbase.lib;bundle-version=\"2.14.0\",org.eclipse.xtend.lib;bundle" + NL + + " -version=\"2.14.0\";resolution:=optional,org.eclipse.ui.console;bundle-ve" + NL + + " rsion=\"3.8.100\"" + NL + + "Import-Package: org.apache.log4j" + NL + + "Bundle-RequiredExecutionEnvironment: JavaSE-1.8" + NL + + "Export-Package: org.hello.ui.internal,org.hello.ui.contentassist,org.hel" + NL + + " lo.ui.quickfix" + NL + + "Bundle-Activator: org.hello.ui.internal.HelloActivator"+ NL; + String expected = + "Manifest-Version: 1.0" + NL + + "Automatic-Module-Name: org.hello.ui" + NL + + "Bundle-ManifestVersion: 2" + NL + + "Bundle-Name: org.hello.ui" + NL + + "Bundle-Vendor: My Company" + NL + + "Bundle-Version: 1.0.0.qualifier" + NL + + "Bundle-SymbolicName: org.hello.ui; singleton:=true" + NL + + "Bundle-ActivationPolicy: lazy" + NL + + "Require-Bundle: org.hello,org.hello.ide,org.eclipse.xtext.ui,org.eclipse" + NL + + " .xtext.ui.shared,org.eclipse.xtext.ui.codetemplates.ui,org.eclipse.ui.e" + NL + + " ditors;bundle-version=\"3.5.0\",org.eclipse.ui.ide;bundle-version=\"3.5.0\"" + NL + + " ,org.eclipse.ui,org.eclipse.compare,org.eclipse.xtext.builder,org.eclip" + NL + + " se.xtext.xbase.lib;bundle-version=\"2.14.0\",org.eclipse.xtend.lib;bundle" + NL + + " -version=\"2.14.0\";resolution:=optional,org.eclipse.ui.console;bundle-ve" + NL + + " rsion=\"3.8.100\"" + NL + + "Import-Package: org.apache.log4j" + NL + + "Bundle-RequiredExecutionEnvironment: JavaSE-1.8" + NL + + "Export-Package: org.hello.ui.internal,org.hello.ui.contentassist,org.hel" + NL + + " lo.ui.quickfix" + NL + + "Bundle-Activator: org.hello.ui.internal.HelloActivator" + NL; + // @formatter:on + MergeableManifest2 manifest = newManifest(content); + manifest.addExportedPackages(manifest.getMainAttributes().get(MergeableManifest2.EXPORT_PACKAGE).replaceAll("\r\n ", "").split(",")); + manifest.addImportedPackages(manifest.getMainAttributes().get(MergeableManifest2.IMPORT_PACKAGE).replaceAll("\r\n ", "").split(",")); + manifest.addRequiredBundles(manifest.getMainAttributes().get(MergeableManifest2.REQUIRE_BUNDLE).replaceAll("\r\n ", "").split(",")); + manifest.addRequiredBundles("org.eclipse.ui.editors", "org.eclipse.xtext.xbase.lib;bundle-version=\"2.14.0\"", + "org.eclipse.xtext.ui.shared"); + assertEquals(expected, write(manifest)); } diff --git a/org.eclipse.xtext.util/src/org/eclipse/xtext/util/MergeableManifest2.java b/org.eclipse.xtext.util/src/org/eclipse/xtext/util/MergeableManifest2.java index 220a9683e..a6fa4ca9f 100644 --- a/org.eclipse.xtext.util/src/org/eclipse/xtext/util/MergeableManifest2.java +++ b/org.eclipse.xtext.util/src/org/eclipse/xtext/util/MergeableManifest2.java @@ -420,8 +420,6 @@ public class MergeableManifest2 implements Cloneable { } private void writeHeader(BufferedWriter writer) throws IOException { - if (version == null) - return; String manifestVersion = mainAttributes.get(MANIFEST_VERSION); if (manifestVersion != null) writer.append(MANIFEST_VERSION).append(": ").append(manifestVersion).append(newline); @@ -762,19 +760,20 @@ public class MergeableManifest2 implements Cloneable { } public boolean hasSameName(Bundle other) { - // trim because prefix (such as newline) is encoded in the name - return Objects.equals(getName().trim(), other.getName().trim()); + return Objects.equals(getName(), other.getName()); } public String getName() { - // trim because prefix (such as newline) is encoded in the name - return split.get(0).trim(); + // trim because prefix (such as newline) is encoded in the name, + // also remove all newlines to ensure linebreaks in name does not + // cause issues + return split.get(0).trim().replaceAll("\r?\n ", ""); } public String getNameIncludingWhitespacePrefix() { return split.get(0); } - + public String getSuffix() { return split.size() > 1 ? split.subList(1, split.size()).stream().reduce((a, b) -> a + ";" + b).get() : null; @@ -782,13 +781,14 @@ public class MergeableManifest2 implements Cloneable { public String getVersion() { for (int n = 1; n < split.size(); n++) { - String part = split.get(n); + String part = split.get(n).trim().replaceAll("\r?\n ", ""); if (part.contains("bundle-version=")) { int startIndex = part.indexOf("bundle-version=") + "bundle-version=".length(); if (part.charAt(startIndex) == '"') { - return part.substring(startIndex + 1, part.indexOf("\"", startIndex + 1)); + return part.substring(startIndex + 1, part.indexOf("\"", startIndex + 1)).trim() + .replaceAll("\r?\n ", ""); } else { - return part.substring(startIndex); + return part.substring(startIndex).trim().replaceAll("\r?\n ", ""); } } }