blob: 18eaa991dcb76b9953d8918e2888ec311b8c1c71 [file] [log] [blame]
Richard S. Hall2532cf82010-03-24 09:51:11 +00001/*
Carsten Ziegeler3314f912014-07-30 07:22:32 +00002 * Copyright (c) OSGi Alliance (2007, 2013). All Rights Reserved.
Richard S. Hall2532cf82010-03-24 09:51:11 +00003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.osgi.util.tracker;
18
Richard S. Halld0dca9b2011-05-18 14:52:16 +000019import java.util.HashMap;
20import java.util.Map;
Richard S. Hall2532cf82010-03-24 09:51:11 +000021import org.osgi.framework.Bundle;
22import org.osgi.framework.BundleContext;
23import org.osgi.framework.BundleEvent;
24import org.osgi.framework.SynchronousBundleListener;
25
26/**
Richard S. Halldfd78a42012-05-11 20:19:02 +000027 * The {@code BundleTracker} class simplifies tracking bundles much like the
28 * {@code ServiceTracker} simplifies tracking services.
Richard S. Hall2532cf82010-03-24 09:51:11 +000029 * <p>
Richard S. Halld0dca9b2011-05-18 14:52:16 +000030 * A {@code BundleTracker} is constructed with state criteria and a
Richard S. Halldfd78a42012-05-11 20:19:02 +000031 * {@code BundleTrackerCustomizer} object. A {@code BundleTracker} can use the
32 * {@code BundleTrackerCustomizer} to select which bundles are tracked and to
33 * create a customized object to be tracked with the bundle. The
34 * {@code BundleTracker} can then be opened to begin tracking all bundles whose
35 * state matches the specified state criteria.
Richard S. Hall2532cf82010-03-24 09:51:11 +000036 * <p>
Richard S. Halldfd78a42012-05-11 20:19:02 +000037 * The {@code getBundles} method can be called to get the {@code Bundle} objects
38 * of the bundles being tracked. The {@code getObject} method can be called to
39 * get the customized object for a tracked bundle.
Richard S. Hall2532cf82010-03-24 09:51:11 +000040 * <p>
Richard S. Halld0dca9b2011-05-18 14:52:16 +000041 * The {@code BundleTracker} class is thread-safe. It does not call a
42 * {@code BundleTrackerCustomizer} while holding any locks.
Richard S. Halldfd78a42012-05-11 20:19:02 +000043 * {@code BundleTrackerCustomizer} implementations must also be thread-safe.
Richard S. Hall2532cf82010-03-24 09:51:11 +000044 *
Richard S. Halld0dca9b2011-05-18 14:52:16 +000045 * @param <T> The type of the tracked object.
Richard S. Hall2532cf82010-03-24 09:51:11 +000046 * @ThreadSafe
Carsten Ziegeler3314f912014-07-30 07:22:32 +000047 * @author $Id: 9a1b57568a8be735292700584f4eb936fc80f2ff $
Richard S. Hall2532cf82010-03-24 09:51:11 +000048 * @since 1.4
49 */
Richard S. Halld0dca9b2011-05-18 14:52:16 +000050public class BundleTracker<T> implements BundleTrackerCustomizer<T> {
Richard S. Hall2532cf82010-03-24 09:51:11 +000051 /* set this to true to compile in debug messages */
Richard S. Halld0dca9b2011-05-18 14:52:16 +000052 static final boolean DEBUG = false;
Richard S. Hall2532cf82010-03-24 09:51:11 +000053
54 /**
Richard S. Halld0dca9b2011-05-18 14:52:16 +000055 * The Bundle Context used by this {@code BundleTracker}.
Richard S. Hall2532cf82010-03-24 09:51:11 +000056 */
Richard S. Halld0dca9b2011-05-18 14:52:16 +000057 protected final BundleContext context;
Richard S. Hall2532cf82010-03-24 09:51:11 +000058
59 /**
Richard S. Halld0dca9b2011-05-18 14:52:16 +000060 * The {@code BundleTrackerCustomizer} object for this tracker.
Richard S. Hall2532cf82010-03-24 09:51:11 +000061 */
Richard S. Halld0dca9b2011-05-18 14:52:16 +000062 final BundleTrackerCustomizer<T> customizer;
Richard S. Hall2532cf82010-03-24 09:51:11 +000063
64 /**
Richard S. Halld0dca9b2011-05-18 14:52:16 +000065 * Tracked bundles: {@code Bundle} object -> customized Object and
66 * {@code BundleListener} object
Richard S. Hall2532cf82010-03-24 09:51:11 +000067 */
Richard S. Halld0dca9b2011-05-18 14:52:16 +000068 private volatile Tracked tracked;
Richard S. Hall2532cf82010-03-24 09:51:11 +000069
70 /**
71 * Accessor method for the current Tracked object. This method is only
72 * intended to be used by the unsynchronized methods which do not modify the
73 * tracked field.
74 *
75 * @return The current Tracked object.
76 */
77 private Tracked tracked() {
78 return tracked;
79 }
80
81 /**
82 * State mask for bundles being tracked. This field contains the ORed values
83 * of the bundle states being tracked.
84 */
Richard S. Halld0dca9b2011-05-18 14:52:16 +000085 final int mask;
Richard S. Hall2532cf82010-03-24 09:51:11 +000086
87 /**
Richard S. Halldfd78a42012-05-11 20:19:02 +000088 * Create a {@code BundleTracker} for bundles whose state is present in the
89 * specified state mask.
Richard S. Hall2532cf82010-03-24 09:51:11 +000090 *
91 * <p>
92 * Bundles whose state is present on the specified state mask will be
Richard S. Halld0dca9b2011-05-18 14:52:16 +000093 * tracked by this {@code BundleTracker}.
Richard S. Hall2532cf82010-03-24 09:51:11 +000094 *
Richard S. Halldfd78a42012-05-11 20:19:02 +000095 * @param context The {@code BundleContext} against which the tracking is
96 * done.
97 * @param stateMask The bit mask of the {@code OR}ing of the bundle states
98 * to be tracked.
Richard S. Hall2532cf82010-03-24 09:51:11 +000099 * @param customizer The customizer object to call when bundles are added,
Richard S. Halldfd78a42012-05-11 20:19:02 +0000100 * modified, or removed in this {@code BundleTracker}. If customizer
101 * is {@code null}, then this {@code BundleTracker} will be used as
102 * the {@code BundleTrackerCustomizer} and this {@code BundleTracker}
103 * will call the {@code BundleTrackerCustomizer} methods on itself.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000104 * @see Bundle#getState()
105 */
Richard S. Halldfd78a42012-05-11 20:19:02 +0000106 public BundleTracker(BundleContext context, int stateMask, BundleTrackerCustomizer<T> customizer) {
Richard S. Hall2532cf82010-03-24 09:51:11 +0000107 this.context = context;
108 this.mask = stateMask;
109 this.customizer = (customizer == null) ? this : customizer;
110 }
111
112 /**
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000113 * Open this {@code BundleTracker} and begin tracking bundles.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000114 *
115 * <p>
116 * Bundle which match the state criteria specified when this
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000117 * {@code BundleTracker} was created are now tracked by this
118 * {@code BundleTracker}.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000119 *
Richard S. Halldfd78a42012-05-11 20:19:02 +0000120 * @throws java.lang.IllegalStateException If the {@code BundleContext} with
121 * which this {@code BundleTracker} was created is no longer valid.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000122 * @throws java.lang.SecurityException If the caller and this class do not
123 * have the appropriate
Richard S. Halldfd78a42012-05-11 20:19:02 +0000124 * {@code AdminPermission[context bundle,LISTENER]}, and the Java
125 * Runtime Environment supports permissions.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000126 */
127 public void open() {
128 final Tracked t;
129 synchronized (this) {
130 if (tracked != null) {
131 return;
132 }
133 if (DEBUG) {
134 System.out.println("BundleTracker.open"); //$NON-NLS-1$
135 }
136 t = new Tracked();
137 synchronized (t) {
138 context.addBundleListener(t);
139 Bundle[] bundles = context.getBundles();
140 if (bundles != null) {
141 int length = bundles.length;
142 for (int i = 0; i < length; i++) {
143 int state = bundles[i].getState();
144 if ((state & mask) == 0) {
145 /* null out bundles whose states are not interesting */
146 bundles[i] = null;
147 }
148 }
149 /* set tracked with the initial bundles */
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000150 t.setInitial(bundles);
Richard S. Hall2532cf82010-03-24 09:51:11 +0000151 }
152 }
153 tracked = t;
154 }
155 /* Call tracked outside of synchronized region */
156 t.trackInitial(); /* process the initial references */
157 }
158
159 /**
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000160 * Close this {@code BundleTracker}.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000161 *
162 * <p>
Richard S. Halldfd78a42012-05-11 20:19:02 +0000163 * This method should be called when this {@code BundleTracker} should end
164 * the tracking of bundles.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000165 *
166 * <p>
167 * This implementation calls {@link #getBundles()} to get the list of
168 * tracked bundles to remove.
169 */
170 public void close() {
171 final Bundle[] bundles;
172 final Tracked outgoing;
173 synchronized (this) {
174 outgoing = tracked;
175 if (outgoing == null) {
176 return;
177 }
178 if (DEBUG) {
179 System.out.println("BundleTracker.close"); //$NON-NLS-1$
180 }
181 outgoing.close();
182 bundles = getBundles();
183 tracked = null;
184 try {
185 context.removeBundleListener(outgoing);
Richard S. Halldfd78a42012-05-11 20:19:02 +0000186 } catch (IllegalStateException e) {
Richard S. Hall2532cf82010-03-24 09:51:11 +0000187 /* In case the context was stopped. */
188 }
189 }
190 if (bundles != null) {
191 for (int i = 0; i < bundles.length; i++) {
192 outgoing.untrack(bundles[i], null);
193 }
194 }
195 }
196
197 /**
198 * Default implementation of the
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000199 * {@code BundleTrackerCustomizer.addingBundle} method.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000200 *
201 * <p>
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000202 * This method is only called when this {@code BundleTracker} has been
203 * constructed with a {@code null BundleTrackerCustomizer} argument.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000204 *
205 * <p>
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000206 * This implementation simply returns the specified {@code Bundle}.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000207 *
208 * <p>
209 * This method can be overridden in a subclass to customize the object to be
210 * tracked for the bundle being added.
211 *
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000212 * @param bundle The {@code Bundle} being added to this
213 * {@code BundleTracker} object.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000214 * @param event The bundle event which caused this customizer method to be
Richard S. Halldfd78a42012-05-11 20:19:02 +0000215 * called or {@code null} if there is no bundle event associated with
216 * the call to this method.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000217 * @return The specified bundle.
218 * @see BundleTrackerCustomizer#addingBundle(Bundle, BundleEvent)
219 */
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000220 public T addingBundle(Bundle bundle, BundleEvent event) {
Carsten Ziegeler3314f912014-07-30 07:22:32 +0000221 @SuppressWarnings("unchecked")
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000222 T result = (T) bundle;
223 return result;
Richard S. Hall2532cf82010-03-24 09:51:11 +0000224 }
225
226 /**
227 * Default implementation of the
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000228 * {@code BundleTrackerCustomizer.modifiedBundle} method.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000229 *
230 * <p>
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000231 * This method is only called when this {@code BundleTracker} has been
232 * constructed with a {@code null BundleTrackerCustomizer} argument.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000233 *
234 * <p>
235 * This implementation does nothing.
236 *
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000237 * @param bundle The {@code Bundle} whose state has been modified.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000238 * @param event The bundle event which caused this customizer method to be
Richard S. Halldfd78a42012-05-11 20:19:02 +0000239 * called or {@code null} if there is no bundle event associated with
240 * the call to this method.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000241 * @param object The customized object for the specified Bundle.
242 * @see BundleTrackerCustomizer#modifiedBundle(Bundle, BundleEvent, Object)
243 */
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000244 public void modifiedBundle(Bundle bundle, BundleEvent event, T object) {
Richard S. Hall2532cf82010-03-24 09:51:11 +0000245 /* do nothing */
246 }
247
248 /**
249 * Default implementation of the
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000250 * {@code BundleTrackerCustomizer.removedBundle} method.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000251 *
252 * <p>
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000253 * This method is only called when this {@code BundleTracker} has been
254 * constructed with a {@code null BundleTrackerCustomizer} argument.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000255 *
256 * <p>
257 * This implementation does nothing.
258 *
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000259 * @param bundle The {@code Bundle} being removed.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000260 * @param event The bundle event which caused this customizer method to be
Richard S. Halldfd78a42012-05-11 20:19:02 +0000261 * called or {@code null} if there is no bundle event associated with
262 * the call to this method.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000263 * @param object The customized object for the specified bundle.
264 * @see BundleTrackerCustomizer#removedBundle(Bundle, BundleEvent, Object)
265 */
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000266 public void removedBundle(Bundle bundle, BundleEvent event, T object) {
Richard S. Hall2532cf82010-03-24 09:51:11 +0000267 /* do nothing */
268 }
269
270 /**
Richard S. Halldfd78a42012-05-11 20:19:02 +0000271 * Return an array of {@code Bundle}s for all bundles being tracked by this
272 * {@code BundleTracker}.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000273 *
Richard S. Halldfd78a42012-05-11 20:19:02 +0000274 * @return An array of {@code Bundle}s or {@code null} if no bundles are
275 * being tracked.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000276 */
277 public Bundle[] getBundles() {
278 final Tracked t = tracked();
279 if (t == null) { /* if BundleTracker is not open */
280 return null;
281 }
282 synchronized (t) {
283 int length = t.size();
284 if (length == 0) {
285 return null;
286 }
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000287 return t.copyKeys(new Bundle[length]);
Richard S. Hall2532cf82010-03-24 09:51:11 +0000288 }
289 }
290
291 /**
Richard S. Halldfd78a42012-05-11 20:19:02 +0000292 * Returns the customized object for the specified {@code Bundle} if the
293 * specified bundle is being tracked by this {@code BundleTracker}.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000294 *
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000295 * @param bundle The {@code Bundle} being tracked.
296 * @return The customized object for the specified {@code Bundle} or
Richard S. Halldfd78a42012-05-11 20:19:02 +0000297 * {@code null} if the specified {@code Bundle} is not being
298 * tracked.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000299 */
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000300 public T getObject(Bundle bundle) {
Richard S. Hall2532cf82010-03-24 09:51:11 +0000301 final Tracked t = tracked();
302 if (t == null) { /* if BundleTracker is not open */
303 return null;
304 }
305 synchronized (t) {
306 return t.getCustomizedObject(bundle);
307 }
308 }
309
310 /**
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000311 * Remove a bundle from this {@code BundleTracker}.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000312 *
Richard S. Halldfd78a42012-05-11 20:19:02 +0000313 * The specified bundle will be removed from this {@code BundleTracker} . If
314 * the specified bundle was being tracked then the
315 * {@code BundleTrackerCustomizer.removedBundle} method will be called for
316 * that bundle.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000317 *
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000318 * @param bundle The {@code Bundle} to be removed.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000319 */
320 public void remove(Bundle bundle) {
321 final Tracked t = tracked();
322 if (t == null) { /* if BundleTracker is not open */
323 return;
324 }
325 t.untrack(bundle, null);
326 }
327
328 /**
Richard S. Halldfd78a42012-05-11 20:19:02 +0000329 * Return the number of bundles being tracked by this {@code BundleTracker}.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000330 *
331 * @return The number of bundles being tracked.
332 */
333 public int size() {
334 final Tracked t = tracked();
335 if (t == null) { /* if BundleTracker is not open */
336 return 0;
337 }
338 synchronized (t) {
339 return t.size();
340 }
341 }
342
343 /**
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000344 * Returns the tracking count for this {@code BundleTracker}.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000345 *
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000346 * The tracking count is initialized to 0 when this {@code BundleTracker} is
347 * opened. Every time a bundle is added, modified or removed from this
348 * {@code BundleTracker} the tracking count is incremented.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000349 *
350 * <p>
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000351 * The tracking count can be used to determine if this {@code BundleTracker}
352 * has added, modified or removed a bundle by comparing a tracking count
353 * value previously collected with the current tracking count value. If the
354 * value has not changed, then no bundle has been added, modified or removed
355 * from this {@code BundleTracker} since the previous tracking count was
356 * collected.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000357 *
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000358 * @return The tracking count for this {@code BundleTracker} or -1 if this
359 * {@code BundleTracker} is not open.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000360 */
361 public int getTrackingCount() {
362 final Tracked t = tracked();
363 if (t == null) { /* if BundleTracker is not open */
364 return -1;
365 }
366 synchronized (t) {
367 return t.getTrackingCount();
368 }
369 }
370
371 /**
Richard S. Halldfd78a42012-05-11 20:19:02 +0000372 * Return a {@code Map} with the {@code Bundle}s and customized objects for
373 * all bundles being tracked by this {@code BundleTracker}.
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000374 *
Richard S. Halldfd78a42012-05-11 20:19:02 +0000375 * @return A {@code Map} with the {@code Bundle}s and customized objects for
376 * all services being tracked by this {@code BundleTracker}. If no
377 * bundles are being tracked, then the returned map is empty.
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000378 * @since 1.5
379 */
380 public Map<Bundle, T> getTracked() {
381 Map<Bundle, T> map = new HashMap<Bundle, T>();
382 final Tracked t = tracked();
383 if (t == null) { /* if BundleTracker is not open */
384 return map;
385 }
386 synchronized (t) {
387 return t.copyEntries(map);
388 }
389 }
390
391 /**
392 * Return if this {@code BundleTracker} is empty.
393 *
394 * @return {@code true} if this {@code BundleTracker} is not tracking any
395 * bundles.
396 * @since 1.5
397 */
398 public boolean isEmpty() {
399 final Tracked t = tracked();
400 if (t == null) { /* if BundleTracker is not open */
401 return true;
402 }
403 synchronized (t) {
404 return t.isEmpty();
405 }
406 }
407
408 /**
Richard S. Hall2532cf82010-03-24 09:51:11 +0000409 * Inner class which subclasses AbstractTracked. This class is the
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000410 * {@code SynchronousBundleListener} object for the tracker.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000411 *
412 * @ThreadSafe
413 * @since 1.4
414 */
Richard S. Halldfd78a42012-05-11 20:19:02 +0000415 private final class Tracked extends AbstractTracked<Bundle, T, BundleEvent> implements SynchronousBundleListener {
Richard S. Hall2532cf82010-03-24 09:51:11 +0000416 /**
417 * Tracked constructor.
418 */
419 Tracked() {
420 super();
421 }
422
423 /**
Richard S. Halldfd78a42012-05-11 20:19:02 +0000424 * {@code BundleListener} method for the {@code BundleTracker} class.
425 * This method must NOT be synchronized to avoid deadlock potential.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000426 *
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000427 * @param event {@code BundleEvent} object from the framework.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000428 */
429 public void bundleChanged(final BundleEvent event) {
430 /*
431 * Check if we had a delayed call (which could happen when we
432 * close).
433 */
434 if (closed) {
435 return;
436 }
437 final Bundle bundle = event.getBundle();
438 final int state = bundle.getState();
439 if (DEBUG) {
Richard S. Halldfd78a42012-05-11 20:19:02 +0000440 System.out.println("BundleTracker.Tracked.bundleChanged[" + state + "]: " + bundle); //$NON-NLS-1$ //$NON-NLS-2$
Richard S. Hall2532cf82010-03-24 09:51:11 +0000441 }
442
443 if ((state & mask) != 0) {
444 track(bundle, event);
445 /*
446 * If the customizer throws an unchecked exception, it is safe
447 * to let it propagate
448 */
Richard S. Halldfd78a42012-05-11 20:19:02 +0000449 } else {
Richard S. Hall2532cf82010-03-24 09:51:11 +0000450 untrack(bundle, event);
451 /*
452 * If the customizer throws an unchecked exception, it is safe
453 * to let it propagate
454 */
455 }
456 }
457
458 /**
459 * Call the specific customizer adding method. This method must not be
460 * called while synchronized on this object.
461 *
462 * @param item Item to be tracked.
463 * @param related Action related object.
Richard S. Halldfd78a42012-05-11 20:19:02 +0000464 * @return Customized object for the tracked item or {@code null} if the
465 * item is not to be tracked.
Richard S. Hall2532cf82010-03-24 09:51:11 +0000466 */
Carsten Ziegeler3314f912014-07-30 07:22:32 +0000467 @Override
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000468 T customizerAdding(final Bundle item, final BundleEvent related) {
469 return customizer.addingBundle(item, related);
Richard S. Hall2532cf82010-03-24 09:51:11 +0000470 }
471
472 /**
473 * Call the specific customizer modified method. This method must not be
474 * called while synchronized on this object.
475 *
476 * @param item Tracked item.
477 * @param related Action related object.
478 * @param object Customized object for the tracked item.
479 */
Carsten Ziegeler3314f912014-07-30 07:22:32 +0000480 @Override
Richard S. Halldfd78a42012-05-11 20:19:02 +0000481 void customizerModified(final Bundle item, final BundleEvent related, final T object) {
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000482 customizer.modifiedBundle(item, related, object);
Richard S. Hall2532cf82010-03-24 09:51:11 +0000483 }
484
485 /**
486 * Call the specific customizer removed method. This method must not be
487 * called while synchronized on this object.
488 *
489 * @param item Tracked item.
490 * @param related Action related object.
491 * @param object Customized object for the tracked item.
492 */
Carsten Ziegeler3314f912014-07-30 07:22:32 +0000493 @Override
Richard S. Halldfd78a42012-05-11 20:19:02 +0000494 void customizerRemoved(final Bundle item, final BundleEvent related, final T object) {
Richard S. Halld0dca9b2011-05-18 14:52:16 +0000495 customizer.removedBundle(item, related, object);
Richard S. Hall2532cf82010-03-24 09:51:11 +0000496 }
497 }
498}