Skip to content
This repository has been archived by the owner on Apr 6, 2022. It is now read-only.

Commit

Permalink
[FIXED JENKINS-10681] Added support for localized MANIFEST files.
Browse files Browse the repository at this point in the history
  • Loading branch information
uhafner committed Aug 29, 2011
1 parent 9a77f97 commit 5704f55
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 15 deletions.
71 changes: 59 additions & 12 deletions src/main/java/hudson/plugins/analysis/util/ModuleDetector.java
Expand Up @@ -10,6 +10,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

Expand All @@ -26,17 +27,23 @@
* @author Christoph Läubrich (support for OSGi-Bundles)
*/
public class ModuleDetector {
private static final String PLUS = ", ";
private static final String BACK_SLASH = "\\";
private static final String SLASH = "/";
private static final String ALL_DIRECTORIES = "**/";

private static final String BUNDLE_VENDOR = "Bundle-Vendor";
private static final String BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";
private static final String BUNDLE_NAME = "Bundle-Name";
private static final String REPLACEMENT_CHAR = "%";

static final String MAVEN_POM = "pom.xml";
static final String ANT_PROJECT = "build.xml";
static final String OSGI_BUNDLE = "META-INF/MANIFEST.MF";

private static final String PATTERN = ALL_DIRECTORIES + MAVEN_POM
+ ", " + ALL_DIRECTORIES + ANT_PROJECT
+ ", " + ALL_DIRECTORIES + OSGI_BUNDLE;
+ PLUS + ALL_DIRECTORIES + ANT_PROJECT
+ PLUS + ALL_DIRECTORIES + OSGI_BUNDLE;

/** The factory to create input streams with. */
private FileInputStreamFactory factory = new DefaultFileInputStreamFactory();
Expand Down Expand Up @@ -224,7 +231,7 @@ private String parsePom(final String pom) {
}

/**
* Scans a Manifest file for OSGi Bundle Information
* Scans a Manifest file for OSGi Bundle Information.
*
* @param manifestFile
* file name of MANIFEST.MF
Expand All @@ -237,16 +244,12 @@ private String parseManifest(final String manifestFile) {
file = factory.create(manifestFile);
Manifest manifest = new Manifest(file);
Attributes attributes = manifest.getMainAttributes();
String symbolicName = attributes.getValue("Bundle-SymbolicName");
if (StringUtils.isNotBlank(symbolicName)) {
String vendor = attributes.getValue("Bundle-Vendor");
if (StringUtils.isNotBlank(vendor)) {
return symbolicName + " (" + vendor + ")";
}
else {
return symbolicName;
}
Properties properties = readProperties(StringUtils.substringBefore(manifestFile, OSGI_BUNDLE));
String name = getLocalizedValue(attributes, properties, BUNDLE_NAME);
if (StringUtils.isNotBlank(name)) {
return name;
}
return getSymbolicName(attributes, properties);
}
catch (IOException exception) {
// ignore
Expand All @@ -257,6 +260,50 @@ private String parseManifest(final String manifestFile) {
return StringUtils.EMPTY;
}

private String getLocalizedValue(final Attributes attributes, final Properties properties, final String bundleName) {
String value = attributes.getValue(bundleName);
if (StringUtils.startsWith(StringUtils.trim(value), REPLACEMENT_CHAR)) {
return properties.getProperty(StringUtils.substringAfter(value, REPLACEMENT_CHAR));
}
return value;
}

private Properties readProperties(final String path) {
Properties properties = new Properties();
readProperties(path, properties, "plugin.properties");
readProperties(path, properties, "OSGI-INF/l10n/bundle.properties");

return properties;
}

private void readProperties(final String path, final Properties properties, final String fileName) {
InputStream file = null;
try {
file = factory.create(path + SLASH + fileName);
properties.load(file);
}
catch (IOException exception) {
// ignore if properties are not present or not readable
}
finally {
IOUtils.closeQuietly(file);
}
}

private String getSymbolicName(final Attributes attributes, final Properties properties) {
String symbolicName = StringUtils.substringBefore(attributes.getValue(BUNDLE_SYMBOLIC_NAME), ";");
if (StringUtils.isNotBlank(symbolicName)) {
String vendor = getLocalizedValue(attributes, properties, BUNDLE_VENDOR);
if (StringUtils.isNotBlank(vendor)) {
return symbolicName + " (" + vendor + ")";
}
else {
return symbolicName;
}
}
return StringUtils.EMPTY;
}

/**
* An input stream factory based on a {@link FileInputStream}.
*/
Expand Down
59 changes: 56 additions & 3 deletions src/test/java/hudson/plugins/analysis/util/ModuleDetectorTest.java
Expand Up @@ -18,13 +18,13 @@
*/
@SuppressWarnings("DMI")
public class ModuleDetectorTest {
private static final String MANIFEST = "MANIFEST.MF";
private static final String MANIFEST_NAME = "MANIFEST-NAME.MF";
private static final File ROOT = new File("/tmp");
/**
* FIXME: Document field PREFIX
*/
private static final String PREFIX = ROOT.getAbsolutePath() + "/";
private static final int NO_RESULT = 0;
private static final String PATH_PREFIX_MAVEN = "path/to/maven";
private static final String PATH_PREFIX_OSGI = "path/to/osgi";
private static final String PATH_PREFIX_ANT = "path/to/ant";
private static final String EXPECTED_MAVEN_MODULE = "ADT Business Logic";
private static final String EXPECTED_ANT_MODULE = "checkstyle";
Expand All @@ -50,6 +50,59 @@ private InputStream read(final String fileName) {
return ModuleDetectorTest.class.getResourceAsStream(fileName);
}

/**
* Checks whether we could identify OSGi modules using the module mapping.
*
* @throws FileNotFoundException
* should never happen
*/
@Test
public void testOsgiModules() throws FileNotFoundException {
ModuleDetector detector = createDetectorUnderTest(MANIFEST,
new String[] {PATH_PREFIX_OSGI + ModuleDetector.OSGI_BUNDLE});

String expectedName = "de.faktorlogik.prototyp";
verifyModuleName(detector, expectedName, PATH_PREFIX_OSGI + "/something.txt");
verifyModuleName(detector, expectedName, PATH_PREFIX_OSGI + "/in/between/something.txt");
verifyModuleName(detector, StringUtils.EMPTY, "/path/to/something.txt");
}

/**
* Checks whether we could identify OSGi modules using the module mapping.
*
* @throws FileNotFoundException
* should never happen
*/
@Test
public void testOsgiModulesWithVendor() throws FileNotFoundException {
FileInputStreamFactory factory = createFactoryMock(MANIFEST, new String[] {PATH_PREFIX_OSGI + ModuleDetector.OSGI_BUNDLE});
when(factory.create(anyString())).thenReturn(read(MANIFEST)).thenReturn(read("l10n.properties"));
ModuleDetector detector = createDetectorUnderTest(factory);

String expectedName = "de.faktorlogik.prototyp (My Vendor)";
verifyModuleName(detector, expectedName, PATH_PREFIX_OSGI + "/something.txt");
verifyModuleName(detector, expectedName, PATH_PREFIX_OSGI + "/in/between/something.txt");
verifyModuleName(detector, StringUtils.EMPTY, "/path/to/something.txt");
}

/**
* Checks whether we could identify OSGi modules using the module mapping.
*
* @throws FileNotFoundException
* should never happen
*/
@Test
public void testOsgiModulesWithName() throws FileNotFoundException {
FileInputStreamFactory factory = createFactoryMock(MANIFEST_NAME, new String[] {PATH_PREFIX_OSGI + ModuleDetector.OSGI_BUNDLE});
when(factory.create(anyString())).thenReturn(read(MANIFEST_NAME)).thenReturn(read("l10n.properties"));
ModuleDetector detector = createDetectorUnderTest(factory);

String expectedName = "My Bundle";
verifyModuleName(detector, expectedName, PATH_PREFIX_OSGI + "/something.txt");
verifyModuleName(detector, expectedName, PATH_PREFIX_OSGI + "/in/between/something.txt");
verifyModuleName(detector, StringUtils.EMPTY, "/path/to/something.txt");
}

/**
* Checks whether we could identify Maven modules using the module mapping.
*
Expand Down
40 changes: 40 additions & 0 deletions src/test/resources/hudson/plugins/analysis/util/MANIFEST-NAME.MF
@@ -0,0 +1,40 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: de.faktorlogik.prototyp; singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: de.faktorlogik.prototyp.internal.Activator
Bundle-Vendor: %Bundle-Vendor
Require-Bundle: org.eclipse.ui;bundle-version="3.6.0",
org.eclipse.core.runtime;bundle-version="3.6.0",
org.eclipse.core.databinding;bundle-version="1.3.100",
org.eclipse.core.databinding.beans;bundle-version="1.2.100",
org.eclipse.core.databinding.observable;bundle-version="1.3.0",
org.eclipse.core.databinding.property;bundle-version="1.3.0",
org.eclipse.jface.databinding;bundle-version="1.4.0",
org.eclipse.zest.core;bundle-version="1.1.0",
org.eclipse.zest.layouts;bundle-version="1.1.0",
com.ibm.icu;bundle-version="4.2.1",
com.google.guava;bundle-version="1.0.0",
findbugs.annotations;bundle-version="1.3.9",
findbugs.jsr305;bundle-version="1.3.9",
net.ffxml.swtforms;bundle-version="0.9.1",
commons-io;bundle-version="1.4.0",
commons-lang;bundle-version="2.4.0",
owlapiv3;bundle-version="2.2.2",
aterm;bundle-version="2.2.2",
xsdlib;bundle-version="2.2.2",
relaxngDatatype;bundle-version="2.2.2",
jgrapht;bundle-version="2.2.2",
pellet-core;bundle-version="2.2.2",
pellet-datatypes;bundle-version="2.2.2",
pellet-el;bundle-version="2.2.2",
pellet-modularity;bundle-version="2.2.2",
pellet-owlapiv3;bundle-version="2.2.2",
pellet-query;bundle-version="2.2.2",
pellet-rules;bundle-version="2.2.2",
de.faktorlogik.util;bundle-version="1.0.0",
de.faktorlogik.eclipse.ui;bundle-version="1.0.0",
de.faktorlogik.core;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
39 changes: 39 additions & 0 deletions src/test/resources/hudson/plugins/analysis/util/MANIFEST.MF
@@ -0,0 +1,39 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: de.faktorlogik.prototyp; singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: de.faktorlogik.prototyp.internal.Activator
Bundle-Vendor: %Bundle-Vendor
Require-Bundle: org.eclipse.ui;bundle-version="3.6.0",
org.eclipse.core.runtime;bundle-version="3.6.0",
org.eclipse.core.databinding;bundle-version="1.3.100",
org.eclipse.core.databinding.beans;bundle-version="1.2.100",
org.eclipse.core.databinding.observable;bundle-version="1.3.0",
org.eclipse.core.databinding.property;bundle-version="1.3.0",
org.eclipse.jface.databinding;bundle-version="1.4.0",
org.eclipse.zest.core;bundle-version="1.1.0",
org.eclipse.zest.layouts;bundle-version="1.1.0",
com.ibm.icu;bundle-version="4.2.1",
com.google.guava;bundle-version="1.0.0",
findbugs.annotations;bundle-version="1.3.9",
findbugs.jsr305;bundle-version="1.3.9",
net.ffxml.swtforms;bundle-version="0.9.1",
commons-io;bundle-version="1.4.0",
commons-lang;bundle-version="2.4.0",
owlapiv3;bundle-version="2.2.2",
aterm;bundle-version="2.2.2",
xsdlib;bundle-version="2.2.2",
relaxngDatatype;bundle-version="2.2.2",
jgrapht;bundle-version="2.2.2",
pellet-core;bundle-version="2.2.2",
pellet-datatypes;bundle-version="2.2.2",
pellet-el;bundle-version="2.2.2",
pellet-modularity;bundle-version="2.2.2",
pellet-owlapiv3;bundle-version="2.2.2",
pellet-query;bundle-version="2.2.2",
pellet-rules;bundle-version="2.2.2",
de.faktorlogik.util;bundle-version="1.0.0",
de.faktorlogik.eclipse.ui;bundle-version="1.0.0",
de.faktorlogik.core;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
@@ -0,0 +1,2 @@
Bundle-Name=My Bundle
Bundle-Vendor=My Vendor

0 comments on commit 5704f55

Please sign in to comment.