    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *     http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.compress.java.util.jar;
    018
    019import java.beans.PropertyChangeListener;
    020import java.io.File;
    021import java.io.IOException;
    022import java.io.InputStream;
    023import java.io.OutputStream;
    024import java.security.AccessController;
    025import java.security.PrivilegedAction;
    026import java.util.SortedMap;
    027import java.util.jar.JarFile;
    028import java.util.jar.JarInputStream;
    029import java.util.jar.JarOutputStream;
    030
    031import org.apache.commons.compress.harmony.archive.internal.nls.Messages;
    032
    033/**
    034 * Class factory for {@link Pack200.Packer} and {@link Pack200.Unpacker}.
    035 */
    036public abstract class Pack200 {
    037
    038    private static final String SYSTEM_PROPERTY_PACKER = "java.util.jar.Pack200.Packer"; //$NON-NLS-1$
    039
    040    private static final String SYSTEM_PROPERTY_UNPACKER = "java.util.jar.Pack200.Unpacker"; //$NON-NLS-1$
    041
    042    /**
    043     * Prevent this class from being instantiated.
    044     */
    045    private Pack200() {
    046        // do nothing
    047    }
    048
    049    /**
    050     * Returns a new instance of a packer engine.
    051     * <p>
    052     * The implementation of the packer engine is defined by the system property
    053     * {@code 'java.util.jar.Pack200.Packer'}. If this system property is
    054     * defined an instance of the specified class is returned, otherwise the
    055     * system's default implementation is returned.
    056     *
    057     * @return an instance of {@code Packer}
    058     */
    059    public static Pack200.Packer newPacker() {
    060        return (Packer) AccessController
    061                .doPrivileged(new PrivilegedAction<Object>() {
    062                    public Object run() {
    063                        String className = System
    064                                .getProperty(SYSTEM_PROPERTY_PACKER,
    065                                        "org.apache.commons.compress.harmony.pack200.Pack200PackerAdapter"); //$NON-NLS-1$
    066                        try {
    067                            // TODO Not sure if this will cause problems with
    068                            // loading the packer
    069                            return ClassLoader.getSystemClassLoader()
    070                                    .loadClass(className).newInstance();
    071                        } catch (Exception e) {
    072                            throw new Error(Messages.getString("archive.3E",className), e); //$NON-NLS-1$
    073                        }
    074                    }
    075                });
    076
    077    }
    078
    079    /**
    080     * Returns a new instance of a unpacker engine.
    081     * <p>
    082     * The implementation of the unpacker engine is defined by the system
    083     * property {@code 'java.util.jar.Pack200.Unpacker'}. If this system
    084     * property is defined an instance of the specified class is returned,
    085     * otherwise the system's default implementation is returned.
    086     *
    087     * @return a instance of {@code Unpacker}.
    088     */
    089    public static Pack200.Unpacker newUnpacker() {
    090        return (Unpacker) AccessController
    091                .doPrivileged(new PrivilegedAction<Object>() {
    092                    public Object run() {
    093                        String className = System
    094                                .getProperty(SYSTEM_PROPERTY_UNPACKER,
    095                                        "org.apache.commons.compress.harmony.unpack200.Pack200UnpackerAdapter");//$NON-NLS-1$
    096                        try {
    097                            return ClassLoader.getSystemClassLoader()
    098                                    .loadClass(className).newInstance();
    099                        } catch (Exception e) {
    100                            throw new Error(Messages.getString("archive.3E",className), e); //$NON-NLS-1$
    101                        }
    102                    }
    103                });
    104    }
    105
    106    /**
    107     * The interface defining the API for converting a JAR file to an output
    108     * stream in the Pack200 format.
    109     */
    110    public static interface Packer {
    111
    112        /**
    113         * the format of a class attribute name.
    114         */
    115        static final String CLASS_ATTRIBUTE_PFX = "pack.class.attribute."; //$NON-NLS-1$
    116
    117        /**
    118         * the format of a code attribute name.
    119         */
    120        static final String CODE_ATTRIBUTE_PFX = "pack.code.attribute."; //$NON-NLS-1$
    121
    122        /**
    123         * the deflation hint to set in the output archive.
    124         */
    125        static final String DEFLATE_HINT = "pack.deflate.hint";//$NON-NLS-1$
    126
    127        /**
    128         * the indicated amount of effort to use in compressing the archive.
    129         */
    130        static final String EFFORT = "pack.effort";//$NON-NLS-1$
    131
    132        /**
    133         * a String representation for {@code error}.
    134         */
    135        static final String ERROR = "error";//$NON-NLS-1$
    136
    137        /**
    138         * a String representation of {@code false}.
    139         */
    140        static final String FALSE = "false";//$NON-NLS-1$
    141
    142        /**
    143         * the format of a field attribute name.
    144         */
    145        static final String FIELD_ATTRIBUTE_PFX = "pack.field.attribute.";//$NON-NLS-1$
    146
    147        /**
    148         * a String representation for {@code keep}.
    149         */
    150        static final String KEEP = "keep";//$NON-NLS-1$
    151
    152        /**
    153         * decide if all elements shall transmit in their original order.
    154         */
    155        static final String KEEP_FILE_ORDER = "pack.keep.file.order";//$NON-NLS-1$
    156
    157        /**
    158         * a String representation for {@code latest}.
    159         */
    160        static final String LATEST = "latest";//$NON-NLS-1$
    161
    162        /**
    163         * the format of a method attribute name.
    164         */
    165        static final String METHOD_ATTRIBUTE_PFX = "pack.method.attribute.";//$NON-NLS-1$
    166
    167        /**
    168         * if it shall attempt to determine the latest modification time if this
    169         * is set to {@code LATEST}.
    170         */
    171        static final String MODIFICATION_TIME = "pack.modification.time";//$NON-NLS-1$
    172
    173        /**
    174         * a String representation of {@code pass}.
    175         */
    176        static final String PASS = "pass";//$NON-NLS-1$
    177
    178        /**
    179         * the file that will not be compressed.
    180         */
    181        static final String PASS_FILE_PFX = "pack.pass.file.";//$NON-NLS-1$
    182
    183        /**
    184         * packer progress as a percentage.
    185         */
    186        static final String PROGRESS = "pack.progress";//$NON-NLS-1$
    187
    188        /**
    189         * The number of bytes of each archive segment.
    190         */
    191        static final String SEGMENT_LIMIT = "pack.segment.limit";//$NON-NLS-1$
    192
    193        /**
    194         * a String representation of {@code strip}.
    195         */
    196        static final String STRIP = "strip";//$NON-NLS-1$
    197
    198        /**
    199         * a String representation of {@code true}.
    200         */
    201        static final String TRUE = "true";//$NON-NLS-1$
    202
    203        /**
    204         * the action to take if an unknown attribute is encountered.
    205         */
    206        static final String UNKNOWN_ATTRIBUTE = "pack.unknown.attribute";//$NON-NLS-1$
    207
    208        /**
    209         * Returns a sorted map of the properties of this packer.
    210         *
    211         * @return the properties of the packer.
    212         */
    213        SortedMap<String, String> properties();
    214
    215        /**
    216         * Pack the specified JAR file to the specified output stream.
    217         *
    218         * @param in
    219         *            JAR file to be compressed.
    220         * @param out
    221         *            stream of compressed data.
    222         * @throws IOException
    223         *             if I/O exception occurs.
    224         */
    225        void pack(JarFile in, OutputStream out) throws IOException;
    226
    227        /**
    228         * Pack the data from the specified jar input stream to the specified
    229         * output stream.
    230         *
    231         * @param in
    232         *            stream of uncompressed JAR data.
    233         * @param out
    234         *            stream of compressed data.
    235         * @throws IOException
    236         *             if I/O exception occurs.
    237         */
    238        void pack(JarInputStream in, OutputStream out) throws IOException;
    239
    240        /**
    241         * add a listener for PropertyChange events
    242         *
    243         * @param listener
    244         *            the listener to listen if PropertyChange events occurs
    245         */
    246        void addPropertyChangeListener(PropertyChangeListener listener);
    247
    248        /**
    249         * remove a listener
    250         *
    251         * @param listener
    252         *            listener to remove
    253         */
    254        void removePropertyChangeListener(PropertyChangeListener listener);
    255    }
    256
    257    /**
    258     * The interface defining the API for converting a packed stream in the
    259     * Pack200 format to a JAR file.
    260     */
    261    public static interface Unpacker {
    262
    263        /**
    264         * The String indicating if the unpacker should ignore all transmitted
    265         * values,can be replaced by either {@code true} or {@code false}.
    266         */
    267        static final String DEFLATE_HINT = "unpack.deflate.hint";//$NON-NLS-1$
    268
    269        /**
    270         * a String representation of {@code false}.
    271         */
    272        static final String FALSE = "false";//$NON-NLS-1$
    273
    274        /**
    275         * a String representation of {@code keep}.
    276         */
    277        static final String KEEP = "keep";//$NON-NLS-1$
    278
    279        /**
    280         * the progress as a {@code percentage}.
    281         */
    282        static final String PROGRESS = "unpack.progress";//$NON-NLS-1$
    283
    284        /**
    285         * a String representation of {@code true}.
    286         */
    287        static final String TRUE = "true";//$NON-NLS-1$
    288
    289        /**
    290         * Returns a sorted map of the properties of this unpacker.
    291         *
    292         * @return the properties of unpacker.
    293         */
    294        SortedMap<String, String> properties();
    295
    296        /**
    297         * Unpack the specified stream to the specified JAR output stream.
    298         *
    299         * @param in
    300         *            stream to uncompressed.
    301         * @param out
    302         *            JAR output stream of uncompressed data.
    303         * @throws IOException
    304         *             if I/O exception occurs.
    305         */
    306        void unpack(InputStream in, JarOutputStream out) throws IOException;
    307
    308        /**
    309         * Unpack the contents of the specified {@code File} to the specified
    310         * JAR output stream.
    311         *
    312         * @param in
    313         *            file to be uncompressed.
    314         * @param out
    315         *            JAR output stream of uncompressed data.
    316         * @throws IOException
    317         *             if I/O exception occurs.
    318         */
    319        void unpack(File in, JarOutputStream out) throws IOException;
    320
    321        /**
    322         * add a listener for {@code PropertyChange} events.
    323         *
    324         * @param listener
    325         *            the listener to listen if {@code PropertyChange} events
    326         *            occurs.
    327         */
    328        void addPropertyChangeListener(PropertyChangeListener listener);
    329
    330        /**
    331         * remove a listener.
    332         *
    333         * @param listener
    334         *            listener to remove.
    335         */
    336        void removePropertyChangeListener(PropertyChangeListener listener);
    337    }
    338
    339}