Bug 484004: Start publishing Eclipse platform artifacts to Maven central
- give EnrichPoms a temporary home
diff --git a/releng/EnrichPoms/.classpath b/releng/EnrichPoms/.classpath
new file mode 100644
index 0000000..fceb480
--- /dev/null
+++ b/releng/EnrichPoms/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/releng/EnrichPoms/.gitignore b/releng/EnrichPoms/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/releng/EnrichPoms/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/releng/EnrichPoms/.project b/releng/EnrichPoms/.project
new file mode 100644
index 0000000..7981491
--- /dev/null
+++ b/releng/EnrichPoms/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>EnrichPoms</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/releng/EnrichPoms/.settings/org.eclipse.jdt.core.prefs b/releng/EnrichPoms/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..3a21537
--- /dev/null
+++ b/releng/EnrichPoms/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/releng/EnrichPoms/CBIaggregator.sh b/releng/EnrichPoms/CBIaggregator.sh
new file mode 100644
index 0000000..712071f
--- /dev/null
+++ b/releng/EnrichPoms/CBIaggregator.sh
@@ -0,0 +1,304 @@
+#!/bin/bash
+#*******************************************************************************
+# Copyright (c) 2016 GK Software 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:
+#     Stephan Herrmann - initial API and implementation
+#********************************************************************************
+
+#================================================================================
+#   Parameters we might want to externalize into a properties file
+#================================================================================
+
+# ECLIPSE:
+DROPS4=/home/data/httpd/archive.eclipse.org/eclipse/downloads/drops4
+FILE_ECLIPSE=${DROPS4}/R-4.6.1-201609071200/eclipse-SDK-4.6.1-linux-gtk-x86_64.tar.gz
+APP_NAME_P2DIRECTOR=org.eclipse.equinox.p2.director
+
+# QUESTION: set tmpdir? (-vmargs not accepted by director application?)
+
+# AGGREGATOR:
+IU_AGG_PRODUCT=org.eclipse.cbi.p2repo.cli.product
+URL_AGG_UPDATES=http://download.eclipse.org/cbi/updates/aggregator/headless/4.6/
+
+FILE_SDK_AGGR=/shared/tools/objectteams/sdk_aggr/SDK4Mvn.aggr
+
+# ENRICH POMS tool:
+ENRICH_POMS_JAR=/shared/tools/objectteams/sdk_aggr/enrichPoms.jar
+
+# LOCAL TOOLS:
+LOCAL_TOOLS=${WORKSPACE}/tools
+DIR_AGGREGATOR=aggregator
+AGGREGATOR=${LOCAL_TOOLS}/${DIR_AGGREGATOR}/cbiAggr
+ECLIPSE=${LOCAL_TOOLS}/eclipse/eclipse
+
+#================================================================================
+# Util functions
+#================================================================================
+function require_executable() {
+	if [ -x ${1} ]
+	then
+		echo "Successfully installed: ${1}"
+	else
+		echo "not executable: ${1}"
+		/bin/ls -l ${1}
+		exit 1
+	fi
+}
+
+#================================================================================
+#   (1) Install and run the CBI aggregator
+#================================================================================
+if [ ! -d ${LOCAL_TOOLS} ]
+then
+	/bin/mkdir ${LOCAL_TOOLS}
+fi
+
+if [ ! -x ${ECLIPSE} ]
+then
+	cd ${LOCAL_TOOLS}
+	tar xf ${FILE_ECLIPSE}
+	cd ${WORKSPACE}
+fi
+require_executable ${ECLIPSE}
+
+if [ ! -x ${AGGREGATOR} ]
+then
+	${ECLIPSE} -application ${APP_NAME_P2DIRECTOR} \
+		-r ${URL_AGG_UPDATES} \
+		-d ${LOCAL_TOOLS}/${DIR_AGGREGATOR} -p CBIProfile \
+		-installIU ${IU_AGG_PRODUCT}
+fi
+require_executable ${AGGREGATOR}
+
+RepoRaw=${WORKSPACE}/reporaw-${BUILD_NUMBER}
+Repo=${WORKSPACE}/repo-${BUILD_NUMBER}
+/bin/mkdir ${RepoRaw}
+
+${AGGREGATOR} aggregate --buildModel ${FILE_SDK_AGGR} --action CLEAN_BUILD --buildRoot ${RepoRaw}
+if [ "$?" != "0" ]
+then
+    echo "FAILURE $?"
+    exit 1
+fi
+/bin/mv ${RepoRaw}/final ${Repo}
+/bin/rm -rf ${RepoRaw}
+
+echo "========== Repo created: =========="
+/usr/bin/du -sc ${Repo}/*
+/usr/bin/du -sc ${Repo}/org/*
+/usr/bin/du -sc ${Repo}/org/eclipse/*
+echo "==================================="
+
+
+#================================================================================
+#   (2) Remove irrelevant stuff
+#================================================================================
+# Removes from the build output of cbiAggregator everything that is not relevant for maven.
+# All removed directories / files will be logged to .logs/removed.txt
+
+echo "==== Remove irrelevant stuff ===="
+
+cd ${Repo}
+
+if [ ! -d .logs ]
+then
+	/bin/mkdir .logs
+elif [ -f .logs/removed.txt ]
+then
+	/bin/rm .logs/removed.txt
+fi
+
+#==== remove the p2 repository (not logged): ====
+
+/bin/rm -r p2.index p2.packed content.jar artifacts.jar
+
+#==== remove -sources artifacts, misplaced due to quirk from https://bugs.eclipse.org/508910: ====
+
+echo "== Misplaced -sources artifacts: ==" | tee >> .logs/removed.txt
+
+# works only outside org/eclipse/{platform,jdt,pde}:
+
+/usr/bin/find -type d -name platform -prune -o -name jdt -prune -o -name pde -prune -o \
+	-name \*-sources.jar\* -print -exec /bin/rm {} \; >> .logs/removed.txt
+
+#==== remove features: ====
+
+echo "== Features: ==" | tee >> .logs/removed.txt
+
+/usr/bin/find * -type d -name \*feature.group -print -exec /bin/rm -rf {} \; -prune >> .logs/removed.txt
+/usr/bin/find * -type d -name \*feature.jar -print -exec /bin/rm -rf {} \; -prune >> .logs/removed.txt
+
+#==== remove eclipse test plug-ins: ====
+
+echo "== Test plugins: ==" | tee >> .logs/removed.txt
+
+ls -d org/eclipse/*/*test* >> .logs/removed.txt
+/bin/rm -r org/eclipse/*/*test*
+
+#==== remove other non-artifacts: ====
+
+echo "== Other non-artifacts: ==" | tee >> .logs/removed.txt
+
+/usr/bin/find tooling -type d >> .logs/removed.txt
+/bin/rm -r tooling*
+
+# ... folders that contain only 1.2.3/foo-1.2.3.pom but no corresponding 1.2.3/foo-1.2.3.jar:
+function hasPomButNoJar() {
+		cd ${1}
+		# expect only one sub-directory, starting with a digit, plus maven-metadata.xml*:
+		other=`ls -d [!0-9]* 2> /dev/null`
+        if `echo "${other}" | egrep "^maven-metadata.xml\s*maven-metadata.xml.md5\s*maven-metadata.xml.sha1$"`
+        then
+        	exit 1
+        fi
+        # scan all *.pom inside the version sub-directory
+        r=1
+        for pom in `ls [0-9]*/*.pom 2> /dev/null`
+        do
+                jar=`echo ${pom} | sed -e "s|\(.*\)\.pom|\1.jar|"`
+                if [ -f ${jar} ]
+                then
+                		# jar found, so keep it
+                        exit 1
+                fi
+                # pom without jar found, let's answer true below
+                r=0
+        done
+        exit $r
+}
+export -f hasPomButNoJar
+
+/usr/bin/find org/eclipse/{jdt,pde,platform} -type d \
+	-exec /bin/bash -c 'hasPomButNoJar "$@"' bash {} \; \
+	-print -exec /bin/rm -rf {} \; -prune >> .logs/removed.txt
+# second "bash" is used as $0 in the function
+
+cd ${WORKSPACE}
+
+echo "========== Repo reduced: =========="
+/usr/bin/du -sc ${Repo}/*
+/usr/bin/du -sc ${Repo}/org/*
+/usr/bin/du -sc ${Repo}/org/eclipse/*
+echo "==================================="
+
+#================================================================================
+#   (2) Garbage Collector
+#================================================================================
+# Removes from the build output of cbiAggregator everything that is not referenced 
+# from any pom below org/eclipse/{platform,jdt,pde}
+#
+# Log output:
+#  .logs/removedGarbage.txt	all directories during garbage collection 
+#  .logs/gc.log 			incoming dependencies of retained artifacts
+#  .logs/empty-dirs.txt		removed empty directories 
+
+echo "==== Garbage Collector ===="
+
+cd ${Repo}
+
+#==== function gc_bundle(): ====
+# Test if pom ${1} is referenced in any other pom.
+# If not, append the containing directory to the file "toremove.txt"
+function gc_bundle {
+        AID=`echo ${1} | sed -e "s|.*/\(.*\)[_-].*|\1|"`
+        DIR=`echo ${1} | sed -e "s|\(.*\)/[0-9].*|\1|"`
+        POM=`basename ${1}`
+
+        ANSWER=`find org/eclipse/{platform,jdt,pde} -name \*.pom \! -name ${POM} \
+        		 -exec /bin/grep -q "<artifactId>${AID}</artifactId>" {} \; -print -quit`
+
+        if [ "$ANSWER" == "" ]
+        then
+                echo "Will remove $DIR"
+                echo $DIR >> toremove.txt
+        else
+                echo "$1 is used by $ANSWER"
+        fi
+}
+export -f gc_bundle
+
+#==== run the garbage collector: ====
+# iterate (max 5 times) in case artifacts were used only from garbage:
+for iteration in 1 2 3 4 5
+do
+	echo "== GC iteration ${iteration} =="
+
+	# look for garbage only outside platform, jdt or pde folders:
+	find -name platform -prune -o -name jdt -prune -o -name pde -prune -o \
+		 -name \*.pom -exec /bin/bash -c 'gc_bundle "$@"' bash {} \; \
+		 > gc-${iteration}.log
+	# second "bash" is used as $0 in the function
+	
+	if [ ! -f toremove.txt ]
+	then
+		# no more garbage found
+		break
+	fi
+	cat toremove.txt >> .logs/removedGarbage.txt
+	for d in `cat toremove.txt`; do /bin/rm -r $d; done	
+	/bin/rm toremove.txt
+done
+
+# merge gc logs:
+cat gc-*.log | sort --unique > .logs/gc.log
+/bin/rm gc-*.log
+
+#==== remove all directories that have become empty: ====
+for iteration in 1 2 3 4 5 ; do find -type d -empty -print \
+ 	-exec /bin/rmdir {} \; -prune; done \
+ 	>> .logs/empty-dirs.txt
+
+echo "========== Repo reduced: =========="
+/usr/bin/du -sc ${Repo}/*
+/usr/bin/du -sc ${Repo}/org/*
+/usr/bin/du -sc ${Repo}/org/eclipse/*
+echo "==================================="
+
+cd ${WORKSPACE}
+
+#================================================================================
+#   (3) Enrich POMs
+#================================================================================
+# Add some required information to the generated poms:
+# - dynamic content (retrieved mostly from MANIFEST.MF):
+#   - name
+#   - url
+#   - scm connection and tag
+# - static content
+#   - license
+#   - organization
+#   - issue management
+
+
+echo "==== Enrich POMs ===="
+
+cd ${Repo}
+
+echo "platform"
+java -jar ${ENRICH_POMS_JAR} `pwd`/org/eclipse/platform &> .logs/enrich-platform.txt
+echo "jdt"
+java -jar ${ENRICH_POMS_JAR} `pwd`/org/eclipse/jdt &> .logs/enrich-jdt.txt
+echo "pde"
+java -jar ${ENRICH_POMS_JAR} `pwd`/org/eclipse/pde &> .logs/enrich-pde.txt
+
+echo "== updated checksums =="
+
+function updateCheckSums() {
+        /usr/bin/md5sum ${1} | cut -d " " -f 1 > ${1}.md5
+        /usr/bin/sha1sum ${1} | cut -d " " -f 1 > ${1}.sha1
+}
+
+for pom in org/eclipse/{platform,jdt,pde}/*/*/*.pom
+do
+        updateCheckSums ${pom}
+done
+
+
+echo "========== Repo completed ========="
+
+cd ${WORKSPACE}
diff --git a/releng/EnrichPoms/enrichPoms.jardesc b/releng/EnrichPoms/enrichPoms.jardesc
new file mode 100644
index 0000000..c44980f
--- /dev/null
+++ b/releng/EnrichPoms/enrichPoms.jardesc
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<jardesc>
+    <jar path="CollectPomInfo/enrichPoms.jar"/>
+    <options buildIfNeeded="true" compress="true" descriptionLocation="/CollectPomInfo/enrichPomFiles.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
+    <storedRefactorings deprecationInfo="true" structuralOnly="false"/>
+    <selectedProjects/>
+    <manifest generateManifest="true" mainClassHandleIdentifier="=CollectPomInfo/src&lt;org.eclipse.cbi.p2repo.aggregator.maven.pom{EnrichPoms.java[EnrichPoms" manifestLocation="" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true">
+        <sealing sealJar="false">
+            <packagesToSeal/>
+            <packagesToUnSeal/>
+        </sealing>
+    </manifest>
+    <selectedElements exportClassFiles="true" exportJavaFiles="false" exportOutputFolder="false">
+        <javaElement handleIdentifier="=CollectPomInfo/src"/>
+    </selectedElements>
+</jardesc>
diff --git a/releng/EnrichPoms/src/org/eclipse/cbi/p2repo/aggregator/maven/pom/ArtifactInfo.java b/releng/EnrichPoms/src/org/eclipse/cbi/p2repo/aggregator/maven/pom/ArtifactInfo.java
new file mode 100644
index 0000000..0e8ff63
--- /dev/null
+++ b/releng/EnrichPoms/src/org/eclipse/cbi/p2repo/aggregator/maven/pom/ArtifactInfo.java
@@ -0,0 +1,147 @@
+/********************************************************************************
+ * Copyright (c) 2016 GK Software 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:
+ *     Stephan Herrmann - initial implementation
+ ********************************************************************************/
+package org.eclipse.cbi.p2repo.aggregator.maven.pom;
+
+public class ArtifactInfo {
+
+	private static final String SCM_TAG_START = ";tag=\""; // git tag inside Eclipse-SourceReference
+
+	private static final String INDENT = "  ";
+	
+	private static final String FRONT_MATTER =
+			"  <licenses>\n" + 
+			"    <license>\n" + 
+			"      <name>Eclipse Public License</name>\n" + 
+			"      <url>http://www.eclipse.org/legal/epl-v10.html</url>\n" + 
+			"      <distribution>repo</distribution>\n" + 
+			"    </license>\n" + 
+			"  </licenses>\n" + 
+			"  <organization>\n" + 
+			"    <name>Eclipse Foundation</name>\n" + 
+			"    <url>http://www.eclipse.org/</url>\n" + 
+			"  </organization>\n" + 
+			"  <issueManagement>\n" + 
+			"    <system>Bugzilla</system>\n" + 
+			"    <url>https://bugs.eclipse.org/</url>\n" + 
+			"  </issueManagement>\n";
+	
+	public static final String COPYRIGHT =
+			"<!--\n" +
+			"  Copyright (c) 2016 GK Software AG and others.\n" + 
+			"  All rights reserved. This program and the accompanying materials\n" + 
+			"  are made available under the terms of the Eclipse Public License v1.0\n" + 
+			"  which accompanies this distribution, and is available at\n" + 
+			"  http://www.eclipse.org/legal/epl-v10.html\n" + 
+			"\n" + 
+			"  Contributors:\n" + 
+			"      Stephan Herrmann - initial implementation\n" + 
+			"-->\n";
+
+	public String bsn;
+	public String name;
+	public String scmUrl;
+	
+	@Override
+	public String toString() {
+		return "ArtifactInfo [bsn=" + bsn + ", name=" + name + ", scmUrl=" + scmUrl + "]";
+	}
+
+	public String toPomFragment() {
+		try {
+			fixData();
+			StringBuilder buf = new StringBuilder();
+			String indent = INDENT;
+			element("name", indent, buf, this.name);
+			element("url", indent, buf, "http://www.eclipse.org/"+getProject());
+			buf.append(FRONT_MATTER);
+			if (this.scmUrl == null) {
+				System.err.println("No scm info for "+this.bsn);
+			} else {
+				element("scm", indent, buf,
+					subElement("connection", extractScmUrl()),
+					subElement("tag", extractScmTag()));
+			}
+			return buf.toString();
+		} catch (RuntimeException e) {
+			System.err.println("Failed for "+this);
+			throw e;
+		}
+	}
+	
+	private void fixData() {
+		if (this.scmUrl == null) {
+			if (this.bsn.startsWith("org.eclipse.emf")) {
+				this.scmUrl = "scm:git:https://git.eclipse.org/r/emf/org.eclipse.emf";
+				System.out.println("Fixed scmUrl for "+this.bsn);
+			} else if (this.bsn.startsWith("org.eclipse.ecf")) {
+				this.scmUrl = "scm:git:https://git.eclipse.org/r/ecf/org.eclipse.ecf;tag=\"R-Release_HEAD-sdk_feature-279_279\"";
+				System.out.println("Fixed scmUrl for "+this.bsn);
+			}
+		}
+		if (this.name == null || this.name.charAt(0) == '%') {
+			if (this.bsn.equals("org.eclipse.core.resources.win32.x86")
+					|| this.bsn.equals("org.eclipse.core.resources.win32.x86_64")) {
+				this.name = "Core Resource Management Win32 Fragment";
+				System.out.println("Fixed name for "+this.bsn);
+			}
+		}
+	}
+
+	String getProject() {
+		if (this.bsn.startsWith("org.eclipse.jdt"))
+			return "jdt";
+		if (this.bsn.startsWith("org.eclipse.pde"))
+			return "pde";
+		if (this.bsn.startsWith("org.eclipse.ecf"))
+			return "ecf";
+		return "platform";
+	}
+	
+	String extractScmUrl() {
+		int semi = this.scmUrl.indexOf(';');
+		if (semi == -1)
+			return this.scmUrl;
+		return this.scmUrl.substring(0, semi);
+	}
+	
+	String extractScmTag() {
+		int tagStart = this.scmUrl.indexOf(SCM_TAG_START);
+		if (tagStart == -1)
+			return null;
+		int next = this.scmUrl.indexOf("\"", tagStart+SCM_TAG_START.length());
+		if (next == -1)
+			next = this.scmUrl.length();
+		return this.scmUrl.substring(tagStart+SCM_TAG_START.length(), next);
+	}
+
+	void element(String tag, String indent, StringBuilder buf, String... contents) {
+		buf.append(indent).append('<').append(tag).append('>');
+		if (contents.length == 1 && !contents[0].contains("\n")) {
+			buf.append(contents[0]);
+		} else {
+			buf.append("\n");
+			for (String content : contents)
+				if (content != null)
+					for (String line: content.split("\\n")) 
+						buf.append(indent).append(INDENT).append(line).append('\n');
+			buf.append(indent);
+		}
+		buf.append("</").append(tag).append(">\n");
+	}
+
+	String subElement(String tag, String content) {
+		if (content == null)
+			return null;
+		StringBuilder buf = new StringBuilder();
+		element(tag, "", buf, content);
+		return buf.toString();
+	}
+}
diff --git a/releng/EnrichPoms/src/org/eclipse/cbi/p2repo/aggregator/maven/pom/EnrichPoms.java b/releng/EnrichPoms/src/org/eclipse/cbi/p2repo/aggregator/maven/pom/EnrichPoms.java
new file mode 100644
index 0000000..fe83293
--- /dev/null
+++ b/releng/EnrichPoms/src/org/eclipse/cbi/p2repo/aggregator/maven/pom/EnrichPoms.java
@@ -0,0 +1,88 @@
+/********************************************************************************
+ * Copyright (c) 2016 GK Software 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:
+ *     Stephan Herrmann - initial implementation
+ ********************************************************************************/
+package org.eclipse.cbi.p2repo.aggregator.maven.pom;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class EnrichPoms {
+
+	private static final String DOT_POM = ".pom";
+	private static final String DOT_JAR = ".jar";
+	private static final String BAK_SUFFIX = "-bak";
+
+
+	public static void main(String[] args) throws IOException {
+		Path path = FileSystems.getDefault().getPath(args[0]);
+		if (!Files.exists(path) || !Files.isDirectory(path))
+			throw new IllegalArgumentException(path.toString()+ " is not a directory");
+		
+		Files.walk(path)
+			.filter(EnrichPoms::isArtifact)
+			.forEach(EnrichPoms::enrich);
+	}
+	
+	public static boolean isArtifact(Path path) {
+		if (Files.isDirectory(path))
+			return false;
+		if (!path.getFileName().toString().endsWith(DOT_POM))
+			return false;
+		Path jarPath = getCorrespondingJarPath(path);
+		return Files.exists(jarPath);
+	}
+
+	public static Path getCorrespondingJarPath(Path pomPath) {
+		String fileName = pomPath.getFileName().toString();
+		String jarName = fileName.substring(0, fileName.length()-DOT_POM.length())+DOT_JAR; 
+		return pomPath.resolveSibling(jarName);
+	}
+
+	public static void enrich(Path pomPath) {
+		try {
+			Path backPath = pomPath.resolveSibling(pomPath.getFileName().toString()+BAK_SUFFIX);
+			if (Files.exists(backPath)) {
+				System.out.println("Skipping (-bak exists): "+pomPath);
+				return;
+			}
+			Path jarPath = getCorrespondingJarPath(pomPath);
+			ArtifactInfo info = ManifestReader.read(jarPath);
+			Path newPom = Files.createTempFile(pomPath.getParent(), "", DOT_POM);
+			try (OutputStreamWriter out = new OutputStreamWriter(Files.newOutputStream(newPom))) {
+				boolean copyrightInserted = false;
+				boolean detailsInserted = false;
+				for (String line : Files.readAllLines(pomPath)) {
+					out.write(line);
+					out.append('\n');
+					if (!copyrightInserted) {
+						if (line.equals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")) {
+							out.append(ArtifactInfo.COPYRIGHT);
+							copyrightInserted = true;
+						}
+					}
+					if (!detailsInserted) {
+						if (line.contains("</description>")) {
+							out.append(info.toPomFragment());
+							detailsInserted = true;
+						}
+					}
+				}
+			}
+			if (!Files.exists(backPath))
+				Files.move(pomPath, backPath);
+			Files.move(newPom, pomPath);
+		} catch (IOException e) {
+			System.err.println("Failed to rewrite pom "+pomPath+": "+e.getClass()+": "+e.getMessage());
+		}
+	}
+}
diff --git a/releng/EnrichPoms/src/org/eclipse/cbi/p2repo/aggregator/maven/pom/ManifestReader.java b/releng/EnrichPoms/src/org/eclipse/cbi/p2repo/aggregator/maven/pom/ManifestReader.java
new file mode 100644
index 0000000..58f991d
--- /dev/null
+++ b/releng/EnrichPoms/src/org/eclipse/cbi/p2repo/aggregator/maven/pom/ManifestReader.java
@@ -0,0 +1,116 @@
+/********************************************************************************
+ * Copyright (c) 2016 GK Software 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:
+ *     Stephan Herrmann - initial implementation
+ ********************************************************************************/
+package org.eclipse.cbi.p2repo.aggregator.maven.pom;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+
+public class ManifestReader {
+
+	// Eclipse headers in MANIFEST.MF:
+	private static final String BUNDLE_SYMBOLIC_NAME 		= "Bundle-SymbolicName";
+	private static final String BUNDLE_NAME 				= "Bundle-Name";
+	private static final String BUNDLE_LOCALIZATION 		= "Bundle-Localization";
+	private static final String ECLIPSE_SOURCE_REFERENCES 	= "Eclipse-SourceReferences";
+	private static final String FRAGMENT_HOST 				= "Fragment-Host";
+	
+	private static final String DOT_PROPERTIES 				= ".properties";
+	private static final String BUNDLE_PROPERTIES 			= "OSGI-INF/l10n/bundle.properties";
+
+	public static ArtifactInfo read(Path path) throws FileNotFoundException, IOException {
+		File file = path.toFile();
+		try (JarInputStream jInput = new JarInputStream(new FileInputStream(file))) {
+			Manifest mf = jInput.getManifest();
+			Attributes mainAttributes = mf.getMainAttributes();
+//			printAllMainAttributes(mainAttributes);
+
+			String localization = mainAttributes.getValue(BUNDLE_LOCALIZATION);
+			boolean isFragment = mainAttributes.getValue(FRAGMENT_HOST) != null;
+			Properties translations = getTranslations(file, localization, isFragment);
+
+			ArtifactInfo info = new ArtifactInfo();
+			info.bsn = getSymbolicName(mainAttributes);
+			info.scmUrl = mainAttributes.getValue(ECLIPSE_SOURCE_REFERENCES);
+			info.name = getBundleName(mainAttributes, translations, isFragment);
+			return info;
+		}
+	}
+
+	public static String getSymbolicName(Attributes mainAttributes) {
+		String bsn = mainAttributes.getValue(BUNDLE_SYMBOLIC_NAME);
+		int semi = bsn.indexOf(';');
+		if (semi != -1)
+			return bsn.substring(0, semi); // cut off ;singleton etc...
+		return bsn;
+	}
+
+	static Properties getTranslations(File jarFile, String propFile, boolean isFragment) throws IOException {
+		try (JarFile jf = new JarFile(jarFile)) {
+			ZipEntry zipEntry = getTranslationsEntry(jf, propFile);
+			if (zipEntry == null) {
+				if (!isFragment) { // expected for fragments :-/
+					if (propFile != null)
+						System.err.println("translations "+propFile+DOT_PROPERTIES+" missing for "+jarFile.getName());
+					else
+						System.err.println("translations "+BUNDLE_PROPERTIES+" missing for "+jarFile.getName());
+				}
+				return null;
+			}
+			Properties properties = new Properties();
+			properties.load(jf.getInputStream(zipEntry));
+			return properties;
+		}
+	}
+	
+	static ZipEntry getTranslationsEntry(JarFile jf, String propFile) {
+		ZipEntry entry = null;
+		if (propFile != null)
+			entry = jf.getEntry(propFile+DOT_PROPERTIES);
+		if (entry == null)
+			entry = jf.getEntry(BUNDLE_PROPERTIES);
+		return entry;
+	}
+
+	static String getBundleName(Attributes mainAttributes, Properties translations, boolean isFragment) {
+		String name = mainAttributes.getValue(BUNDLE_NAME);
+		if (name.charAt(0) == '%') {
+			if (translations == null) {
+				if (isFragment) { // TODO
+					System.err.println("Cannot translate fragment name "+name+" for "+getSymbolicName(mainAttributes));
+				} else {
+					System.err.println("Cannot translate bundle name "+name+" for "+getSymbolicName(mainAttributes));
+				}
+				return name;
+			}
+			String translated = translations.getProperty(name.substring(1));
+			if (translated != null)
+				return translated;
+		}
+		return name;
+	}
+
+	// debugging
+	static void printAllMainAttributes(Attributes mainAttributes) {
+		for (Entry<Object, Object> entry : mainAttributes.entrySet()) {
+			System.out.println(entry.getKey()+" -> "+entry.getValue());
+		}
+	}
+}