    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one
    003 * or more contributor license agreements.  See the NOTICE file
    004 * distributed with this work for additional information
    005 * regarding copyright ownership.  The ASF licenses this file
    006 * to you under the Apache License, Version 2.0 (the
    007 * "License"); you may not use this file except in compliance
    008 * with the License.  You may obtain a copy of the License at
    009 *
    010 * http://www.apache.org/licenses/LICENSE-2.0
    011 *
    012 * Unless required by applicable law or agreed to in writing,
    013 * software distributed under the License is distributed on an
    014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015 * KIND, either express or implied.  See the License for the
    016 * specific language governing permissions and limitations
    017 * under the License.
    018 */
    019
    020package org.apache.commons.compress.compressors.pack200;
    021
    022import java.io.File;
    023import java.io.FileOutputStream;
    024import java.io.IOException;
    025import java.util.HashMap;
    026import java.util.Map;
    027import java.util.jar.JarFile;
    028import java.util.jar.JarOutputStream;
    029import java.util.jar.Pack200;
    030
    031/**
    032 * Utility methods for Pack200.
    033 *
    034 * @ThreadSafe
    035 * @since 1.3
    036 */
    037public class Pack200Utils {
    038    private Pack200Utils() { }
    039
    040    /**
    041     * Normalizes a JAR archive in-place so it can be safely signed
    042     * and packed.
    043     *
    044     * <p>As stated in <a
    045     * href="http://download.oracle.com/javase/1.5.0/docs/api/java/util/jar/Pack200.Packer.html">Pack200.Packer's</a>
    046     * javadocs applying a Pack200 compression to a JAR archive will
    047     * in general make its sigantures invalid.  In order to prepare a
    048     * JAR for signing it should be "normalized" by packing and
    049     * unpacking it.  This is what this method does.</p>
    050     *
    051     * <p>Note this methods implicitly sets the segment length to
    052     * -1.</p>
    053     *
    054     * @param jar the JAR archive to normalize
    055     * @throws IOException if reading or writing fails
    056     */
    057    public static void normalize(final File jar)
    058        throws IOException {
    059        normalize(jar, jar, null);
    060    }
    061
    062    /**
    063     * Normalizes a JAR archive in-place so it can be safely signed
    064     * and packed.
    065     *
    066     * <p>As stated in <a
    067     * href="http://download.oracle.com/javase/1.5.0/docs/api/java/util/jar/Pack200.Packer.html">Pack200.Packer's</a>
    068     * javadocs applying a Pack200 compression to a JAR archive will
    069     * in general make its sigantures invalid.  In order to prepare a
    070     * JAR for signing it should be "normalized" by packing and
    071     * unpacking it.  This is what this method does.</p>
    072     *
    073     * @param jar the JAR archive to normalize
    074     * @param props properties to set for the pack operation.  This
    075     * method will implicitly set the segment limit to -1.
    076     * @throws IOException if reading or writing fails
    077     */
    078    public static void normalize(final File jar, final Map<String, String> props)
    079        throws IOException {
    080        normalize(jar, jar, props);
    081    }
    082
    083    /**
    084     * Normalizes a JAR archive so it can be safely signed and packed.
    085     *
    086     * <p>As stated in <a
    087     * href="http://download.oracle.com/javase/1.5.0/docs/api/java/util/jar/Pack200.Packer.html">Pack200.Packer's</a>
    088     * javadocs applying a Pack200 compression to a JAR archive will
    089     * in general make its sigantures invalid.  In order to prepare a
    090     * JAR for signing it should be "normalized" by packing and
    091     * unpacking it.  This is what this method does.</p>
    092     *
    093     * <p>This method does not replace the existing archive but creates
    094     * a new one.</p>
    095     *
    096     * <p>Note this methods implicitly sets the segment length to
    097     * -1.</p>
    098     *
    099     * @param from the JAR archive to normalize
    100     * @param to the normalized archive
    101     * @throws IOException if reading or writing fails
    102     */
    103    public static void normalize(final File from, final File to)
    104        throws IOException {
    105        normalize(from, to, null);
    106    }
    107
    108    /**
    109     * Normalizes a JAR archive so it can be safely signed and packed.
    110     *
    111     * <p>As stated in <a
    112     * href="http://download.oracle.com/javase/1.5.0/docs/api/java/util/jar/Pack200.Packer.html">Pack200.Packer's</a>
    113     * javadocs applying a Pack200 compression to a JAR archive will
    114     * in general make its sigantures invalid.  In order to prepare a
    115     * JAR for signing it should be "normalized" by packing and
    116     * unpacking it.  This is what this method does.</p>
    117     *
    118     * <p>This method does not replace the existing archive but creates
    119     * a new one.</p>
    120     *
    121     * @param from the JAR archive to normalize
    122     * @param to the normalized archive
    123     * @param props properties to set for the pack operation.  This
    124     * method will implicitly set the segment limit to -1.
    125     * @throws IOException if reading or writing fails
    126     */
    127    public static void normalize(final File from, final File to, Map<String, String> props)
    128            throws IOException {
    129        if (props == null) {
    130            props = new HashMap<>();
    131        }
    132        props.put(Pack200.Packer.SEGMENT_LIMIT, "-1");
    133        final File tempFile = File.createTempFile("commons-compress", "pack200normalize");
    134        try {
    135            try (FileOutputStream fos = new FileOutputStream(tempFile);
    136                    JarFile jarFile = new JarFile(from)) {
    137                final Pack200.Packer packer = Pack200.newPacker();
    138                packer.properties().putAll(props);
    139                packer.pack(jarFile, fos);
    140            }
    141            final Pack200.Unpacker unpacker = Pack200.newUnpacker();
    142            try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(to))) {
    143                unpacker.unpack(tempFile, jos);
    144            }
    145        } finally {
    146            if (!tempFile.delete()) {
    147                tempFile.deleteOnExit();
    148            }
    149        }
    150    }
    151}