1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.observation;
35
36 import info.magnolia.context.LifeTimeJCRSessionUtil;
37
38 import javax.jcr.RepositoryException;
39 import javax.jcr.Session;
40 import javax.jcr.observation.Event;
41 import javax.jcr.observation.EventListener;
42 import javax.jcr.observation.EventListenerIterator;
43 import javax.jcr.observation.ObservationManager;
44
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 import com.google.common.base.Optional;
49 import com.google.common.base.Preconditions;
50 import com.google.common.base.Predicate;
51 import com.google.common.collect.Iterators;
52
53
54
55
56
57
58
59
60
61
62
63
64 public class WorkspaceEventListenerRegistration {
65
66 private static final int ALL_EVENT_TYPES_MASK = Event.NODE_ADDED | Event.NODE_REMOVED | Event.NODE_MOVED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED;
67
68 private static final Logger log = LoggerFactory.getLogger(WorkspaceEventListenerRegistration.class);
69
70 private WorkspaceEventListenerRegistration() {
71 }
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public static Registrar observe(final String workspace, final String observationPath, final EventListener eventListener) {
87 Preconditions.checkNotNull(workspace, "Workspace cannot be null.");
88 Preconditions.checkNotNull(observationPath, "Observation path cannot be null.");
89 Preconditions.checkNotNull(eventListener, "Event listener cannot be null.");
90 return new Registrar(workspace, observationPath, eventListener);
91 }
92
93 private static ObservationManager getObservationManager(final String workspace) throws RepositoryException {
94 final Session session = LifeTimeJCRSessionUtil.getSession(workspace);
95 return session.getWorkspace().getObservationManager();
96 }
97
98 @SuppressWarnings("unchecked")
99 private static boolean isAlreadyRegistered(final String workspace, final EventListener listener) throws RepositoryException {
100 EventListenerIterator iterator = getObservationManager(workspace).getRegisteredEventListeners();
101 Optional<EventListener> existingListener = Iterators.tryFind(iterator, new Predicate<EventListener>() {
102 @Override
103 public boolean apply(final EventListener input) {
104 return input.equals(listener);
105 }
106 });
107 return existingListener.isPresent();
108 }
109
110
111
112
113 public interface Handle {
114
115
116
117
118
119
120 void unregister() throws RepositoryException;
121 }
122
123
124
125
126 public static class Registrar {
127
128
129 private final String workspace;
130 private final String observationPath;
131 private EventListener eventListener;
132
133
134 private boolean includeSubNodes = true;
135 private String[] nodeTypes = null;
136 private int eventMasksType = ALL_EVENT_TYPES_MASK;
137 private Long delay = null;
138 private Long maxDelay = null;
139
140 private Registrar(final String workspace, final String observationPath, final EventListener eventListener) {
141 this.workspace = workspace;
142 this.observationPath = observationPath;
143 this.eventListener = eventListener;
144 }
145
146 public Registrar withSubNodes(final boolean includeSubNodes) {
147 this.includeSubNodes = includeSubNodes;
148 return this;
149 }
150
151 public Registrar withNodeTypes(final String... nodeTypes) {
152 this.nodeTypes = nodeTypes;
153 return this;
154 }
155
156 public Registrar withEventTypesMask(final int eventMasksType) {
157 this.eventMasksType = eventMasksType;
158 return this;
159 }
160
161 public Registrar withDelay(final Long delay, final Long maxDelay) {
162 this.delay = delay;
163 this.maxDelay = maxDelay;
164 return this;
165 }
166
167
168
169
170
171
172
173
174 public Handle register() throws RepositoryException {
175 if (!(eventListener instanceof DeferringEventListener) && delay != null && maxDelay != null) {
176 eventListener = new DeferringEventListener(eventListener, delay, maxDelay);
177 }
178 if (isAlreadyRegistered(workspace, eventListener)) {
179 throw new WorkspaceEventListenerRegistrationException("Listener has been already registered. If you want to register same listener multiple times, please create new instance of it.");
180 }
181
182 log.debug("Registering event listener for path [{}]", observationPath);
183
184 final ObservationManager observationManager = getObservationManager(workspace);
185 observationManager.addEventListener(eventListener, eventMasksType, observationPath, includeSubNodes, null, nodeTypes, false);
186
187 return new Handle() {
188 @Override
189 public void unregister() throws RepositoryException {
190 final ObservationManager om = getObservationManager(workspace);
191 om.removeEventListener(eventListener);
192 }
193 };
194 }
195
196 }
197
198
199
200
201 public static class WorkspaceEventListenerRegistrationException extends RuntimeException {
202
203 public WorkspaceEventListenerRegistrationException(String message) {
204 super(message);
205 }
206
207 }
208 }