1 /* 2 * Copyright (c) 2010, 2013, 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 jdk.nashorn.internal.runtime; 27 28 import java.util.Map; 29 import java.util.WeakHashMap; 30 31 /** 32 * Helper class to manage property listeners and notification. 33 */ 34 public class PropertyListenerManager implements PropertyListener { 35 PropertyListenerManager() {} 36 37 /** property listeners for this object. */ 38 private Map<PropertyListener,Boolean> listeners; 39 40 // These counters are updated in debug mode 41 private static int listenersAdded; 42 private static int listenersRemoved; 43 44 /** 45 * Return aggregate listeners added to all PropertyListenerManagers 46 * @return the listenersAdded 47 */ 48 public static int getListenersAdded() { 49 return listenersAdded; 50 } 51 52 /** 53 * Return aggregate listeners removed from all PropertyListenerManagers 54 * @return the listenersRemoved 55 */ 56 public static int getListenersRemoved() { 57 return listenersRemoved; 58 } 59 60 /** 61 * Return listeners added to this PropertyListenerManager. 62 * @return the listener count 63 */ 64 public final int getListenerCount() { 65 return listeners != null? listeners.size() : 0; 66 } 67 68 // Property listener management methods 69 70 /** 71 * Add a property listener to this object. 72 * 73 * @param listener The property listener that is added. 74 */ 75 public synchronized final void addPropertyListener(final PropertyListener listener) { 76 if (listeners == null) { 77 listeners = new WeakHashMap<>(); 78 } 79 80 if (Context.DEBUG) { 81 listenersAdded++; 82 } 83 listeners.put(listener, Boolean.TRUE); 84 } 85 86 /** 87 * Remove a property listener from this object. 88 * 89 * @param listener The property listener that is removed. 90 */ 91 public synchronized final void removePropertyListener(final PropertyListener listener) { 92 if (listeners != null) { 93 if (Context.DEBUG) { 94 listenersRemoved++; 95 } 96 listeners.remove(listener); 97 } 98 } 99 100 /** 101 * This method can be called to notify property addition to this object's listeners. 102 * 103 * @param object The ScriptObject to which property was added. 104 * @param prop The property being added. 105 */ 106 protected synchronized final void notifyPropertyAdded(final ScriptObject object, final Property prop) { 107 if (listeners != null) { 108 for (PropertyListener listener : listeners.keySet()) { 109 listener.propertyAdded(object, prop); 110 } 111 } 112 } 113 114 /** 115 * This method can be called to notify property deletion to this object's listeners. 116 * 117 * @param object The ScriptObject from which property was deleted. 118 * @param prop The property being deleted. 119 */ 120 protected synchronized final void notifyPropertyDeleted(final ScriptObject object, final Property prop) { 121 if (listeners != null) { 122 for (PropertyListener listener : listeners.keySet()) { 123 listener.propertyDeleted(object, prop); 124 } 125 } 126 } 127 128 /** 129 * This method can be called to notify property modification to this object's listeners. 130 * 131 * @param object The ScriptObject to which property was modified. 132 * @param oldProp The old property being replaced. 133 * @param newProp The new property that replaces the old property. 134 */ 135 protected synchronized final void notifyPropertyModified(final ScriptObject object, final Property oldProp, final Property newProp) { 136 if (listeners != null) { 137 for (PropertyListener listener : listeners.keySet()) { 138 listener.propertyModified(object, oldProp, newProp); 139 } 140 } 141 } 142 143 /** 144 * This method can be called to notify __proto__ modification to this object's listeners. 145 * 146 * @param object The ScriptObject whose __proto__ was changed. 147 * @param oldProto old __proto__ 148 * @param newProto new __proto__ 149 */ 150 protected synchronized final void notifyProtoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) { 151 if (listeners != null) { 152 for (PropertyListener listener : listeners.keySet()) { 153 listener.protoChanged(object, oldProto, newProto); 154 } 155 } 156 } 157 158 // PropertyListener methods 159 160 @Override 161 public final void propertyAdded(final ScriptObject object, final Property prop) { 162 notifyPropertyAdded(object, prop); 163 } 164 165 @Override 166 public final void propertyDeleted(final ScriptObject object, final Property prop) { 167 notifyPropertyDeleted(object, prop); 168 } 169 170 @Override 171 public final void propertyModified(final ScriptObject object, final Property oldProp, final Property newProp) { 172 notifyPropertyModified(object, oldProp, newProp); 173 } 174 175 @Override 176 public final void protoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) { 177 notifyProtoChanged(object, oldProto, newProto); 178 } 179 }