📄 wikieventmanager.java
字号:
// the entry value is the delegate WikiEventDelegate delegate = (WikiEventDelegate)entry.getValue(); // now see if we can remove the listener from the delegate // (delegate may be null because this is a weak reference) if( delegate != null && delegate.removeWikiEventListener(listener) ) { return true; // was removed } } } return false; } /** * Returns true if there are one or more listeners registered with * the provided client Object (undelegated event source). This locates * any delegate and checks to see if it has any listeners attached. * * @param client the client Object * @return True, if there is a listener for this client object. */ public static boolean isListening( Object client ) { WikiEventDelegate source = getInstance().getDelegateFor(client); return source != null ? source.isListening() : false ; } /** * Notify all listeners of the WikiEventDelegate having a registered * interest in change events of the supplied WikiEvent. * * @param client the client initiating the event. * @param event the WikiEvent to fire. */ public static void fireEvent( Object client, WikiEvent event ) { WikiEventDelegate source = getInstance().getDelegateFor(client); if ( source != null ) source.fireEvent(event); if ( c_monitor != null ) c_monitor.actionPerformed(event); } // private and utility methods ............................................. /** * Return the client-to-delegate Map. */ private Map getDelegates() { return m_delegates; } /** * Returns a WikiEventDelegate for the provided client Object. * If the parameter is a class reference, will generate and return a * client-less WikiEventDelegate. If the parameter is not a Class and * the delegate cache contains any objects matching the Class of any * delegates in the cache, the first Class-matching delegate will be * used in preference to creating a new delegate. * If a null parameter is supplied, this will create a client-less * delegate that will attach to the first incoming client (i.e., * there will be no Class-matching requirement). * * @param client the client Object, or alternately a Class reference * @return the WikiEventDelegate. */ private WikiEventDelegate getDelegateFor( Object client ) { synchronized( m_delegates ) { if( client == null || client instanceof Class ) // then preload the cache { WikiEventDelegate delegate = new WikiEventDelegate(client); m_preloadCache.add(delegate); m_delegates.put( client, delegate ); return delegate; } else if( !m_preloadCache.isEmpty() ) { // then see if any of the cached delegates match the class of the incoming client for( int i = m_preloadCache.size()-1 ; i >= 0 ; i-- ) // start with most-recently added { WikiEventDelegate delegate = m_preloadCache.elementAt(i); if( delegate.getClientClass() == null || delegate.getClientClass().equals(client.getClass()) ) { // we have a hit, so use it, but only on a client we haven't seen before if( !m_delegates.keySet().contains(client) ) { m_preloadCache.remove(delegate); m_delegates.put( client, delegate ); return delegate; } } } } // otherwise treat normally... WikiEventDelegate delegate = m_delegates.get( client ); if( delegate == null ) { delegate = new WikiEventDelegate( client ); m_delegates.put( client, delegate ); } return delegate; } } // ......................................................................... /** * Inner delegating class that manages event listener addition and * removal. Classes that generate events can obtain an instance of * this class from the WikiEventManager and delegate responsibility * to it. Interaction with this delegating class is done via the * methods of the {@link WikiEventDelegate} API. * * @author Murray Altheim * @since 2.4.20 */ private static final class WikiEventDelegate { /* A list of event listeners for this instance. */ private ArrayList<WeakReference<WikiEventListener>> m_listenerList = new ArrayList<WeakReference<WikiEventListener>>(); private Class m_class = null; /** * Constructor for an WikiEventDelegateImpl, provided * with the client Object it will service, or the Class * of client, the latter when used to preload a future * incoming delegate. */ protected WikiEventDelegate( Object client ) { if( client instanceof Class ) { m_class = (Class)client; } } /** * Returns the class of the client-less delegate, null if * this delegate is attached to a client Object. */ protected Class getClientClass() { return m_class; } /** * Return an unmodifiable Set containing the WikiEventListeners of * this WikiEventDelegateImpl. If there are no attached listeners, * returns an empty Set rather than null. * * @return an unmodifiable Set containing this delegate's WikiEventListeners * @throws java.lang.UnsupportedOperationException if any attempt is made to modify the Set */ public Set getWikiEventListeners() { synchronized( m_listenerList ) { TreeSet<WikiEventListener> set = new TreeSet<WikiEventListener>( new WikiEventListenerComparator() ); for( Iterator i = m_listenerList.iterator(); i.hasNext(); ) { WikiEventListener l = (WikiEventListener) ((WeakReference)i.next()).get(); if( l != null ) { set.add( l ); } } return Collections.unmodifiableSet(set); } } /** * Adds <tt>listener</tt> as a listener for events fired by the WikiEventDelegate. * * @param listener the WikiEventListener to be added * @return true if the listener was added (i.e., it was not already in the list and was added) */ public boolean addWikiEventListener( WikiEventListener listener ) { synchronized( m_listenerList ) { return m_listenerList.add( new WeakReference<WikiEventListener>(listener) ); } } /** * Removes <tt>listener</tt> from the WikiEventDelegate. * * @param listener the WikiEventListener to be removed * @return true if the listener was removed (i.e., it was actually in the list and was removed) */ public boolean removeWikiEventListener( WikiEventListener listener ) { synchronized( m_listenerList ) { for( Iterator i = m_listenerList.iterator(); i.hasNext(); ) { WikiEventListener l = (WikiEventListener) ((WeakReference)i.next()).get(); if( l == listener ) { i.remove(); return true; } } } return false; } /** * Returns true if there are one or more listeners registered * with this instance. */ public boolean isListening() { synchronized( m_listenerList ) { return !m_listenerList.isEmpty(); } } /** * Notify all listeners having a registered interest * in change events of the supplied WikiEvent. */ public void fireEvent( WikiEvent event ) { boolean needsCleanup = false; try { synchronized( m_listenerList ) { for( int i = 0; i < m_listenerList.size(); i++ ) { WikiEventListener listener = (WikiEventListener) ((WeakReference)m_listenerList.get(i)).get(); if( listener != null ) { listener.actionPerformed( event ); } else { needsCleanup = true; } } // // Remove all such listeners which have expired // if( needsCleanup ) { for( int i = 0; i < m_listenerList.size(); i++ ) { WeakReference w = m_listenerList.get(i); if( w.get() == null ) m_listenerList.remove(i--); } } } } catch( ConcurrentModificationException e ) { // // We don't die, we just don't do notifications in that case. // log.info("Concurrent modification of event list; please report this.",e); } } } // end inner class WikiEventDelegate private static class WikiEventListenerComparator implements Comparator<WikiEventListener> { // TODO: This method is a critical performance bottleneck public int compare(WikiEventListener w0, WikiEventListener w1) { if( w1 == w0 || w0.equals(w1) ) return 0; return w1.hashCode() - w0.hashCode(); } }} // end com.ecyrd.jspwiki.event.WikiEventManager
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -