1 /* 2 * Copyright (c) 2011, 2014, 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.webkit.dom; 27 28 import com.sun.webkit.Disposer; 29 import com.sun.webkit.DisposerRecord; 30 import java.lang.ref.WeakReference; 31 import java.util.HashMap; 32 import java.util.Map; 33 import java.util.WeakHashMap; 34 import org.w3c.dom.events.Event; 35 import org.w3c.dom.events.EventListener; 36 37 //navive code driven life circle. 38 //single time peer usage 39 final class EventListenerImpl implements EventListener { 40 private static final Map<EventListener, Long> EL2peer = 41 new WeakHashMap<EventListener, Long>(); 42 private static final Map<Long, WeakReference<EventListener>> peer2EL = 43 new HashMap<Long, WeakReference<EventListener>>(); 44 45 private static final class SelfDisposer implements DisposerRecord { 46 private final long peer; 47 private SelfDisposer(final long peer) { 48 this.peer = peer; 49 } 50 public void dispose() { 51 //dispose JavaEL <-> JSstab connection (JavaEL die) 52 EventListenerImpl.dispose(peer); 53 EventListenerImpl.twkDisposeJSPeer(peer); 54 } 55 } 56 57 private final EventListener eventListener; 58 private final long jsPeer; 59 60 static long getPeer(EventListener eventListener) { 61 if (eventListener == null) { 62 return 0L; 63 } 64 65 Long peer = EL2peer.get(eventListener); 66 if (peer != null) { 67 return peer; 68 } 69 70 //[eventListener] is the Java EventListener. 71 EventListenerImpl eli = new EventListenerImpl(eventListener, 0L); 72 peer = eli.twkCreatePeer(); 73 EL2peer.put(eventListener, peer); 74 peer2EL.put(peer, new WeakReference<EventListener>(eventListener)); 75 76 return peer; 77 } 78 private native long twkCreatePeer(); 79 80 private static EventListener getELfromPeer(long peer) { 81 WeakReference<EventListener> wr = peer2EL.get(peer); 82 return wr == null ? null : wr.get(); 83 } 84 85 static EventListener getImpl(long peer) { 86 if (peer == 0) 87 return null; 88 89 EventListener ev = getELfromPeer(peer); 90 if (ev != null) { 91 // the peer need to be deref'ed! 92 twkDisposeJSPeer(peer); 93 return ev; 94 } 95 96 //[peer] is the JS EventListener. 97 EventListener el = new EventListenerImpl(null, peer); 98 EL2peer.put(el, peer); 99 peer2EL.put(peer, new WeakReference<EventListener>(el)); 100 Disposer.addRecord(el, new SelfDisposer(peer)); 101 102 return el; 103 } 104 105 public void handleEvent(Event evt) { 106 //call to JS peer if any 107 if (jsPeer != 0L && (evt instanceof EventImpl)) { 108 twkDispatchEvent(jsPeer, ((EventImpl)evt).getPeer() ); 109 } 110 } 111 private native static void twkDispatchEvent(long eventListenerPeer, long eventPeer); 112 113 private EventListenerImpl(EventListener eventListener, long jsPeer) { 114 this.eventListener = eventListener; 115 this.jsPeer = jsPeer; 116 } 117 118 //dispose JavaEL <-> JSstab connection (JSstab die) 119 private static void dispose(long peer) { 120 EventListener ev = getELfromPeer(peer); 121 if (ev != null ) 122 EL2peer.remove(ev); 123 peer2EL.remove(peer); 124 } 125 //dispose JSstab for JS-native EL 126 private native static void twkDisposeJSPeer(long peer); 127 128 private void fwkHandleEvent(long eventPeer) { 129 eventListener.handleEvent(EventImpl.getImpl(eventPeer)); 130 } 131 }