blob: d4e808d829879b6bec030deab1aed7a4cbe90890 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.java.util.jar.pack;
27
28import java.util.*;
29import java.util.jar.*;
30import java.util.jar.Pack200;
31import java.util.zip.*;
32import java.io.*;
33import java.beans.PropertyChangeListener;
34import java.beans.PropertyChangeEvent;
35/**
36 * Control block for publishing Pack200 options to the other classes.
37 */
38class PropMap extends TreeMap {
39 ArrayList _listeners = new ArrayList(1);
40
41 void addListener(PropertyChangeListener listener) {
42 _listeners.add(listener);
43 }
44
45 void removeListener(PropertyChangeListener listener) {
46 _listeners.remove(listener);
47 }
48
49 void addListeners(ArrayList listeners) {
50 _listeners.addAll(listeners);
51 }
52
53 void removeListeners(ArrayList listeners) {
54 _listeners.removeAll(listeners);
55 }
56
57 // Override:
58 public Object put(Object key, Object value) {
59 Object oldValue = super.put(key, value);
60 if (value != oldValue && _listeners.size() > 0) {
61 // Post the property change event.
62 PropertyChangeEvent event =
63 new PropertyChangeEvent(this, (String) key,
64 oldValue, value);
65 for (Iterator i = _listeners.iterator(); i.hasNext(); ) {
66 PropertyChangeListener listener =
67 (PropertyChangeListener) i.next();
68 listener.propertyChange(event);
69 }
70 }
71 return oldValue;
72 }
73
74 // All this other stuff is private to the current package.
75 // Outide clients of Pack200 do not need to use it; they can
76 // get by with generic SortedMap functionality.
77 private static Map defaultProps;
78 static {
79 Properties props = new Properties();
80
81 // Allow implementation selected via -Dpack.disable.native=true
82 props.put(Utils.DEBUG_DISABLE_NATIVE,
83 String.valueOf(Boolean.getBoolean(Utils.DEBUG_DISABLE_NATIVE)));
84
85 // Set the DEBUG_VERBOSE from system
86 props.put(Utils.DEBUG_VERBOSE,
87 String.valueOf(Integer.getInteger(Utils.DEBUG_VERBOSE,0)));
88
89 // Set the PACK_TIMEZONE_NO_UTC
90 props.put(Utils.PACK_DEFAULT_TIMEZONE,
91 String.valueOf(Boolean.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)));
92
93 // Limit segment size to less than a megabyte.
94 props.put(Pack200.Packer.SEGMENT_LIMIT, ""+(1*1000*1000));
95
96 // Preserve file ordering by default.
97 props.put(Pack200.Packer.KEEP_FILE_ORDER, Pack200.Packer.TRUE);
98
99 // Preserve all modification times by default.
100 props.put(Pack200.Packer.MODIFICATION_TIME, Pack200.Packer.KEEP);
101
102 // Preserve deflation hints by default.
103 props.put(Pack200.Packer.DEFLATE_HINT, Pack200.Packer.KEEP);
104
105 // Pass through files with unrecognized attributes by default.
106 props.put(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS);
107
108 // Default effort is 5, midway between 1 and 9.
109 props.put(Pack200.Packer.EFFORT, "5");
110
111 // Define certain attribute layouts by default.
112 // Do this after the previous props are put in place,
113 // to allow override if necessary.
114 try {
115 String propFile = "intrinsic.properties";
116 InputStream propStr = PackerImpl.class.getResourceAsStream(propFile);
117 props.load(new BufferedInputStream(propStr));
118 propStr.close();
119 for (Iterator i = props.entrySet().iterator(); i.hasNext(); ) {
120 Map.Entry e = (Map.Entry) i.next();
121 String key = (String) e.getKey();
122 String val = (String) e.getValue();
123 if (key.startsWith("attribute.")) {
124 e.setValue(Attribute.normalizeLayoutString(val));
125 }
126 }
127 } catch (IOException ee) {
128 throw new RuntimeException(ee);
129 }
130
131 defaultProps = (new HashMap(props)); // shrink to fit
132 }
133
134 PropMap() {
135 putAll(defaultProps);
136 }
137
138 // Return a view of this map which includes only properties
139 // that begin with the given prefix. This is easy because
140 // the map is sorted, and has a subMap accessor.
141 SortedMap prefixMap(String prefix) {
142 int len = prefix.length();
143 if (len == 0)
144 return this;
145 char nextch = (char)(prefix.charAt(len-1) + 1);
146 String limit = prefix.substring(0, len-1)+nextch;
147 //System.out.println(prefix+" => "+subMap(prefix, limit));
148 return subMap(prefix, limit);
149 }
150
151 String getProperty(String s) {
152 return (String) get(s);
153 }
154 String getProperty(String s, String defaultVal) {
155 String val = getProperty(s);
156 if (val == null)
157 return defaultVal;
158 return val;
159 }
160 String setProperty(String s, String val) {
161 return (String) put(s, val);
162 }
163
164 // Get sequence of props for "prefix", and "prefix.*".
165 List getProperties(String prefix) {
166 Collection values = prefixMap(prefix).values();
167 ArrayList res = new ArrayList(values.size());
168 res.addAll(values);
169 while (res.remove(null));
170 return res;
171 }
172
173 private boolean toBoolean(String val) {
174 return Boolean.valueOf(val).booleanValue();
175 }
176 boolean getBoolean(String s) {
177 return toBoolean(getProperty(s));
178 }
179 boolean setBoolean(String s, boolean val) {
180 return toBoolean(setProperty(s, String.valueOf(val)));
181 }
182
183 int toInteger(String val) {
184 if (val == null) return 0;
185 if (Pack200.Packer.TRUE.equals(val)) return 1;
186 if (Pack200.Packer.FALSE.equals(val)) return 0;
187 return Integer.parseInt(val);
188 }
189 int getInteger(String s) {
190 return toInteger(getProperty(s));
191 }
192 int setInteger(String s, int val) {
193 return toInteger(setProperty(s, String.valueOf(val)));
194 }
195
196 long toLong(String val) {
197 try {
198 return val == null ? 0 : Long.parseLong(val);
199 } catch (java.lang.NumberFormatException nfe) {
200 throw new IllegalArgumentException("Invalid value");
201 }
202 }
203 long getLong(String s) {
204 return toLong(getProperty(s));
205 }
206 long setLong(String s, long val) {
207 return toLong(setProperty(s, String.valueOf(val)));
208 }
209
210 int getTime(String s) {
211 String sval = getProperty(s, "0");
212 if (Utils.NOW.equals(sval)) {
213 return (int)((System.currentTimeMillis()+500)/1000);
214 }
215 long lval = toLong(sval);
216 final long recentSecondCount = 1000000000;
217
218 if (lval < recentSecondCount*10 && !"0".equals(sval))
219 Utils.log.warning("Supplied modtime appears to be seconds rather than milliseconds: "+sval);
220
221 return (int)((lval+500)/1000);
222 }
223
224 void list(PrintStream out) {
225 PrintWriter outw = new PrintWriter(out);
226 list(outw);
227 outw.flush();
228 }
229 void list(PrintWriter out) {
230 out.println("#"+Utils.PACK_ZIP_ARCHIVE_MARKER_COMMENT+"[");
231 Set defaults = defaultProps.entrySet();
232 for (Iterator i = entrySet().iterator(); i.hasNext(); ) {
233 Map.Entry e = (Map.Entry) i.next();
234 if (defaults.contains(e)) continue;
235 out.println(" " + e.getKey() + " = " + e.getValue());
236 }
237 out.println("#]");
238 }
239}