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="https://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="https://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="https://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="https://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}