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.beans.PropertyChangeListener; 29 import java.beans.PropertyChangeEvent; 30 import java.io.IOException; 31 import java.io.InputStream; 32 import java.io.PrintStream; 33 import java.io.PrintWriter; 34 import java.util.ArrayList; 35 import java.util.Collection; 36 import java.util.Comparator; 37 import java.util.HashMap; 38 import java.util.List; 39 import java.util.Map; 40 import java.util.Properties; 41 import java.util.Set; 42 import java.util.SortedMap; 43 import java.util.TreeMap; 44 import java.util.jar.Pack200; 45 /** 46 * Control block for publishing Pack200 options to the other classes. 47 */ 48 49 final class PropMap implements SortedMap<String, String> { 50 private final TreeMap<String, String> theMap = new TreeMap<>();; 51 private final List<PropertyChangeListener> listenerList = new ArrayList<>(1); 52 53 void addListener(PropertyChangeListener listener) { 54 listenerList.add(listener); 55 } 56 57 void removeListener(PropertyChangeListener listener) { 58 listenerList.remove(listener); 59 } 60 61 void addListeners(ArrayList<PropertyChangeListener> listeners) { 62 listenerList.addAll(listeners); 63 } 64 65 void removeListeners(ArrayList<PropertyChangeListener> listeners) { 66 listenerList.removeAll(listeners); 67 } 68 69 // Override: 70 public String put(String key, String value) { 71 String oldValue = theMap.put(key, value); 72 if (value != oldValue && !listenerList.isEmpty()) { 73 // Post the property change event. 74 PropertyChangeEvent event = 75 new PropertyChangeEvent(this, key, 76 oldValue, value); 77 for (PropertyChangeListener listener : listenerList) { 78 listener.propertyChange(event); 79 } 80 } 81 return oldValue; 82 } 83 84 // All this other stuff is private to the current package. 85 // Outide clients of Pack200 do not need to use it; they can 86 // get by with generic SortedMap functionality. 87 private static Map<String, String> defaultProps; 88 static { 89 Properties props = new Properties(); 90 91 // Allow implementation selected via -Dpack.disable.native=true 92 props.put(Utils.DEBUG_DISABLE_NATIVE, 93 String.valueOf(Boolean.getBoolean(Utils.DEBUG_DISABLE_NATIVE))); 94 95 // Set the DEBUG_VERBOSE from system 96 props.put(Utils.DEBUG_VERBOSE, 97 String.valueOf(Integer.getInteger(Utils.DEBUG_VERBOSE,0))); 98 322 323 @Override 324 public SortedMap<String, String> headMap(String toKey) { 325 return theMap.headMap(toKey); 326 } 327 328 @Override 329 public SortedMap<String, String> tailMap(String fromKey) { 330 return theMap.tailMap(fromKey); 331 } 332 333 @Override 334 public String firstKey() { 335 return theMap.firstKey(); 336 } 337 338 @Override 339 public String lastKey() { 340 return theMap.lastKey(); 341 } 342 } | 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 import java.lang.reflect.Constructor; 44 import java.lang.reflect.InvocationTargetException; 45 import java.lang.reflect.Method; 46 47 /** 48 * Control block for publishing Pack200 options to the other classes. 49 */ 50 51 final class PropMap implements SortedMap<String, String> { 52 private final TreeMap<String, String> theMap = new TreeMap<>();; 53 54 // type is erased, elements are of type java.beans.PropertyChangeListener 55 private final List<Object> listenerList = new ArrayList<>(1); 56 57 void addListener(Object listener) { 58 assert Beans.isPropertyChangeListener(listener); 59 listenerList.add(listener); 60 } 61 62 void removeListener(Object listener) { 63 assert Beans.isPropertyChangeListener(listener); 64 listenerList.remove(listener); 65 } 66 67 // Override: 68 public String put(String key, String value) { 69 String oldValue = theMap.put(key, value); 70 if (value != oldValue && !listenerList.isEmpty()) { 71 assert Beans.isBeansPresent(); 72 // Post the property change event. 73 Object event = Beans.newPropertyChangeEvent(this, key, oldValue, value); 74 for (Object listener : listenerList) { 75 Beans.invokePropertyChange(listener, event); 76 } 77 } 78 return oldValue; 79 } 80 81 // All this other stuff is private to the current package. 82 // Outide clients of Pack200 do not need to use it; they can 83 // get by with generic SortedMap functionality. 84 private static Map<String, String> defaultProps; 85 static { 86 Properties props = new Properties(); 87 88 // Allow implementation selected via -Dpack.disable.native=true 89 props.put(Utils.DEBUG_DISABLE_NATIVE, 90 String.valueOf(Boolean.getBoolean(Utils.DEBUG_DISABLE_NATIVE))); 91 92 // Set the DEBUG_VERBOSE from system 93 props.put(Utils.DEBUG_VERBOSE, 94 String.valueOf(Integer.getInteger(Utils.DEBUG_VERBOSE,0))); 95 319 320 @Override 321 public SortedMap<String, String> headMap(String toKey) { 322 return theMap.headMap(toKey); 323 } 324 325 @Override 326 public SortedMap<String, String> tailMap(String fromKey) { 327 return theMap.tailMap(fromKey); 328 } 329 330 @Override 331 public String firstKey() { 332 return theMap.firstKey(); 333 } 334 335 @Override 336 public String lastKey() { 337 return theMap.lastKey(); 338 } 339 340 /** 341 * A class that provides access to the java.beans.PropertyChangeListener 342 * and java.beans.PropertyChangeEvent without creating a static dependency 343 * on java.beans. This class can be removed once the addPropertyChangeListener 344 * and removePropertyChangeListener methods are removed from Packer and 345 * Unpacker. 346 */ 347 private static class Beans { 348 private static final Class<?> propertyChangeListenerClass = 349 getClass("java.beans.PropertyChangeListener"); 350 351 private static final Class<?> propertyChangeEventClass = 352 getClass("java.beans.PropertyChangeEvent"); 353 354 private static final Method propertyChangeMethod = 355 getMethod(propertyChangeListenerClass, 356 "propertyChange", 357 propertyChangeEventClass); 358 359 private static final Constructor<?> propertyEventCtor = 360 getConstructor(propertyChangeEventClass, 361 Object.class, 362 String.class, 363 Object.class, 364 Object.class); 365 366 private static Class<?> getClass(String name) { 367 try { 368 return Class.forName(name, true, Beans.class.getClassLoader()); 369 } catch (ClassNotFoundException e) { 370 return null; 371 } 372 } 373 private static Constructor<?> getConstructor(Class<?> c, Class<?>... types) { 374 try { 375 return (c == null) ? null : c.getDeclaredConstructor(types); 376 } catch (NoSuchMethodException x) { 377 throw new AssertionError(x); 378 } 379 } 380 381 private static Method getMethod(Class<?> c, String name, Class<?>... types) { 382 try { 383 return (c == null) ? null : c.getMethod(name, types); 384 } catch (NoSuchMethodException e) { 385 throw new AssertionError(e); 386 } 387 } 388 389 /** 390 * Returns {@code true} if java.beans is present. 391 */ 392 static boolean isBeansPresent() { 393 return propertyChangeListenerClass != null && 394 propertyChangeEventClass != null; 395 } 396 397 /** 398 * Returns {@code true} if the given object is a PropertyChangeListener 399 */ 400 static boolean isPropertyChangeListener(Object obj) { 401 if (propertyChangeListenerClass == null) { 402 return false; 403 } else { 404 return propertyChangeListenerClass.isInstance(obj); 405 } 406 } 407 408 /** 409 * Returns a new PropertyChangeEvent with the given source, property 410 * name, old and new values. 411 */ 412 static Object newPropertyChangeEvent(Object source, String prop, 413 Object oldValue, Object newValue) 414 { 415 try { 416 return propertyEventCtor.newInstance(source, prop, oldValue, newValue); 417 } catch (InstantiationException | IllegalAccessException x) { 418 throw new AssertionError(x); 419 } catch (InvocationTargetException x) { 420 Throwable cause = x.getCause(); 421 if (cause instanceof Error) 422 throw (Error)cause; 423 if (cause instanceof RuntimeException) 424 throw (RuntimeException)cause; 425 throw new AssertionError(x); 426 } 427 } 428 429 /** 430 * Invokes the given PropertyChangeListern's propertyChange method 431 * with the given event. 432 */ 433 static void invokePropertyChange(Object listener, Object ev) { 434 try { 435 propertyChangeMethod.invoke(listener, ev); 436 } catch (IllegalAccessException x) { 437 throw new AssertionError(x); 438 } catch (InvocationTargetException x) { 439 Throwable cause = x.getCause(); 440 if (cause instanceof Error) 441 throw (Error)cause; 442 if (cause instanceof RuntimeException) 443 throw (RuntimeException)cause; 444 throw new AssertionError(x); 445 } 446 } 447 } 448 } |