/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.FileWriter;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.TreeSet;
import org.dom4j.Document;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
/** A utility which goes through a standard dist build and tags every jar
* with the current build version using the jar file version manifest
* headers. The unique jars and their version info and md5 digests are
* output to the jboss.home/jar-versions.xml.
*
* @author Scott.Stark@jboss.org
* @version $Revision: 81000 $
*/
public class VersionRelease
{
static byte[] buffer = new byte[4096];
/** The jboss dist root directory */
File jbossHome;
String specVersion;
String specVendor;
String specTitle;
String implTitle;
String implURL;
String implVersion;
String implVendor;
String implVendorID;
MessageDigest md5;
TreeSet jars = new TreeSet();
public VersionRelease(String homeDir)
throws FileNotFoundException, NoSuchAlgorithmException
{
jbossHome = new File(homeDir);
if( jbossHome.exists() == false )
throw new FileNotFoundException(jbossHome.getAbsolutePath() + " does not exist");
specTitle = System.getProperty("specification.title");
specVersion = System.getProperty("specification.version");
specVendor = System.getProperty("specification.vendor");
implTitle = System.getProperty("implementation.title");
implURL = System.getProperty("implementation.url");
implVersion = System.getProperty("implementation.version");
implVendor = System.getProperty("implementation.vendor");
implVendorID = System.getProperty("implementation.vendor.id");
md5 = MessageDigest.getInstance("MD5");
}
public void run()
{
processDir(jbossHome);
try
{
DocumentFactory df = DocumentFactory.getInstance();
Document doc = df.createDocument();
Element root = doc.addElement("jar-versions");
Iterator iter = jars.iterator();
while( iter.hasNext() )
{
JarInfo info = (JarInfo) iter.next();
info.writeXML(root);
}
File versionsXml = new File(jbossHome, "jar-versions.xml");
FileWriter versionInfo = new FileWriter(versionsXml);
OutputFormat outformat = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(versionInfo, outformat);
writer.setEscapeText(true);
writer.write(doc);
writer.flush();
versionInfo.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
void processDir(File dir)
{
File[] files = dir.listFiles();
for(int f = 0; f < files.length; f ++)
{
File child = files[f];
if( child.isDirectory() == true )
processDir(child);
else
processFile(child);
}
}
void processFile(File file)
{
System.out.println("Checking file: "+file);
// See if this is a jar archive
try
{
JarInfo info = new JarInfo(file, this);
info.write(md5);
jars.add(info);
}
catch(FileNotFoundException e)
{
}
catch(Exception e)
{
e.printStackTrace();
}
}
static class JarInfo implements Comparable
{
File file;
File tmpFile;
Manifest mf;
JarFile jarFile;
String jarName;
boolean sealed;
String md5Digest;
String specVersion;
String specVendor;
String specTitle;
String implTitle;
String implURL;
String implVersion;
String implVendor;
String implVendorID;
JarInfo(File file, VersionRelease release)
throws IOException
{
this.file = file;
this.jarName = file.getName();
this.tmpFile = new File(file.getAbsolutePath()+".tmp");
if( file.renameTo(tmpFile) == false )
throw new IOException("Failed to rename: "+file);
try
{
this.jarFile = new JarFile(tmpFile);
}
catch(IOException e)
{
tmpFile.renameTo(file);
throw new FileNotFoundException("Not a JarFile: "+file);
}
this.mf = jarFile.getManifest();
Attributes mfAttrs = mf.getMainAttributes();
String sealedAttr = mfAttrs.getValue(Attributes.Name.SEALED);
sealed = Boolean.valueOf(sealedAttr).booleanValue();
specVersion = mfAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
if( specVersion == null )
{
specVersion = release.specVersion;
mfAttrs.put(Attributes.Name.SPECIFICATION_VERSION, specVersion);
}
specVendor = mfAttrs.getValue(Attributes.Name.SPECIFICATION_VENDOR);
if( specVendor == null )
{
specVendor = release.specVendor;
mfAttrs.put(Attributes.Name.SPECIFICATION_VENDOR, specVendor);
}
specTitle = mfAttrs.getValue(Attributes.Name.SPECIFICATION_TITLE);
if( specTitle == null )
{
specTitle = release.specTitle;
mfAttrs.put(Attributes.Name.SPECIFICATION_TITLE, specTitle);
}
implTitle = mfAttrs.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
if( implTitle == null )
{
implTitle = release.implTitle;
mfAttrs.put(Attributes.Name.IMPLEMENTATION_TITLE, implTitle);
}
implVersion = mfAttrs.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
if( implVersion == null )
{
implVersion = release.implVersion;
mfAttrs.put(Attributes.Name.IMPLEMENTATION_VERSION, implVersion);
}
implVendor = mfAttrs.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
if( implVendor == null )
{
implVendor = release.implVendor;
mfAttrs.put(Attributes.Name.IMPLEMENTATION_VENDOR, implVendor);
}
implVendorID = mfAttrs.getValue(Attributes.Name.IMPLEMENTATION_VENDOR_ID);
if( implVendorID == null )
{
implVendorID = release.implVendorID;
mfAttrs.put(Attributes.Name.IMPLEMENTATION_VENDOR_ID, implVendorID);
}
implURL = mfAttrs.getValue(Attributes.Name.IMPLEMENTATION_URL);
if( implURL == null )
{
implURL = release.implURL;
mfAttrs.put(Attributes.Name.IMPLEMENTATION_URL, implURL);
}
}
public void write(MessageDigest md5)
throws IOException
{
md5.reset();
if( sealed == true )
{
System.out.println("Skipping sealed jar: "+file);
}
else
{
FileOutputStream fos = new FileOutputStream(file);
JarOutputStream jos = new JarOutputStream(fos, mf);
Enumeration entries = jarFile.entries();
while( entries.hasMoreElements() )
{
JarEntry entry = (JarEntry) entries.nextElement();
String name = entry.getName();
if( name.equals("META-INF/MANIFEST.MF") )
{
continue;
}
JarEntry outEntry = new JarEntry(entry.getName());
outEntry.setTime(entry.getTime());
if( entry.getComment() != null )
outEntry.setComment(entry.getComment());
jos.putNextEntry(outEntry);
InputStream is = jarFile.getInputStream(entry);
int bytes = is.read(buffer);
while( bytes > 0 )
{
jos.write(buffer, 0, bytes);
bytes = is.read(buffer);
}
jos.closeEntry();
}
jarFile.close();
jos.close();
tmpFile.delete();
}
// Calculate the md5sum
FileInputStream fis = new FileInputStream(file);
int bytes = fis.read(buffer);
while( bytes > 0 )
{
md5.update(buffer, 0, bytes);
bytes = fis.read(buffer);
}
fis.close();
byte[] digest = md5.digest();
BigInteger bi = new BigInteger(-1, digest);
bi = bi.abs();
md5Digest = bi.toString(16);
System.out.println(file+", md5: "+md5Digest);
}
public int compareTo(Object o)
{
JarInfo info = (JarInfo) o;
return jarName.compareTo(info.jarName);
}
public boolean equals(Object o)
{
JarInfo info = (JarInfo) o;
return jarName.equals(info.jarName);
}
public int hashCode()
{
return jarName.hashCode();
}
/* Output an xml string element like:
<jar name='twiddle.jar' specVersion='3.2.4'
specVendor='JBoss (http://www.jboss.org/)'
specTitle='JBoss'
implVersion='3.2.4RC2 (build: CVSTag=Branch_3_2 date=200404182118)'
implVendor='JBoss.org'
implTitle='JBoss [WonderLand]'
implVendorID='http://www.jboss.org/'
implURL='http://www.jboss.org/'
sealed='false'
md5Digest='ebf8681b4e600cbe7bb2eff68c537c79' />
*/
public String toString()
{
StringBuffer tmp = new StringBuffer("<jar name='");
tmp.append(jarName);
tmp.append("' specVersion='");
tmp.append(specVersion);
tmp.append("' specVendor='");
tmp.append(specVendor);
tmp.append("' specTitle='");
tmp.append(specTitle);
tmp.append("' implVersion='");
tmp.append(implVersion);
tmp.append("' implVendor='");
tmp.append(implVendor);
tmp.append("' implTitle='");
tmp.append(implTitle);
tmp.append("' implVendorID='");
tmp.append(implVendorID);
tmp.append("' implURL='");
tmp.append(implURL);
tmp.append("' sealed='");
tmp.append(sealed);
tmp.append("' md5Digest='");
tmp.append(md5Digest);
tmp.append("' />");
return tmp.toString();
}
public void writeXML(Element root)
{
Element jar = root.addElement("jar");
jar.addAttribute("name", jarName);
jar.addAttribute("specVersion", specVersion);
jar.addAttribute("specVendor", specVendor);
jar.addAttribute("specTitle", specTitle);
jar.addAttribute("implVersion", implVersion);
jar.addAttribute("implVendor", implVendor);
jar.addAttribute("implTitle", implTitle);
jar.addAttribute("implVendorID", implVendorID);
jar.addAttribute("implURL", implURL);
jar.addAttribute("sealed", ""+sealed);
jar.addAttribute("md5Digest", md5Digest);
}
}
public static void main(String[] args)
throws Exception
{
VersionRelease vr = new VersionRelease(args[0]);
vr.run();
}
}