001: /*
002: * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.java.util.jar.pack;
027:
028: import java.util.*;
029: import java.util.jar.*;
030: import java.util.jar.Pack200;
031: import java.util.zip.*;
032: import java.io.*;
033: import java.beans.PropertyChangeListener;
034: import java.beans.PropertyChangeEvent;
035:
036: /**
037: * Control block for publishing Pack200 options to the other classes.
038: */
039: class PropMap extends TreeMap {
040: ArrayList _listeners = new ArrayList(1);
041:
042: void addListener(PropertyChangeListener listener) {
043: _listeners.add(listener);
044: }
045:
046: void removeListener(PropertyChangeListener listener) {
047: _listeners.remove(listener);
048: }
049:
050: void addListeners(ArrayList listeners) {
051: _listeners.addAll(listeners);
052: }
053:
054: void removeListeners(ArrayList listeners) {
055: _listeners.removeAll(listeners);
056: }
057:
058: // Override:
059: public Object put(Object key, Object value) {
060: Object oldValue = super .put(key, value);
061: if (value != oldValue && _listeners.size() > 0) {
062: // Post the property change event.
063: PropertyChangeEvent event = new PropertyChangeEvent(this ,
064: (String) key, oldValue, value);
065: for (Iterator i = _listeners.iterator(); i.hasNext();) {
066: PropertyChangeListener listener = (PropertyChangeListener) i
067: .next();
068: listener.propertyChange(event);
069: }
070: }
071: return oldValue;
072: }
073:
074: // All this other stuff is private to the current package.
075: // Outide clients of Pack200 do not need to use it; they can
076: // get by with generic SortedMap functionality.
077: private static Map defaultProps;
078: static {
079: Properties props = new Properties();
080:
081: // Allow implementation selected via -Dpack.disable.native=true
082: props.put(Utils.DEBUG_DISABLE_NATIVE, String.valueOf(Boolean
083: .getBoolean(Utils.DEBUG_DISABLE_NATIVE)));
084:
085: // Set the DEBUG_VERBOSE from system
086: props.put(Utils.DEBUG_VERBOSE, String.valueOf(Integer
087: .getInteger(Utils.DEBUG_VERBOSE, 0)));
088:
089: // Set the PACK_TIMEZONE_NO_UTC
090: props.put(Utils.PACK_DEFAULT_TIMEZONE, String.valueOf(Boolean
091: .getBoolean(Utils.PACK_DEFAULT_TIMEZONE)));
092:
093: // Limit segment size to less than a megabyte.
094: props.put(Pack200.Packer.SEGMENT_LIMIT, "" + (1 * 1000 * 1000));
095:
096: // Preserve file ordering by default.
097: props.put(Pack200.Packer.KEEP_FILE_ORDER, Pack200.Packer.TRUE);
098:
099: // Preserve all modification times by default.
100: props
101: .put(Pack200.Packer.MODIFICATION_TIME,
102: Pack200.Packer.KEEP);
103:
104: // Preserve deflation hints by default.
105: props.put(Pack200.Packer.DEFLATE_HINT, Pack200.Packer.KEEP);
106:
107: // Pass through files with unrecognized attributes by default.
108: props
109: .put(Pack200.Packer.UNKNOWN_ATTRIBUTE,
110: Pack200.Packer.PASS);
111:
112: // Default effort is 5, midway between 1 and 9.
113: props.put(Pack200.Packer.EFFORT, "5");
114:
115: // Define certain attribute layouts by default.
116: // Do this after the previous props are put in place,
117: // to allow override if necessary.
118: try {
119: String propFile = "intrinsic.properties";
120: InputStream propStr = PackerImpl.class
121: .getResourceAsStream(propFile);
122: props.load(new BufferedInputStream(propStr));
123: propStr.close();
124: for (Iterator i = props.entrySet().iterator(); i.hasNext();) {
125: Map.Entry e = (Map.Entry) i.next();
126: String key = (String) e.getKey();
127: String val = (String) e.getValue();
128: if (key.startsWith("attribute.")) {
129: e.setValue(Attribute.normalizeLayoutString(val));
130: }
131: }
132: } catch (IOException ee) {
133: throw new RuntimeException(ee);
134: }
135:
136: defaultProps = (new HashMap(props)); // shrink to fit
137: }
138:
139: PropMap() {
140: putAll(defaultProps);
141: }
142:
143: // Return a view of this map which includes only properties
144: // that begin with the given prefix. This is easy because
145: // the map is sorted, and has a subMap accessor.
146: SortedMap prefixMap(String prefix) {
147: int len = prefix.length();
148: if (len == 0)
149: return this ;
150: char nextch = (char) (prefix.charAt(len - 1) + 1);
151: String limit = prefix.substring(0, len - 1) + nextch;
152: //System.out.println(prefix+" => "+subMap(prefix, limit));
153: return subMap(prefix, limit);
154: }
155:
156: String getProperty(String s) {
157: return (String) get(s);
158: }
159:
160: String getProperty(String s, String defaultVal) {
161: String val = getProperty(s);
162: if (val == null)
163: return defaultVal;
164: return val;
165: }
166:
167: String setProperty(String s, String val) {
168: return (String) put(s, val);
169: }
170:
171: // Get sequence of props for "prefix", and "prefix.*".
172: List getProperties(String prefix) {
173: Collection values = prefixMap(prefix).values();
174: ArrayList res = new ArrayList(values.size());
175: res.addAll(values);
176: while (res.remove(null))
177: ;
178: return res;
179: }
180:
181: private boolean toBoolean(String val) {
182: return Boolean.valueOf(val).booleanValue();
183: }
184:
185: boolean getBoolean(String s) {
186: return toBoolean(getProperty(s));
187: }
188:
189: boolean setBoolean(String s, boolean val) {
190: return toBoolean(setProperty(s, String.valueOf(val)));
191: }
192:
193: int toInteger(String val) {
194: if (val == null)
195: return 0;
196: if (Pack200.Packer.TRUE.equals(val))
197: return 1;
198: if (Pack200.Packer.FALSE.equals(val))
199: return 0;
200: return Integer.parseInt(val);
201: }
202:
203: int getInteger(String s) {
204: return toInteger(getProperty(s));
205: }
206:
207: int setInteger(String s, int val) {
208: return toInteger(setProperty(s, String.valueOf(val)));
209: }
210:
211: long toLong(String val) {
212: try {
213: return val == null ? 0 : Long.parseLong(val);
214: } catch (java.lang.NumberFormatException nfe) {
215: throw new IllegalArgumentException("Invalid value");
216: }
217: }
218:
219: long getLong(String s) {
220: return toLong(getProperty(s));
221: }
222:
223: long setLong(String s, long val) {
224: return toLong(setProperty(s, String.valueOf(val)));
225: }
226:
227: int getTime(String s) {
228: String sval = getProperty(s, "0");
229: if (Utils.NOW.equals(sval)) {
230: return (int) ((System.currentTimeMillis() + 500) / 1000);
231: }
232: long lval = toLong(sval);
233: final long recentSecondCount = 1000000000;
234:
235: if (lval < recentSecondCount * 10 && !"0".equals(sval))
236: Utils.log
237: .warning("Supplied modtime appears to be seconds rather than milliseconds: "
238: + sval);
239:
240: return (int) ((lval + 500) / 1000);
241: }
242:
243: void list(PrintStream out) {
244: PrintWriter outw = new PrintWriter(out);
245: list(outw);
246: outw.flush();
247: }
248:
249: void list(PrintWriter out) {
250: out.println("#" + Utils.PACK_ZIP_ARCHIVE_MARKER_COMMENT + "[");
251: Set defaults = defaultProps.entrySet();
252: for (Iterator i = entrySet().iterator(); i.hasNext();) {
253: Map.Entry e = (Map.Entry) i.next();
254: if (defaults.contains(e))
255: continue;
256: out.println(" " + e.getKey() + " = " + e.getValue());
257: }
258: out.println("#]");
259: }
260: }
|