[#1038] Filter bad entries when read in MANIFEST.

Filter all entries from "Require-Bundle", "Export-Package" and
"Import-Package" entries that are empty to fix manifest files that are
invalid in this regard.

Signed-off-by: Arne Deutsch <Arne.Deutsch@itemis.de>
This commit is contained in:
Arne Deutsch 2019-02-18 10:50:34 +01:00
parent 3e939fdf9f
commit 415beaeb80
2 changed files with 138 additions and 3 deletions

View file

@ -814,6 +814,15 @@ public class MergeableManifest2Test {
write(manifest));
}
@Test
public void addRequiredBundles_emptyBundlesAreIgnored() throws Exception {
MergeableManifest2 manifest = newManifest("Manifest-Version: 1.0" + NL + "Require-Bundle: a" + NL);
manifest.addRequiredBundles("");
assertFalse(manifest.isModified());
assertEquals("Manifest-Version: 1.0" + NL + "Require-Bundle: a" + NL, write(manifest));
}
@Test
public void addExportedPackages_oneEntry() throws Exception {
MergeableManifest2 manifest = newManifest("Manifest-Version: 1.0" + NL);
@ -859,6 +868,15 @@ public class MergeableManifest2Test {
+ NL + " e" + NL, write(manifest));
}
@Test
public void addExportedPackage_emptyBundlesAreIgnored() throws Exception {
MergeableManifest2 manifest = newManifest("Manifest-Version: 1.0" + NL + "Export-Package: a" + NL);
manifest.addExportedPackages("");
assertFalse(manifest.isModified());
assertEquals("Manifest-Version: 1.0" + NL + "Export-Package: a" + NL, write(manifest));
}
@Test
public void addImportedPackages_oneEntry() throws Exception {
MergeableManifest2 manifest = newManifest("Manifest-Version: 1.0" + NL);
@ -904,6 +922,15 @@ public class MergeableManifest2Test {
+ NL + " e" + NL, write(manifest));
}
@Test
public void addImportedPackage_emptyBundlesAreIgnored() throws Exception {
MergeableManifest2 manifest = newManifest("Manifest-Version: 1.0" + NL + "Import-Package: a" + NL);
manifest.addImportedPackages("");
assertFalse(manifest.isModified());
assertEquals("Manifest-Version: 1.0" + NL + "Import-Package: a" + NL, write(manifest));
}
@Test
public void stableOrderOfMainAttributes_1() throws Exception {
MergeableManifest2 manifest = newManifest("Manifest-Version: 1.0" + NL + "Require-Bundle: a" + NL
@ -1303,6 +1330,85 @@ public class MergeableManifest2Test {
assertEquals(expectedNewContent, write(newManifest));
}
@Test
public void readWrite_emptyBundleEntriesAreFiltered() throws Exception {
// @formatter:off
String content =
"Manifest-Version: 1.0" + NL +
"Bundle-ManifestVersion: 2" + NL +
"Bundle-Name: Xtext Homeautomation Example - Runtime" + NL +
"Bundle-Vendor: Eclipse Xtext" + NL +
"Bundle-Version: 2.16.0.qualifier" + NL +
"Bundle-SymbolicName: org.eclipse.xtext.example.homeautomation; singleton:=true" + NL +
"Bundle-ActivationPolicy: lazy" + NL +
"Require-Bundle: org.eclipse.xtext," + NL +
" org.eclipse.xtext.xbase," + NL +
" org.eclipse.xtext.util," + NL +
" ," + NL +
" org.antlr.runtime;bundle-version=\"[3.2.0,3.2.1)\"," + NL +
" org.eclipse.xtext.common.types," + NL +
" " + NL +
"Bundle-RequiredExecutionEnvironment: JavaSE-1.8" + NL +
"Export-Package: ," + NL +
" org.eclipse.xtext.example.homeautomation.ruleEngine," + NL +
" \t," + NL +
" org.eclipse.xtext.example.homeautomation.ruleEngine.impl," + NL +
" " + NL +
"Import-Package: org.apache.log4j" + NL +
"Automatic-Module-Name: org.eclipse.xtext.example.homeautomation" + NL;
String expected =
"Manifest-Version: 1.0" + NL +
"Bundle-ManifestVersion: 2" + NL +
"Bundle-Name: Xtext Homeautomation Example - Runtime" + NL +
"Bundle-Vendor: Eclipse Xtext" + NL +
"Bundle-Version: 2.16.0.qualifier" + NL +
"Bundle-SymbolicName: org.eclipse.xtext.example.homeautomation; singleton:=true" + NL +
"Bundle-ActivationPolicy: lazy" + NL +
"Require-Bundle: org.eclipse.xtext," + NL +
" org.eclipse.xtext.xbase," + NL +
" org.eclipse.xtext.util," + NL +
" org.antlr.runtime;bundle-version=\"[3.2.0,3.2.1)\"," + NL +
" org.eclipse.xtext.common.types" + NL +
"Bundle-RequiredExecutionEnvironment: JavaSE-1.8" + NL +
"Export-Package: org.eclipse.xtext.example.homeautomation.ruleEngine," + NL +
" org.eclipse.xtext.example.homeautomation.ruleEngine.impl" + NL +
"Import-Package: org.apache.log4j" + NL +
"Automatic-Module-Name: org.eclipse.xtext.example.homeautomation" + NL;
// @formatter:on
MergeableManifest2 manifest = newManifest(content);
assertEquals(expected, write(manifest));
}
@Test
public void readWrite_addRequiredBundle_emptyInOriginal_filteredEvenWhenAddingEmpty() throws Exception {
// @formatter:off
String content =
"Manifest-Version: 1.0" + NL +
"Bundle-ManifestVersion: 2" + NL +
"Require-Bundle: org.eclipse.xtext," + NL +
" org.eclipse.xtext.xbase," + NL +
" org.eclipse.xtext.util," + NL +
" ," + NL +
" org.antlr.runtime;bundle-version=\"[3.2.0,3.2.1)\"," + NL +
" org.eclipse.xtext.common.types," + NL +
" " + NL +
"Automatic-Module-Name: org.eclipse.xtext.example.homeautomation" + NL;
String expected =
"Manifest-Version: 1.0" + NL +
"Bundle-ManifestVersion: 2" + NL +
"Require-Bundle: org.eclipse.xtext," + NL +
" org.eclipse.xtext.xbase," + NL +
" org.eclipse.xtext.util," + NL +
" org.antlr.runtime;bundle-version=\"[3.2.0,3.2.1)\"," + NL +
" org.eclipse.xtext.common.types" + NL +
"Automatic-Module-Name: org.eclipse.xtext.example.homeautomation" + NL;
// @formatter:on
MergeableManifest2 manifest = newManifest(content);
manifest.addRequiredBundles("");
assertEquals(expected, write(manifest));
}
/**
* In this final test we read all "META-INF/MANIFEST.MF" files from
* classpath. We the:

View file

@ -23,6 +23,8 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
@ -56,6 +58,8 @@ public class MergeableManifest2 implements Cloneable {
private Map<String, Attributes> entries = new LinkedHashMap<>();
private boolean modified;
private Pattern emptyEntryPattern = newEmptyLinePattern();
/**
* Create a new manifest from the given stream and with the given name. As
* the stream is created by the caller the caller is also responsible for
@ -70,6 +74,10 @@ public class MergeableManifest2 implements Cloneable {
this.modified = false;
}
private Pattern newEmptyLinePattern() {
return Pattern.compile("," + newline + " [ \t]*," + newline + " ");
}
/**
* Create a new manifest from the given stream. As the stream is created by
* the caller the caller is also responsible for closing it.
@ -90,6 +98,7 @@ public class MergeableManifest2 implements Cloneable {
this.name = toCopy.name;
this.version = toCopy.version;
this.newline = toCopy.newline;
this.emptyEntryPattern = newEmptyLinePattern();
this.mainAttributes.putAll(toCopy.mainAttributes);
this.entries.putAll(toCopy.entries);
this.modified = false;
@ -135,6 +144,12 @@ public class MergeableManifest2 implements Cloneable {
bree = value;
} else if (name.equals(BUNDLE_ACTIVATOR)) {
bundleActivator = value;
} else if (name.equals(REQUIRE_BUNDLE) || name.equals(EXPORT_PACKAGE) || name.equals(IMPORT_PACKAGE)) {
// filter all entries from "Require-Bundle",
// "Export-Package" and "Import-Package" entries
// that are empty to fix manifest files that are invalid in
// this regard
value = filterEmptyBundles(value);
}
mainAttributes.put(name, value);
} else {
@ -142,7 +157,17 @@ public class MergeableManifest2 implements Cloneable {
}
}
return lineIndex;
}
private String filterEmptyBundles(String bundleString) {
String result = bundleString.trim();
if (result.startsWith("," + newline + " "))
result = result.substring(("," + newline + " ").length(), result.length());
Matcher matcher = emptyEntryPattern.matcher(result);
result = matcher.replaceAll("," + newline + " ");
if (result.endsWith(","))
result = result.substring(0, result.length() - 1);
return result;
}
private void readEntries(List<String> lines, int startIndex) throws IOException {
@ -375,6 +400,7 @@ public class MergeableManifest2 implements Cloneable {
*/
public void setLineDelimiter(String lineDelimeter) {
newline = lineDelimeter;
this.emptyEntryPattern = newEmptyLinePattern();
}
/**
@ -655,7 +681,7 @@ public class MergeableManifest2 implements Cloneable {
if (input.isEmpty())
return new BundleList(new ArrayList<>(), newline);
return new BundleList(splitAtCharHonorQuoting(input, ',').stream().map(s -> Bundle.fromInput(s))
.collect(Collectors.toList()), newline);
.filter(b -> !"".equals(b.getName())).collect(Collectors.toList()), newline);
}
public void mergeInto(Bundle newBundle) {
@ -688,8 +714,11 @@ public class MergeableManifest2 implements Cloneable {
}
// in case we add a new bundle and there are already other bundles
// we write it on a new line for better readability
if (!merged)
list.add(Bundle.fromBundleWithNewName(newBundle, newline + " " + newBundle.getName()));
if (!merged) {
if (!"".equals(newBundle.getName())) {
list.add(Bundle.fromBundleWithNewName(newBundle, newline + " " + newBundle.getName()));
}
}
}
// Output is used by algorithm ... do not change for debugging purposes!