View Javadoc
1   /*
2    * Copyright (C) 2010, Google Inc. and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  
11  package org.eclipse.jgit.events;
12  
13  import java.util.List;
14  import java.util.concurrent.ConcurrentHashMap;
15  import java.util.concurrent.ConcurrentMap;
16  import java.util.concurrent.CopyOnWriteArrayList;
17  
18  /**
19   * Manages a thread-safe list of {@link org.eclipse.jgit.events.RepositoryListener}s.
20   */
21  public class ListenerList {
22  	private final ConcurrentMap<Class<? extends RepositoryListener>, CopyOnWriteArrayList<ListenerHandle>> lists = new ConcurrentHashMap<>();
23  
24  	/**
25  	 * Register a {@link org.eclipse.jgit.events.WorkingTreeModifiedListener}.
26  	 *
27  	 * @param listener
28  	 *            the listener implementation.
29  	 * @return handle to later remove the listener.
30  	 * @since 4.9
31  	 */
32  	public ListenerHandle addWorkingTreeModifiedListener(
33  			WorkingTreeModifiedListener listener) {
34  		return addListener(WorkingTreeModifiedListener.class, listener);
35  	}
36  
37  	/**
38  	 * Register an IndexChangedListener.
39  	 *
40  	 * @param listener
41  	 *            the listener implementation.
42  	 * @return handle to later remove the listener.
43  	 */
44  	public ListenerHandle addIndexChangedListener(IndexChangedListener listener) {
45  		return addListener(IndexChangedListener.class, listener);
46  	}
47  
48  	/**
49  	 * Register a RefsChangedListener.
50  	 *
51  	 * @param listener
52  	 *            the listener implementation.
53  	 * @return handle to later remove the listener.
54  	 */
55  	public ListenerHandle addRefsChangedListener(RefsChangedListener listener) {
56  		return addListener(RefsChangedListener.class, listener);
57  	}
58  
59  	/**
60  	 * Register a ConfigChangedListener.
61  	 *
62  	 * @param listener
63  	 *            the listener implementation.
64  	 * @return handle to later remove the listener.
65  	 */
66  	public ListenerHandle addConfigChangedListener(
67  			ConfigChangedListener listener) {
68  		return addListener(ConfigChangedListener.class, listener);
69  	}
70  
71  	/**
72  	 * Add a listener to the list.
73  	 *
74  	 * @param type
75  	 *            type of listener being registered.
76  	 * @param listener
77  	 *            the listener instance.
78  	 * @return a handle to later remove the registration, if desired.
79  	 */
80  	public <T extends RepositoryListener> ListenerHandle addListener(
81  			Class<T> type, T listener) {
82  		ListenerHandle handle = new ListenerHandle(this, type, listener);
83  		add(handle);
84  		return handle;
85  	}
86  
87  	/**
88  	 * Dispatch an event to all interested listeners.
89  	 * <p>
90  	 * Listeners are selected by the type of listener the event delivers to.
91  	 *
92  	 * @param event
93  	 *            the event to deliver.
94  	 */
95  	@SuppressWarnings("unchecked")
96  	public void dispatch(RepositoryEvent event) {
97  		List<ListenerHandle> list = lists.get(event.getListenerType());
98  		if (list != null) {
99  			for (ListenerHandle handle : list)
100 				event.dispatch(handle.listener);
101 		}
102 	}
103 
104 	private void add(ListenerHandle handle) {
105 		List<ListenerHandle> list = lists.get(handle.type);
106 		if (list == null) {
107 			CopyOnWriteArrayList<ListenerHandle> newList;
108 
109 			newList = new CopyOnWriteArrayList<>();
110 			list = lists.putIfAbsent(handle.type, newList);
111 			if (list == null)
112 				list = newList;
113 		}
114 		list.add(handle);
115 	}
116 
117 	void remove(ListenerHandle handle) {
118 		List<ListenerHandle> list = lists.get(handle.type);
119 		if (list != null)
120 			list.remove(handle);
121 	}
122 }