blob: fc65834dec8894a7449625a170aa1fe331ba1d85 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 BSI Business Systems Integration AG.
* 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:
* BSI Business Systems Integration AG - initial API and implementation
******************************************************************************/
package org.eclipse.scout.releng.ant.incubation;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipFile;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
import org.omg.CORBA.StringHolder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* <h4>MarkIncubation</h4>
*
* @author aho
* @since 1.1.0 (28.01.2011)
*/
public class MarkIncubation extends Task {
public static final String INCUBATION_APPENDIX = " (Incubation)";
private final ArrayList<FileSet> filesets;
public MarkIncubation() {
this.filesets = new ArrayList<FileSet>();
}
public void addFileset(FileSet set) {
filesets.add(set);
}
@Override
public void execute() throws BuildException {
validate();
for (FileSet fs : filesets) {
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
File inputDir = fs.getDir(getProject());
for (String fileName : ds.getIncludedFiles()) {
File inputFile = new File(inputDir, fileName);
if (inputFile.isFile() && fileName.endsWith("jar")) {
try {
processJarFile(inputFile);
}
catch (Exception e) {
throw new BuildException("could not repack file '" + inputFile + "'.", e);
}
}
}
}
}
protected void processJarFile(File file) throws Exception {
log("mark file '"+file.getName()+"' as incubation.");
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
JarOutputStream out = new JarOutputStream(byteStream);
JarFile jarFile = null;
HashMap<String, ByteArrayOutputStream> newEntries = new HashMap<String, ByteArrayOutputStream>();
try {
jarFile = new JarFile(file);
JarEntry featureXml = jarFile.getJarEntry("feature.xml");
if (featureXml != null) {
StringHolder labelKeyHolder = new StringHolder();
ByteArrayOutputStream featureOutputStream = processFeatureXml(jarFile.getInputStream(featureXml), labelKeyHolder);
if (labelKeyHolder.value != null) {
JarEntry propertyEntry = jarFile.getJarEntry("feature.properties");
if (propertyEntry != null) {
newEntries.put(propertyEntry.getName(), processFeatureProperties(jarFile.getInputStream(propertyEntry), labelKeyHolder.value));
}
}
else {
newEntries.put(featureXml.getName(), featureOutputStream);
}
}
JarEntry manifestEntry = jarFile.getJarEntry("META-INF/MANIFEST.MF");
if (manifestEntry != null) {
StringHolder labelKeyHolder = new StringHolder();
ByteArrayOutputStream manifestOutputStream = processManifest(jarFile.getInputStream(manifestEntry), labelKeyHolder);
if (labelKeyHolder.value != null) {
JarEntry propertyEntry = jarFile.getJarEntry("plugin.properties");
if (propertyEntry != null) {
newEntries.put(propertyEntry.getName(), processPluginProperties(jarFile.getInputStream(propertyEntry), labelKeyHolder.value));
}
}
else {
newEntries.put(manifestEntry.getName(), manifestOutputStream);
}
}
// rewrite jar
if (!newEntries.isEmpty()) {
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
JarEntry newEntry = null;
ByteArrayOutputStream entryStream = null;
if (newEntries.containsKey(entry.getName())) {
entryStream = newEntries.remove(entry.getName());
newEntry = new JarEntry(entry.getName());
newEntry.setTime(entry.getTime());
}
else {
entryStream = processAnyFile(jarFile.getInputStream(entry));
newEntry = new JarEntry(entry);
}
out.putNextEntry(newEntry);
out.write(entryStream.toByteArray());
entryStream.close();
out.closeEntry();
}
out.finish();
out.flush();
}
}
finally {
closeQuiet(out);
closeQuiet(jarFile);
}
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
outputStream.write(byteStream.toByteArray());
}
finally {
if (outputStream != null) {
outputStream.flush();
closeQuiet(outputStream);
}
}
}
private ByteArrayOutputStream processFeatureXml(InputStream fileStream, StringHolder labelKeyHolder) throws Exception {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setExpandEntityReferences(false);
Document doc = factory.newDocumentBuilder().parse(fileStream);
NodeList nodeList = doc.getElementsByTagName("feature");
if (nodeList.getLength() == 1) {
Element originalFeatureElement = (Element) nodeList.item(0);
String label = originalFeatureElement.getAttribute("label");
if (label.startsWith("%")) {
labelKeyHolder.value = label.substring(1);
}
else {
originalFeatureElement.setAttribute("label", label + INCUBATION_APPENDIX);
}
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
DOMSource source = new DOMSource(doc);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
StreamResult result = new StreamResult(outputStream);
transformer.transform(source, result);
return outputStream;
}
finally {
closeQuiet(fileStream);
}
}
private ByteArrayOutputStream processFeatureProperties(InputStream fileStream, String labelKey) throws IOException {
BufferedWriter writer = null;
BufferedReader reader = null;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer = new BufferedWriter(new OutputStreamWriter(out));
reader = new BufferedReader(new InputStreamReader(fileStream));
Pattern pattern = Pattern.compile("^(" + labelKey + "\\=\\s*)(.*)$");
String line = reader.readLine();
while (line != null) {
Matcher m = pattern.matcher(line);
if (m.matches()) {
if (!m.group(2).startsWith("%")) {
line = m.group(1) + m.group(2) + INCUBATION_APPENDIX;
}
}
writer.write(line);
writer.newLine();
line = reader.readLine();
}
writer.flush();
return out;
}
finally {
closeQuiet(reader);
closeQuiet(writer);
}
}
private ByteArrayOutputStream processManifest(InputStream manifest, StringHolder nameKey) throws IOException {
BufferedWriter writer = null;
BufferedReader reader = null;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer = new BufferedWriter(new OutputStreamWriter(out));
reader = new BufferedReader(new InputStreamReader(manifest));
Pattern pattern = Pattern.compile("^(Bundle-Name\\:\\s*)(.*)$");
String line = reader.readLine();
while (line != null) {
Matcher m = pattern.matcher(line);
if (m.matches()) {
if (m.group(2).startsWith("%")) {
nameKey.value = m.group(2).substring(1);
}
else {
line = m.group(1) + m.group(2) + INCUBATION_APPENDIX;
}
}
writer.write(line);
writer.newLine();
line = reader.readLine();
}
writer.flush();
return out;
}
finally {
closeQuiet(reader);
closeQuiet(writer);
}
}
private ByteArrayOutputStream processPluginProperties(InputStream fileStream, String nameKey) throws IOException {
BufferedWriter writer = null;
BufferedReader reader = null;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer = new BufferedWriter(new OutputStreamWriter(out));
reader = new BufferedReader(new InputStreamReader(fileStream));
Pattern pattern = Pattern.compile("^(" + nameKey + "\\=\\s*)(.*)$");
String line = reader.readLine();
while (line != null) {
Matcher m = pattern.matcher(line);
if (m.matches()) {
if (!m.group(2).startsWith("%")) {
line = m.group(1) + m.group(2) + INCUBATION_APPENDIX;
}
}
writer.write(line);
writer.newLine();
line = reader.readLine();
}
writer.flush();
return out;
}
finally {
closeQuiet(reader);
closeQuiet(writer);
}
}
private ByteArrayOutputStream processAnyFile(InputStream inputStream) throws IOException {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int read;
while ((read = inputStream.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
return out;
}
finally {
closeQuiet(inputStream);
}
}
private void validate() throws BuildException {
if (filesets.isEmpty()) {
throw new BuildException("fileset can not be null.");
}
}
private static void closeQuiet(Closeable c) {
if(c == null)return;
try {
c.close();
} catch(Exception e) {}
}
private static void closeQuiet(ZipFile c) {
if(c == null)return;
try {
c.close();
} catch(Exception e) {}
}
}