1 /* 2 * Copyright (c) 2003, 2015, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.java.util.jar.pack; 27 28 import java.io.IOException; 29 import java.io.InputStream; 30 import java.io.PrintStream; 31 import java.io.PrintWriter; 32 import java.util.ArrayList; 33 import java.util.Collection; 34 import java.util.Comparator; 35 import java.util.HashMap; 36 import java.util.List; 37 import java.util.Map; 38 import java.util.Properties; 39 import java.util.Set; 40 import java.util.SortedMap; 41 import java.util.TreeMap; 42 import java.util.jar.Pack200; 43 44 /** 45 * Control block for publishing Pack200 options to the other classes. 46 */ 47 48 final class PropMap implements SortedMap<String, String> { 49 private final TreeMap<String, String> theMap = new TreeMap<>();; 50 51 // Override: 52 public String put(String key, String value) { 53 String oldValue = theMap.put(key, value); 54 return oldValue; 55 } 56 57 // All this other stuff is private to the current package. 58 // Outide clients of Pack200 do not need to use it; they can 59 // get by with generic SortedMap functionality. 60 private static Map<String, String> defaultProps; 61 static { 62 Properties props = new Properties(); 63 64 // Allow implementation selected via -Dpack.disable.native=true 65 props.put(Utils.DEBUG_DISABLE_NATIVE, 66 String.valueOf(Boolean.getBoolean(Utils.DEBUG_DISABLE_NATIVE))); 67 68 // Set the DEBUG_VERBOSE from system 69 props.put(Utils.DEBUG_VERBOSE, 70 String.valueOf(Integer.getInteger(Utils.DEBUG_VERBOSE,0))); 71 72 // The segment size is unlimited 73 props.put(Pack200.Packer.SEGMENT_LIMIT, "-1"); 74 75 // Preserve file ordering by default. 76 props.put(Pack200.Packer.KEEP_FILE_ORDER, Pack200.Packer.TRUE); 77 78 // Preserve all modification times by default. 79 props.put(Pack200.Packer.MODIFICATION_TIME, Pack200.Packer.KEEP); 80 81 // Preserve deflation hints by default. 82 props.put(Pack200.Packer.DEFLATE_HINT, Pack200.Packer.KEEP); 83 84 // Pass through files with unrecognized attributes by default. 85 props.put(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS); 86 87 // Pass through files with unrecognized format by default, also 88 // allow system property to be set 89 props.put(Utils.CLASS_FORMAT_ERROR, 90 System.getProperty(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS)); 91 92 // Default effort is 5, midway between 1 and 9. 93 props.put(Pack200.Packer.EFFORT, "5"); 94 95 // Define certain attribute layouts by default. 96 // Do this after the previous props are put in place, 97 // to allow override if necessary. 98 String propFile = "intrinsic.properties"; 99 100 try (InputStream propStr = PackerImpl.class.getResourceAsStream(propFile)) { 101 if (propStr == null) { 102 throw new RuntimeException(propFile + " cannot be loaded"); 103 } 104 props.load(propStr); 105 } catch (IOException ee) { 106 throw new RuntimeException(ee); 107 } 108 109 for (Map.Entry<Object, Object> e : props.entrySet()) { 110 String key = (String) e.getKey(); 111 String val = (String) e.getValue(); 112 if (key.startsWith("attribute.")) { 113 e.setValue(Attribute.normalizeLayoutString(val)); 114 } 115 } 116 117 @SuppressWarnings({"unchecked", "rawtypes"}) 118 HashMap<String, String> temp = new HashMap(props); // shrink to fit 119 defaultProps = temp; 120 } 121 122 PropMap() { 123 theMap.putAll(defaultProps); 124 } 125 126 // Return a view of this map which includes only properties 127 // that begin with the given prefix. This is easy because 128 // the map is sorted, and has a subMap accessor. 129 SortedMap<String, String> prefixMap(String prefix) { 130 int len = prefix.length(); 131 if (len == 0) 132 return this; 133 char nextch = (char)(prefix.charAt(len-1) + 1); 134 String limit = prefix.substring(0, len-1)+nextch; 135 //System.out.println(prefix+" => "+subMap(prefix, limit)); 136 return subMap(prefix, limit); 137 } 138 139 String getProperty(String s) { 140 return get(s); 141 } 142 String getProperty(String s, String defaultVal) { 143 String val = getProperty(s); 144 if (val == null) 145 return defaultVal; 146 return val; 147 } 148 String setProperty(String s, String val) { 149 return put(s, val); 150 } 151 152 // Get sequence of props for "prefix", and "prefix.*". 153 List<String> getProperties(String prefix) { 154 Collection<String> values = prefixMap(prefix).values(); 155 List<String> res = new ArrayList<>(values.size()); 156 res.addAll(values); 157 while (res.remove(null)); 158 return res; 159 } 160 161 private boolean toBoolean(String val) { 162 return Boolean.valueOf(val).booleanValue(); 163 } 164 boolean getBoolean(String s) { 165 return toBoolean(getProperty(s)); 166 } 167 boolean setBoolean(String s, boolean val) { 168 return toBoolean(setProperty(s, String.valueOf(val))); 169 } 170 int toInteger(String val) { 171 return toInteger(val, 0); 172 } 173 int toInteger(String val, int def) { 174 if (val == null) return def; 175 if (Pack200.Packer.TRUE.equals(val)) return 1; 176 if (Pack200.Packer.FALSE.equals(val)) return 0; 177 return Integer.parseInt(val); 178 } 179 int getInteger(String s, int def) { 180 return toInteger(getProperty(s), def); 181 } 182 int getInteger(String s) { 183 return toInteger(getProperty(s)); 184 } 185 int setInteger(String s, int val) { 186 return toInteger(setProperty(s, String.valueOf(val))); 187 } 188 189 long toLong(String val) { 190 try { 191 return val == null ? 0 : Long.parseLong(val); 192 } catch (java.lang.NumberFormatException nfe) { 193 throw new IllegalArgumentException("Invalid value"); 194 } 195 } 196 long getLong(String s) { 197 return toLong(getProperty(s)); 198 } 199 long setLong(String s, long val) { 200 return toLong(setProperty(s, String.valueOf(val))); 201 } 202 203 int getTime(String s) { 204 String sval = getProperty(s, "0"); 205 if (Utils.NOW.equals(sval)) { 206 return (int)((System.currentTimeMillis()+500)/1000); 207 } 208 long lval = toLong(sval); 209 final long recentSecondCount = 1000000000; 210 211 if (lval < recentSecondCount*10 && !"0".equals(sval)) 212 Utils.log.warning("Supplied modtime appears to be seconds rather than milliseconds: "+sval); 213 214 return (int)((lval+500)/1000); 215 } 216 217 void list(PrintStream out) { 218 PrintWriter outw = new PrintWriter(out); 219 list(outw); 220 outw.flush(); 221 } 222 void list(PrintWriter out) { 223 out.println("#"+Utils.PACK_ZIP_ARCHIVE_MARKER_COMMENT+"["); 224 Set<Map.Entry<String, String>> defaults = defaultProps.entrySet(); 225 for (Map.Entry<String, String> e : theMap.entrySet()) { 226 if (defaults.contains(e)) continue; 227 out.println(" " + e.getKey() + " = " + e.getValue()); 228 } 229 out.println("#]"); 230 } 231 232 @Override 233 public int size() { 234 return theMap.size(); 235 } 236 237 @Override 238 public boolean isEmpty() { 239 return theMap.isEmpty(); 240 } 241 242 @Override 243 public boolean containsKey(Object key) { 244 return theMap.containsKey(key); 245 } 246 247 @Override 248 public boolean containsValue(Object value) { 249 return theMap.containsValue(value); 250 } 251 252 @Override 253 public String get(Object key) { 254 return theMap.get(key); 255 } 256 257 @Override 258 public String remove(Object key) { 259 return theMap.remove(key); 260 } 261 262 @Override 263 public void putAll(Map<? extends String, ? extends String> m) { 264 theMap.putAll(m); 265 } 266 267 @Override 268 public void clear() { 269 theMap.clear(); 270 } 271 272 @Override 273 public Set<String> keySet() { 274 return theMap.keySet(); 275 } 276 277 @Override 278 public Collection<String> values() { 279 return theMap.values(); 280 } 281 282 @Override 283 public Set<Map.Entry<String, String>> entrySet() { 284 return theMap.entrySet(); 285 } 286 287 @Override 288 public Comparator<? super String> comparator() { 289 return theMap.comparator(); 290 } 291 292 @Override 293 public SortedMap<String, String> subMap(String fromKey, String toKey) { 294 return theMap.subMap(fromKey, toKey); 295 } 296 297 @Override 298 public SortedMap<String, String> headMap(String toKey) { 299 return theMap.headMap(toKey); 300 } 301 302 @Override 303 public SortedMap<String, String> tailMap(String fromKey) { 304 return theMap.tailMap(fromKey); 305 } 306 307 @Override 308 public String firstKey() { 309 return theMap.firstKey(); 310 } 311 312 @Override 313 public String lastKey() { 314 return theMap.lastKey(); 315 } 316 }