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 /** 039 * The interface defining the API for converting a JAR file to an output 040 * stream in the Pack200 format. 041 */ 042 public interface Packer { 043 044 /** 045 * the format of a class attribute name. 046 */ 047 String CLASS_ATTRIBUTE_PFX = "pack.class.attribute."; //$NON-NLS-1$ 048 049 /** 050 * the format of a code attribute name. 051 */ 052 String CODE_ATTRIBUTE_PFX = "pack.code.attribute."; //$NON-NLS-1$ 053 054 /** 055 * the deflation hint to set in the output archive. 056 */ 057 String DEFLATE_HINT = "pack.deflate.hint";//$NON-NLS-1$ 058 059 /** 060 * the indicated amount of effort to use in compressing the archive. 061 */ 062 String EFFORT = "pack.effort";//$NON-NLS-1$ 063 064 /** 065 * a String representation for {@code error}. 066 */ 067 String ERROR = "error";//$NON-NLS-1$ 068 069 /** 070 * a String representation of {@code false}. 071 */ 072 String FALSE = "false";//$NON-NLS-1$ 073 074 /** 075 * the format of a field attribute name. 076 */ 077 String FIELD_ATTRIBUTE_PFX = "pack.field.attribute.";//$NON-NLS-1$ 078 079 /** 080 * a String representation for {@code keep}. 081 */ 082 String KEEP = "keep";//$NON-NLS-1$ 083 084 /** 085 * decide if all elements shall transmit in their original order. 086 */ 087 String KEEP_FILE_ORDER = "pack.keep.file.order";//$NON-NLS-1$ 088 089 /** 090 * a String representation for {@code latest}. 091 */ 092 String LATEST = "latest";//$NON-NLS-1$ 093 094 /** 095 * the format of a method attribute name. 096 */ 097 String METHOD_ATTRIBUTE_PFX = "pack.method.attribute.";//$NON-NLS-1$ 098 099 /** 100 * if it shall attempt to determine the latest modification time if this 101 * is set to {@code LATEST}. 102 */ 103 String MODIFICATION_TIME = "pack.modification.time";//$NON-NLS-1$ 104 105 /** 106 * a String representation of {@code pass}. 107 */ 108 String PASS = "pass";//$NON-NLS-1$ 109 110 /** 111 * the file that will not be compressed. 112 */ 113 String PASS_FILE_PFX = "pack.pass.file.";//$NON-NLS-1$ 114 115 /** 116 * packer progress as a percentage. 117 */ 118 String PROGRESS = "pack.progress";//$NON-NLS-1$ 119 120 /** 121 * The number of bytes of each archive segment. 122 */ 123 String SEGMENT_LIMIT = "pack.segment.limit";//$NON-NLS-1$ 124 125 /** 126 * a String representation of {@code strip}. 127 */ 128 String STRIP = "strip";//$NON-NLS-1$ 129 130 /** 131 * a String representation of {@code true}. 132 */ 133 String TRUE = "true";//$NON-NLS-1$ 134 135 /** 136 * the action to take if an unknown attribute is encountered. 137 */ 138 String UNKNOWN_ATTRIBUTE = "pack.unknown.attribute";//$NON-NLS-1$ 139 140 /** 141 * add a listener for PropertyChange events 142 * 143 * @param listener 144 * the listener to listen if PropertyChange events occurs 145 */ 146 void addPropertyChangeListener(PropertyChangeListener listener); 147 148 /** 149 * Pack the specified JAR file to the specified output stream. 150 * 151 * @param in 152 * JAR file to be compressed. 153 * @param out 154 * stream of compressed data. 155 * @throws IOException 156 * if I/O exception occurs. 157 */ 158 void pack(JarFile in, OutputStream out) throws IOException; 159 160 /** 161 * Pack the data from the specified jar input stream to the specified 162 * output stream. 163 * 164 * @param in 165 * stream of uncompressed JAR data. 166 * @param out 167 * stream of compressed data. 168 * @throws IOException 169 * if I/O exception occurs. 170 */ 171 void pack(JarInputStream in, OutputStream out) throws IOException; 172 173 /** 174 * Returns a sorted map of the properties of this packer. 175 * 176 * @return the properties of the packer. 177 */ 178 SortedMap<String, String> properties(); 179 180 /** 181 * remove a listener 182 * 183 * @param listener 184 * listener to remove 185 */ 186 void removePropertyChangeListener(PropertyChangeListener listener); 187 } 188 189 /** 190 * The interface defining the API for converting a packed stream in the 191 * Pack200 format to a JAR file. 192 */ 193 public interface Unpacker { 194 195 /** 196 * The String indicating if the unpacker should ignore all transmitted 197 * values, can be replaced by either {@code true} or {@code false}. 198 */ 199 String DEFLATE_HINT = "unpack.deflate.hint";//$NON-NLS-1$ 200 201 /** 202 * a String representation of {@code false}. 203 */ 204 String FALSE = "false";//$NON-NLS-1$ 205 206 /** 207 * a String representation of {@code keep}. 208 */ 209 String KEEP = "keep";//$NON-NLS-1$ 210 211 /** 212 * the progress as a {@code percentage}. 213 */ 214 String PROGRESS = "unpack.progress";//$NON-NLS-1$ 215 216 /** 217 * a String representation of {@code true}. 218 */ 219 String TRUE = "true";//$NON-NLS-1$ 220 221 /** 222 * add a listener for {@code PropertyChange} events. 223 * 224 * @param listener 225 * the listener to listen if {@code PropertyChange} events 226 * occurs. 227 */ 228 void addPropertyChangeListener(PropertyChangeListener listener); 229 230 /** 231 * Returns a sorted map of the properties of this unpacker. 232 * 233 * @return the properties of unpacker. 234 */ 235 SortedMap<String, String> properties(); 236 237 /** 238 * remove a listener. 239 * 240 * @param listener 241 * listener to remove. 242 */ 243 void removePropertyChangeListener(PropertyChangeListener listener); 244 245 /** 246 * Unpack the contents of the specified {@code File} to the specified 247 * JAR output stream. 248 * 249 * @param in 250 * file to be uncompressed. 251 * @param out 252 * JAR output stream of uncompressed data. 253 * @throws IOException 254 * if I/O exception occurs. 255 */ 256 void unpack(File in, JarOutputStream out) throws IOException; 257 258 /** 259 * Unpack the specified stream to the specified JAR output stream. 260 * 261 * @param in 262 * stream to uncompressed. 263 * @param out 264 * JAR output stream of uncompressed data. 265 * @throws IOException 266 * if I/O exception occurs. 267 */ 268 void unpack(InputStream in, JarOutputStream out) throws IOException; 269 } 270 271 private static final String SYSTEM_PROPERTY_PACKER = "java.util.jar.Pack200.Packer"; //$NON-NLS-1$ 272 273 private static final String SYSTEM_PROPERTY_UNPACKER = "java.util.jar.Pack200.Unpacker"; //$NON-NLS-1$ 274 275 static Object newInstance(final String systemProperty, final String defaultClassName) { 276 return AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 277 final String className = System.getProperty(systemProperty, defaultClassName); 278 try { 279 // TODO Not sure if this will cause problems loading the class 280 return Pack200.class.getClassLoader().loadClass(className).newInstance(); 281 } catch (final Exception e) { 282 throw new Error(Messages.getString("archive.3E", className), e); //$NON-NLS-1$ 283 } 284 }); 285 } 286 287 /** 288 * Returns a new instance of a packer engine. 289 * <p> 290 * The implementation of the packer engine is defined by the system property 291 * {@code 'java.util.jar.Pack200.Packer'}. If this system property is 292 * defined an instance of the specified class is returned, otherwise the 293 * system's default implementation is returned. 294 * 295 * @return an instance of {@code Packer} 296 */ 297 public static Pack200.Packer newPacker() { 298 return (Packer) newInstance(SYSTEM_PROPERTY_PACKER, "org.apache.commons.compress.harmony.pack200.Pack200PackerAdapter"); //$NON-NLS-1$ 299 } 300 301 /** 302 * Returns a new instance of an unpacker engine. 303 * <p> 304 * The implementation of the unpacker engine is defined by the system 305 * property {@link Pack200.Unpacker}. If this system 306 * property is defined an instance of the specified class is returned, 307 * otherwise the system's default implementation is returned. 308 * 309 * @return an instance of {@link Pack200.Unpacker}. 310 */ 311 public static Pack200.Unpacker newUnpacker() { 312 return (Unpacker) newInstance(SYSTEM_PROPERTY_UNPACKER, "org.apache.commons.compress.harmony.unpack200.Pack200UnpackerAdapter"); //$NON-NLS-1$ 313 } 314 315 /** 316 * Prevent this class from being instantiated. 317 */ 318 private Pack200() { 319 // do nothing 320 } 321 322}