blob: 0f4ebbff48a57870901db02625e5689aa21f060b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2007 IBM Corporation 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:
* IBM - Initial API and implementation
*******************************************************************************/
package org.eclipse.update.internal.jarprocessor;
import java.io.*;
import java.util.*;
import java.util.jar.*;
import java.util.zip.ZipException;
/**
* @author aniefer@ca.ibm.com
*
*/
public class Utils {
public static final String MARK_FILE_NAME = "META-INF/eclipse.inf"; //$NON-NLS-1$
/*
* Properties found in outer pack.properties file
*/
//comma separated list of jars to exclude from sigining
public static final String SIGN_EXCLUDES = "sign.excludes"; //$NON-NLS-1$
//comma separated list of jars to exlclude from packing
public static final String PACK_EXCLUDES = "pack.excludes"; //$NON-NLS-1$
//Suffix used when specifying arguments to use when running pack200 on a jar
public static final String PACK_ARGS_SUFFIX = ".pack.args"; //$NON-NLS-1$
/*
* Properties found in both pack.properties and eclipse.inf
*/
// Default arguments to use when running pack200.
// Affects all jars when specified in pack.properties, affects children when specified in eclipse.inf
public static final String DEFAULT_PACK_ARGS = "pack200.default.args"; //$NON-NLS-1$
/*
* Properties found in eclipse.inf file
*/
//This jar has been conditioned with pack200
public static final String MARK_PROPERTY = "pack200.conditioned"; //$NON-NLS-1$
//Exclude this jar from processing
public static final String MARK_EXCLUDE = "jarprocessor.exclude"; //$NON-NLS-1$
//Exclude this jar from pack200
public static final String MARK_EXCLUDE_PACK = "jarprocessor.exclude.pack"; //$NON-NLS-1$
//Exclude this jar from signing
public static final String MARK_EXCLUDE_SIGN = "jarprocessor.exclude.sign"; //$NON-NLS-1$
//Exclude this jar's children from processing
public static final String MARK_EXCLUDE_CHILDREN = "jarprocessor.exclude.children";
//Exclude this jar's children from pack200
public static final String MARK_EXCLUDE_CHILDREN_PACK = "jarprocessor.exclude.children.pack";
//Exclude this jar's children from signing
public static final String MARK_EXCLUDE_CHILDREN_SIGN = "jarprocessor.exclude.children.sign";
//Arguments used in pack200 for this jar
public static final String PACK_ARGS = "pack200.args"; //$NON-NLS-1$
public static final String PACK200_PROPERTY = "org.eclipse.update.jarprocessor.pack200"; //$NON-NLS-1$
public static final String JRE = "@jre"; //$NON-NLS-1$
public static final String PATH = "@path"; //$NON-NLS-1$
public static final String NONE = "@none"; //$NON-NLS-1$
public static final String PACKED_SUFFIX = ".pack.gz"; //$NON-NLS-1$
public static final String JAR_SUFFIX = ".jar"; //$NON-NLS-1$
public static final FileFilter JAR_FILTER = new FileFilter() {
public boolean accept(File pathname) {
return pathname.isFile() && pathname.getName().endsWith(".jar"); //$NON-NLS-1$
}
};
public static final FileFilter PACK_GZ_FILTER = new FileFilter() {
public boolean accept(File pathname) {
return pathname.isFile() && pathname.getName().endsWith(PACKED_SUFFIX);
}
};
public static void close(Object stream) {
if (stream != null) {
try {
if (stream instanceof InputStream)
((InputStream) stream).close();
else if (stream instanceof OutputStream)
((OutputStream) stream).close();
else if (stream instanceof JarFile)
((JarFile) stream).close();
} catch (IOException e) {
//ignore
}
}
}
/**
* get the set of commands to try to execute pack/unpack
* @param cmd, the command, either "pack200" or "unpack200"
* @return String [] or null
*/
public static String[] getPack200Commands(String cmd) {
String[] locations = null;
String prop = System.getProperty(PACK200_PROPERTY);
String javaHome = System.getProperty("java.home"); //$NON-NLS-1$
if (NONE.equals(prop)) {
return null;
} else if (JRE.equals(prop)) {
locations = new String[] {javaHome + "/bin/" + cmd}; //$NON-NLS-1$
} else if (PATH.equals(prop)) {
locations = new String[] {cmd};
} else if (prop == null) {
locations = new String[] {javaHome + "/bin/" + cmd, cmd}; //$NON-NLS-1$
} else {
locations = new String[] {prop + "/" + cmd}; //$NON-NLS-1$
}
return locations;
}
/**
* Transfers all available bytes from the given input stream to the given
* output stream. Closes both streams if close == true, regardless of failure.
* Flushes the destination stream if close == false
*
* @param source
* @param destination
* @param close
* @throws IOException
*/
public static void transferStreams(InputStream source, OutputStream destination, boolean close) throws IOException {
source = new BufferedInputStream(source);
destination = new BufferedOutputStream(destination);
try {
byte[] buffer = new byte[8192];
while (true) {
int bytesRead = -1;
if ((bytesRead = source.read(buffer)) == -1)
break;
destination.write(buffer, 0, bytesRead);
}
} finally {
if (close) {
close(source);
close(destination);
} else {
destination.flush();
}
}
}
/**
* Deletes all the files and directories from the given root down (inclusive).
* Returns false if we could not delete some file or an exception occurred
* at any point in the deletion.
* Even if an exception occurs, a best effort is made to continue deleting.
*/
public static boolean clear(java.io.File root) {
boolean result = clearChildren(root);
try {
if (root.exists())
result &= root.delete();
} catch (Exception e) {
result = false;
}
return result;
}
/**
* Deletes all the files and directories from the given root down, except for
* the root itself.
* Returns false if we could not delete some file or an exception occurred
* at any point in the deletion.
* Even if an exception occurs, a best effort is made to continue deleting.
*/
public static boolean clearChildren(java.io.File root) {
boolean result = true;
if (root.isDirectory()) {
String[] list = root.list();
// for some unknown reason, list() can return null.
// Just skip the children If it does.
if (list != null)
for (int i = 0; i < list.length; i++)
result &= clear(new java.io.File(root, list[i]));
}
return result;
}
public static Set getPackExclusions(Properties properties) {
if (properties == null)
return Collections.EMPTY_SET;
String packExcludes = properties.getProperty(PACK_EXCLUDES);
if (packExcludes != null) {
String[] excludes = toStringArray(packExcludes, ","); //$NON-NLS-1$
Set packExclusions = new HashSet();
for (int i = 0; i < excludes.length; i++) {
packExclusions.add(excludes[i]);
}
return packExclusions;
}
return Collections.EMPTY_SET;
}
public static Set getSignExclusions(Properties properties) {
if (properties == null)
return Collections.EMPTY_SET;
String signExcludes = properties.getProperty(SIGN_EXCLUDES);
if (signExcludes != null) {
String[] excludes = toStringArray(signExcludes, ","); //$NON-NLS-1$
Set signExclusions = new HashSet();
for (int i = 0; i < excludes.length; i++) {
signExclusions.add(excludes[i]);
}
return signExclusions;
}
return Collections.EMPTY_SET;
}
public static String concat(String[] array) {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < array.length; i++) {
if (i > 0)
buffer.append(' ');
buffer.append(array[i]);
}
return buffer.toString();
}
public static String[] toStringArray(String input, String separator) {
StringTokenizer tokenizer = new StringTokenizer(input, separator);
int count = tokenizer.countTokens();
String[] result = new String[count];
for (int i = 0; i < count; i++) {
result[i] = tokenizer.nextToken().trim();
}
return result;
}
/**
* Get the properties from the eclipse.inf file from the given jar. If the file is not a jar, null is returned.
* If the file is a jar, but does not contain an eclipse.inf file, an empty Properties object is returned.
* @param jarFile
* @return The eclipse.inf properties for the given jar file
*/
public static Properties getEclipseInf(File jarFile, boolean verbose) {
if (jarFile == null || !jarFile.exists()) {
if (verbose)
System.out.println("Failed to obtain eclipse.inf due to missing jar file: " + jarFile);
return null;
}
JarFile jar = null;
try {
jar = new JarFile(jarFile, false);
} catch (ZipException e) {
//not a jar, don't bother logging this.
return null;
} catch (IOException e) {
if (verbose) {
System.out.println("Failed to obtain eclipse.inf due to IOException: " + jarFile);
e.printStackTrace();
}
return null;
}
try {
JarEntry mark = jar.getJarEntry(MARK_FILE_NAME);
if (mark != null) {
InputStream in = jar.getInputStream(mark);
Properties props = new Properties();
props.load(in);
in.close();
return props;
}
return new Properties();
} catch (IOException e) {
if (verbose) {
System.out.println("Failed to obtain eclipse.inf due to IOException: " + jarFile);
e.printStackTrace();
}
return null;
} finally {
close(jar);
}
}
public static boolean shouldSkipJar(File input, boolean processAll, boolean verbose) {
Properties inf = getEclipseInf(input, verbose);
if (inf == null) {
//not a jar, could be a pack.gz
return false;
}
String exclude = inf.getProperty(MARK_EXCLUDE);
//was marked as exclude, we should skip
if (exclude != null && Boolean.valueOf(exclude).booleanValue())
return true;
//process all was set, don't skip
if (processAll)
return false;
//otherwise, we skip if not marked marked
String marked = inf.getProperty(MARK_PROPERTY);
return !Boolean.valueOf(marked).booleanValue();
}
/**
* Stores the given properties in the output stream. We store the properties
* in sorted order so that the signing hash doesn't change if the properties didn't change.
* @param props
* @param stream
*/
public static void storeProperties(Properties props, OutputStream stream) {
PrintStream printStream = new PrintStream(stream);
printStream.print("#Processed using Jarprocessor\n"); //$NON-NLS-1$
SortedMap sorted = new TreeMap(props);
for (Iterator iter = sorted.keySet().iterator(); iter.hasNext();) {
String key = (String) iter.next();
printStream.print(key);
printStream.print(" = "); //$NON-NLS-1$
printStream.print(sorted.get(key));
printStream.print("\n");
}
printStream.flush();
}
}