| /******************************************************************************* |
| * Copyright (c) 2006, 2008 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.equinox.internal.p2.jarprocessor; |
| |
| import java.io.*; |
| import java.util.*; |
| import java.util.jar.JarEntry; |
| import java.util.jar.JarFile; |
| import java.util.zip.ZipException; |
| |
| import org.eclipse.internal.provisional.equinox.p2.jarprocessor.JarProcessor; |
| |
| /** |
| * @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"; //$NON-NLS-1$ |
| //Exclude this jar's children from pack200 |
| public static final String MARK_EXCLUDE_CHILDREN_PACK = "jarprocessor.exclude.children.pack"; //$NON-NLS-1$ |
| //Exclude this jar's children from signing |
| public static final String MARK_EXCLUDE_CHILDREN_SIGN = "jarprocessor.exclude.children.sign"; //$NON-NLS-1$ |
| //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(JarProcessor.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); //$NON-NLS-1$ |
| 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); //$NON-NLS-1$ |
| 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); //$NON-NLS-1$ |
| 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"); //$NON-NLS-1$ |
| |
| } |
| printStream.flush(); |
| } |
| } |