/*************************************************************************
*
* $RCSfile: StarJar.java,v $
*
* $Revision: 1.1.1.1 $
*
* last change: $Author: hr $ $Date: 2000/09/18 16:31:42 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://www.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
package com.sun.star.tool.starjar;
import com.sun.star.tool.starjar.regex.MalformedPatternException;
import com.sun.star.tool.starjar.regex.Pattern;
import com.sun.star.tool.starjar.regex.PatternCompiler;
import com.sun.star.tool.starjar.regex.PatternMatcher;
import com.sun.star.tool.starjar.regex.Perl5Compiler;
import com.sun.star.tool.starjar.regex.Perl5Matcher;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.StringBufferInputStream;
import java.io.BufferedReader;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.Hashtable;
import java.util.zip.Adler32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import java.util.zip.ZipException;
class DoubleException extends Exception{
DoubleException(String text) {
super(text);
}
}
class FileList extends Hashtable {
Vector filters;
public FileList(Vector filters) {
this.filters = filters;
}
public void put(FileListElement fileListElement, boolean msg) throws DoubleException {
String ff = fileListElement.getPath() + "-" + fileListElement.getFilename();
Enumeration elements = filters.elements();
while(elements.hasMoreElements()) {
FilterElement filterElement = (FilterElement)elements.nextElement();
if(filterElement.match(fileListElement.getFilename(), fileListElement.getPath()))
fileListElement.setInclude(filterElement.isInclude());
}
// if(msg) System.err.println("FileList.put:" + ff);
if(fileListElement.isInclude()) {
FileListElement oldFileListElement = (FileListElement)get(ff);
if(oldFileListElement != null) {
if((fileListElement.getJarFilename() == null && oldFileListElement.getJarFilename() == null)
|| (fileListElement.getJarFilename() != null &&
fileListElement.getJarFilename().equals(oldFileListElement.getJarFilename())))
{
}
else {
System.err.println("DOUBLE WARNING: " + fileListElement);
// Exception removed, because there are duplicated classes in
// jurt.jar / unoil.jar
// String oldfile = (oldFileListElement.getJarFilename() != null)
// ? (" from " + oldFileListElement.getJarFilename())
// : "";
// String newfile = (fileListElement.getJarFilename() != null)
// ? (" from " + fileListElement.getJarFilename())
// : "";
// throw new DoubleException("DOUBLE FILE ERROR - new:"
// + fileListElement
// + newfile
// + " old:"
// + oldFileListElement
// + oldfile);
}
} else {
super.put(ff, fileListElement);
}
}
}
}
public class StarJar {
protected static Hashtable m_jarFiles = new Hashtable();
protected String m_classPrefix;
protected static ZipFile getJarFile(File file) throws ZipException, java.io.IOException {
ZipFile jarFile = null;
if (m_jarFiles.containsKey(file.getName())) {
jarFile = (ZipFile)m_jarFiles.get(file.getName());
}
else {
jarFile = new ZipFile(file);
m_jarFiles.put(file.getName(), jarFile);
}
return jarFile;
}
protected static ZipFile getJarFile(String name) throws ZipException, java.io.IOException {
return getJarFile(new File(name));
}
public void importFilter(Vector filter, InputStreamReader in) throws
FilterSyntaxException,
IOException,
MalformedPatternException
{
LineNumberReader reader = new LineNumberReader(in);
String line;
while ((line = reader.readLine()) != null) {
StringTokenizer tokenizer = new StringTokenizer(line);
if (tokenizer.countTokens() > 0) {
String token;
token = tokenizer.nextToken();
if ((token.equals("+") || token.equals("-"))) {
if ((tokenizer.countTokens() % 2)!= 0)
throw new FilterSyntaxException("Zeile " + reader.getLineNumber() + ": zu wenig Parameter");
filter.addElement(new FilterElement(token.equals("+"), tokenizer.nextToken(), tokenizer.nextToken()));
}
}
}
reader.close();
}
public void parseDirectoryTree(FileList fileList, File directory, boolean enterJar) throws java.io.IOException, DoubleException {
if(!directory.exists())
System.err.println("File: " + directory.getPath() + File.separator + directory.getName() + " does not exist, ignored!!!");
else if (directory.isFile()
&& (directory.getName().endsWith(".jar") || directory.getName().endsWith(".JAR"))
&& enterJar) {
parseJarFile(fileList, directory);
}
else if (directory.isFile()) {
if (directory.getPath().lastIndexOf(File.separator) != -1) {
String aPath = directory.getPath().substring(0,directory.getPath().lastIndexOf(File.separator));
fileList.put(new FileListElement(this.m_classPrefix, aPath,
directory.getName(),
directory.length(),
true,
null,
null,
null,
false),
false);
}
else {
fileList.put(new FileListElement(this.m_classPrefix,"",
directory.getName(),
directory.length(),
true,
null,
null,
null,
false),
false);
}
}
else if (directory.isDirectory()) {
String[] filenameList = directory.list();
for (int i = 0; i < filenameList.length; i++) {
File file = new File(directory,filenameList[i]);
parseDirectoryTree(fileList, file, false);
}
}
}
public void parseJarFile(FileList fileList, File file) throws ZipException, IOException, DoubleException {
System.err.println("parsingJar:" + file);
ZipFile jarFile = new ZipFile(file);
Enumeration entries = jarFile.entries();
while (entries.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry)entries.nextElement();
String pathName = zipEntry.getName().replace('/', File.separator.charAt(0));
String name = "";
String path = pathName;
int index = pathName.lastIndexOf(File.separator);
if(index > -1) {
name = pathName.substring(index + 1);
path = pathName.substring(0, index);
}
// System.err.println("SFSAF:" + file.getPath() + "#" + index + "#" + File.separator + "#" + name + "#" + path + "#");
fileList.put(new FileListElement(path,
name,
zipEntry.getSize(),
true,
file.getPath() + File.separator + file.getName(),
jarFile,
zipEntry,
true),
true);
}
}
public void addEntry(ZipEntry zipEntry, InputStream in, ZipOutputStream zipFile) throws IOException {
byte[] buffer;
int len;
buffer = new byte[1024];
zipFile.putNextEntry(zipEntry);
if (zipEntry.getMethod() == -1)
while ((len = in.read(buffer)) >= 0)
zipFile.write(buffer, 0, len);
else {
int remaining = (int)zipEntry.getSize();
while (remaining > 0 && (len = in.read(buffer, 0, Math.min(1024,remaining))) != -1) {
zipFile.write(buffer,0,len);
remaining -= len;
}
}
zipFile.flush();
in.close();
}
public void zipFiles(Enumeration liste, String filename, String manifestfilename) throws IOException {
StringBufferInputStream manifestStream;
StringBuffer manifest = new StringBuffer();
FileListElement file;
InputStream in = null;
BufferedOutputStream bufferedOutputStream = null;
ZipOutputStream zipFile = null;
Hashtable hashTags = new Hashtable();
Vector vectorTags=new Vector();
Vector filesForZip = new Vector();
try {
try {
InputStream inManifest = new FileInputStream(manifestfilename);
BufferedReader manifestReader = new BufferedReader(new InputStreamReader(inManifest));
String line;
String tag;
while ((line = manifestReader.readLine()) != null) {
String tags = new String("");
int count = 0;
line.trim();
if (line.startsWith("Name: ", 0)) {
tag = manifestReader.readLine();
while ((tag != null) && (!(tag.trim()).equals(""))) {
if (count++ > 0)
tags += "\n";
tags += tag;
tag = manifestReader.readLine();
}
if (!tags.equals("")) {
hashTags.put(line.substring(6), tags);
}
} else if ( !line.equals("") ) {
tag = manifestReader.readLine();
while ((tag != null) && (!(tag.trim()).equals(""))) {
if (count++ > 0)
tags += "\n";
tags += tag;
tag = manifestReader.readLine();
}
if ( line.startsWith("Manifest-Version:") && (line.indexOf("!MANIFEST_VERSION!")>0) ) {
line=new String("Manifest-Version: 1.0");
}
if (!tags.equals("")) line=line.concat("\n"+tags);
if ( (vectorTags.size()==0 ) && ( !line.startsWith("Manifest-Version:")) ) {
vectorTags.addElement("Manifest-Version: 1.0");
}
vectorTags.addElement(line);
}
}
} catch (Exception e) {
System.out.println("No valid manifest file: "+e);
}
if ( vectorTags.size() == 0 ) {
vectorTags.addElement("Manifest-Version: 1.0\n");
}
Enumeration aEnum=vectorTags.elements();
while ( aEnum.hasMoreElements() ) {
manifest.append((String)aEnum.nextElement());
manifest.append("\n");
}
manifest.append("\n");
bufferedOutputStream = new BufferedOutputStream(new CheckedOutputStream(new FileOutputStream(filename), new Adler32()));
zipFile = new ZipOutputStream(bufferedOutputStream);
while (liste.hasMoreElements()) {
file = (FileListElement)liste.nextElement();
if (file.isInclude()) {
String sPath;
if (!file.isInJarFile()) {
if (!file.getPath().equals(".")) {
if (file.getPath().indexOf(':') != -1)
sPath=(file.getPath().substring(file.getPath().indexOf(File.separator) + 1) + File.separator + file.getFilename()).replace('\\','/');
else {
if(!file.getPath().equals("")) {
sPath = (file.getPath() + File.separator + file.getFilename()).replace('\\','/');
} else {
sPath = (file.getFilename()).replace('\\','/');
}
}
}
else {
sPath = file.getFilename().replace('\\','/');
}
}
else {
sPath=file.getZipFileEntry().getName();
}
if (hashTags.containsKey(sPath) ) {
manifest.append(new String("Name: " + sPath + "\n"));
String tag = (String)hashTags.get(sPath);
if (tag != null)
manifest.append(tag + "\n");
try {
InputStream fis = null;
if (!file.isInJarFile()) {
fis = new FileInputStream(file.getRealPath() + File.separator + file.getFilename());
}
else {
fis = new BufferedInputStream(file.getZipFile().getInputStream(file.getZipFileEntry()));
}
byte[] data = new byte[(int)file.getSize()];
int offset = 0;
while (fis.available() > 0)
offset += fis.read(data, offset, fis.available());
manifest.append(new String("Digest-Algorithms: SHA MD5\n"));
manifest.append(base64Hash("SHA", data)+"\n");
manifest.append(base64Hash("MD5", data)+"\n");
manifest.append("\n");
}
catch (Exception e) {
System.out.println("Exception while creating digest-key: "+e);
}
}
filesForZip.addElement(file);
}
}
ZipEntry zipEntryMF = new ZipEntry("META-INF/MANIFEST.MF");
manifestStream = new StringBufferInputStream(manifest.toString().replace('\\','/'));
zipEntryMF.setSize(manifestStream.available());
zipEntryMF.setCrc(new CRC32().getValue());
addEntry(zipEntryMF, manifestStream, zipFile);
Enumeration filesForZipEnum=filesForZip.elements();
while (filesForZipEnum.hasMoreElements()) {
file = (FileListElement)filesForZipEnum.nextElement();
if (file.isInclude()) {
ZipEntry zipEntry = null;
try {
if (!file.isInJarFile()) {
if (!file.getPath().equals(".")) {
if (file.getPath().indexOf(':') != -1)
zipEntry = new ZipEntry((file.getPath().substring(file.getPath().indexOf(File.separator) + 1) + File.separator + file.getFilename()).replace('\\','/'));
else {
if(!file.getPath().equals("")) {
zipEntry = new ZipEntry((file.getPath() + File.separator + file.getFilename()).replace('\\','/'));
} else {
zipEntry = new ZipEntry((file.getFilename()).replace('\\','/'));
}
}
}
else {
zipEntry = new ZipEntry(file.getFilename().replace('\\','/'));
}
zipEntry.setSize(file.getSize());
zipEntry.setCrc(new CRC32().getValue());
String pathName = "";
if(!file.getRealPath().equals(""))
pathName = file.getRealPath() + File.separator;
pathName += file.getFilename();
System.out.println("Adding " + pathName + " as " + zipEntry.getName() );
in = new BufferedInputStream(new FileInputStream(pathName));
}
else {
System.out.println("Adding from JAR (" + file.getJarFilename() + ") "+ file.getFilename());
zipEntry = new ZipEntry(file.getZipFileEntry().getName());
zipEntry.setSize(file.getSize());
zipEntry.setCrc(new CRC32().getValue());
in = new BufferedInputStream(file.getZipFile().getInputStream(file.getZipFileEntry()));
}
addEntry(zipEntry, in, zipFile);
}
catch (FileNotFoundException e) {
System.out.println("Datei " + file.getPath() + file.getFilename() + " nicht gefunden.");
e.printStackTrace();
return;
}
// catch (IOException e) {
// if (file.isInJarFile())
// System.out.println("error reading archive '" + file.getPath() + File.separator + file.getJarFilename() + "'.");
// e.printStackTrace();
// // return;
// }
}
}
}
finally {
if(zipFile != null)
zipFile.close();
}
// try {
System.out.println("Ok ! -> " + filename);
// }
// catch (IOException e) {
// System.out.println("error closing output file " + filename);
// System.out.println("deleting archive with errors...");
// // e.printStackTrace();
// try {
// bufferedOutputStream.close();
// } catch (IOException ignored) {}
// File delme = new File(filename);
// delme.delete();
// return;
// }
}
/**
* Returns a security hash as a base64 ASCII string.
* @param algorithm Security hash algorithm name.
* @param data The data to be hashed.
* @exception NoSuchAlgorithmException Unimplimented security hash.
*/
static public String base64Hash(String algorithm, byte[] data) {
BASE64Encoder enc = new BASE64Encoder();
try {
java.security.MessageDigest md = java.security.MessageDigest.getInstance(algorithm);
return new String(algorithm+"-Digest: "+enc.encode(md.digest(data)));
}
catch (Exception e) {
System.out.println("Exception in base64Hash: "+e);
return null;
}
}
public static void main(String[] args) {
if (args.length < 5) {
System.out.println("Usage : java stardiv.starjar.StarJar <jarfile> <manifestfile>|- <filterfile> <fileseparator> <files...>");
System.out.println(" Achtung, auch 'Space' muss als FileSeparator angegeben werden!");
return;
}
StarJar starJar = new StarJar();
Vector filter = new Vector();
FileReader fileReader = null;
try {
fileReader = new FileReader(args[2]);
}
catch (FileNotFoundException e) {
System.out.println("error reading filter file:\n" + e);
System.exit(1);
}
try {
starJar.importFilter(filter, fileReader);
FileList fileList = new FileList(filter);
if (args[3].equals(" "))
for (int i = 4; i < args.length; i++)
starJar.parseDirectoryTree(fileList, new File(args[i]), true);
else {
StringTokenizer tokenizer = new StringTokenizer(args[4],args[3]);
while (tokenizer.hasMoreTokens()) {
String tok=tokenizer.nextToken();
starJar.m_classPrefix=tok;
starJar.parseDirectoryTree(fileList, new File(tok), true);
}
}
// starJar.filterFileList(fileList.elements(), filter);
starJar.zipFiles(fileList.elements(), args[0],args[1]);
}
catch (Exception e) {
System.err.println("Exception occurred: " + e);
System.err.print("deleting archive:" + args[0] + " ...");
File loeschen = new File(args[0]);
loeschen.delete();
System.err.println();
System.exit(-1);
}
}
}