1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17package java.util.jar;
18
19import java.beans.PropertyChangeListener;
20import java.io.File;
21import java.io.IOException;
22import java.io.InputStream;
23import java.io.OutputStream;
24import java.util.SortedMap;
25
26/**
27 * Class factory for {@link Pack200.Packer} and {@link Pack200.Unpacker}.
28 */
29public abstract class Pack200 {
30
31    private static final String SYSTEM_PROPERTY_PACKER = "java.util.jar.Pack200.Packer";
32
33    private static final String SYSTEM_PROPERTY_UNPACKER = "java.util.jar.Pack200.Unpacker";
34
35    /**
36     * Prevent this class from being instantiated.
37     */
38    private Pack200() {
39        // do nothing
40    }
41
42    /**
43     * Returns a new instance of a packer engine.
44     * <p>
45     * The implementation of the packer engine is defined by the system property
46     * {@code 'java.util.jar.Pack200.Packer'}. If this system property is
47     * defined an instance of the specified class is returned, otherwise the
48     * system's default implementation is returned.
49     *
50     * @return an instance of {@code Packer}
51     */
52    public static Pack200.Packer newPacker() {
53        String className = System.getProperty(SYSTEM_PROPERTY_PACKER, "org.apache.harmony.pack200.Pack200PackerAdapter");
54        try {
55            // TODO Not sure if this will cause problems with
56            // loading the packer
57            return (Packer) ClassLoader.getSystemClassLoader().loadClass(className).newInstance();
58        } catch (Exception e) {
59            throw new Error("Can't load class " + className, e);
60        }
61    }
62
63    /**
64     * Returns a new instance of a unpacker engine.
65     * <p>
66     * The implementation of the unpacker engine is defined by the system
67     * property {@code 'java.util.jar.Pack200.Unpacker'}. If this system
68     * property is defined an instance of the specified class is returned,
69     * otherwise the system's default implementation is returned.
70     *
71     * @return a instance of {@code Unpacker}.
72     */
73    public static Pack200.Unpacker newUnpacker() {
74        String className = System.getProperty(SYSTEM_PROPERTY_UNPACKER, "org.apache.harmony.unpack200.Pack200UnpackerAdapter");
75        try {
76            return (Unpacker) ClassLoader.getSystemClassLoader().loadClass(className).newInstance();
77        } catch (Exception e) {
78            throw new Error("Can't load class " + className, e);
79        }
80    }
81
82    /**
83     * The interface defining the API for converting a JAR file to an output
84     * stream in the Pack200 format.
85     */
86    public static interface Packer {
87
88        /**
89         * the format of a class attribute name.
90         */
91        static final String CLASS_ATTRIBUTE_PFX = "pack.class.attribute.";
92
93        /**
94         * the format of a code attribute name.
95         */
96        static final String CODE_ATTRIBUTE_PFX = "pack.code.attribute.";
97
98        /**
99         * the deflation hint to set in the output archive.
100         */
101        static final String DEFLATE_HINT = "pack.deflate.hint";
102
103        /**
104         * the indicated amount of effort to use in compressing the archive.
105         */
106        static final String EFFORT = "pack.effort";
107
108        /**
109         * a String representation for {@code error}.
110         */
111        static final String ERROR = "error";
112
113        /**
114         * a String representation of {@code false}.
115         */
116        static final String FALSE = "false";
117
118        /**
119         * the format of a field attribute name.
120         */
121        static final String FIELD_ATTRIBUTE_PFX = "pack.field.attribute.";
122
123        /**
124         * a String representation for {@code keep}.
125         */
126        static final String KEEP = "keep";
127
128        /**
129         * decide if all elements shall transmit in their original order.
130         */
131        static final String KEEP_FILE_ORDER = "pack.keep.file.order";
132
133        /**
134         * a String representation for {@code latest}.
135         */
136        static final String LATEST = "latest";
137
138        /**
139         * the format of a method attribute name.
140         */
141        static final String METHOD_ATTRIBUTE_PFX = "pack.method.attribute.";
142
143        /**
144         * if it shall attempt to determine the latest modification time if this
145         * is set to {@code LATEST}.
146         */
147        static final String MODIFICATION_TIME = "pack.modification.time";
148
149        /**
150         * a String representation of {@code pass}.
151         */
152        static final String PASS = "pass";
153
154        /**
155         * the file that will not be compressed.
156         */
157        static final String PASS_FILE_PFX = "pack.pass.file.";
158
159        /**
160         * packer progress as a percentage.
161         */
162        static final String PROGRESS = "pack.progress";
163
164        /**
165         * The number of bytes of each archive segment.
166         */
167        static final String SEGMENT_LIMIT = "pack.segment.limit";
168
169        /**
170         * a String representation of {@code strip}.
171         */
172        static final String STRIP = "strip";
173
174        /**
175         * a String representation of {@code true}.
176         */
177        static final String TRUE = "true";
178
179        /**
180         * the action to take if an unknown attribute is encountered.
181         */
182        static final String UNKNOWN_ATTRIBUTE = "pack.unknown.attribute";
183
184        /**
185         * Returns a sorted map of the properties of this packer.
186         *
187         * @return the properties of the packer.
188         */
189        SortedMap<String, String> properties();
190
191        /**
192         * Pack the specified JAR file to the specified output stream.
193         *
194         * @param in
195         *            JAR file to be compressed.
196         * @param out
197         *            stream of compressed data.
198         * @throws IOException
199         *             if I/O exception occurs.
200         */
201        void pack(JarFile in, OutputStream out) throws IOException;
202
203        /**
204         * Pack the data from the specified jar input stream to the specified
205         * output stream.
206         *
207         * @param in
208         *            stream of uncompressed JAR data.
209         * @param out
210         *            stream of compressed data.
211         * @throws IOException
212         *             if I/O exception occurs.
213         */
214        void pack(JarInputStream in, OutputStream out) throws IOException;
215
216        /**
217         * add a listener for PropertyChange events
218         *
219         * @param listener
220         *            the listener to listen if PropertyChange events occurs
221         */
222        void addPropertyChangeListener(PropertyChangeListener listener);
223
224        /**
225         * remove a listener
226         *
227         * @param listener
228         *            listener to remove
229         */
230        void removePropertyChangeListener(PropertyChangeListener listener);
231    }
232
233    /**
234     * The interface defining the API for converting a packed stream in the
235     * Pack200 format to a JAR file.
236     */
237    public static interface Unpacker {
238
239        /**
240         * The String indicating if the unpacker should ignore all transmitted
241         * values,can be replaced by either {@code true} or {@code false}.
242         */
243        static final String DEFLATE_HINT = "unpack.deflate.hint";
244
245        /**
246         * a String representation of {@code false}.
247         */
248        static final String FALSE = "false";
249
250        /**
251         * a String representation of {@code keep}.
252         */
253        static final String KEEP = "keep";
254
255        /**
256         * the progress as a {@code percentage}.
257         */
258        static final String PROGRESS = "unpack.progress";
259
260        /**
261         * a String representation of {@code true}.
262         */
263        static final String TRUE = "true";
264
265        /**
266         * Returns a sorted map of the properties of this unpacker.
267         *
268         * @return the properties of unpacker.
269         */
270        SortedMap<String, String> properties();
271
272        /**
273         * Unpack the specified stream to the specified JAR output stream.
274         *
275         * @param in
276         *            stream to uncompressed.
277         * @param out
278         *            JAR output stream of uncompressed data.
279         * @throws IOException
280         *             if I/O exception occurs.
281         */
282        void unpack(InputStream in, JarOutputStream out) throws IOException;
283
284        /**
285         * Unpack the contents of the specified {@code File} to the specified
286         * JAR output stream.
287         *
288         * @param in
289         *            file to be uncompressed.
290         * @param out
291         *            JAR output stream of uncompressed data.
292         * @throws IOException
293         *             if I/O exception occurs.
294         */
295        void unpack(File in, JarOutputStream out) throws IOException;
296
297        /**
298         * add a listener for {@code PropertyChange} events.
299         *
300         * @param listener
301         *            the listener to listen if {@code PropertyChange} events
302         *            occurs.
303         */
304        void addPropertyChangeListener(PropertyChangeListener listener);
305
306        /**
307         * remove a listener.
308         *
309         * @param listener
310         *            listener to remove.
311         */
312        void removePropertyChangeListener(PropertyChangeListener listener);
313    }
314
315}
316