aboutsummaryrefslogtreecommitdiffstats
blob: 4740d5058446bc46d7998c027410f8a42f930244 (plain) (blame)
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/*******************************************************************************
 * This file is part of the Virgo Web Server.
 *
 * Copyright (c) 2010 Eclipse Foundation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    SpringSource, a division of VMware - initial API and implementation and/or initial documentation
 *******************************************************************************/

package org.eclipse.virgo.kernel.core.internal;

import java.util.HashSet;
import java.util.Set;

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;


/**
 * Utility class that tracks a set of {@link ServiceReference}s for a bundle and allows them to be safely
 * ungotten.
 * <p/>
 * <code>ServiceReferences</code> are tracked in a thread-safe manner, and are ungotten without
 * holding any locks.
 * 
 * @see ServiceReference
 */
class ServiceReferenceTracker {
    
    private final BundleContext context;
    
    private final Object monitor = new Object();

    private Set<ServiceReference> references; // protected by monitor.

    
    ServiceReferenceTracker(BundleContext context) {
        this.context = context;
    }
    
    /**
     * Tracks the supplied {@link ServiceReference}. This <code>ServiceReference</code> will be
     * {@link ServiceReference#unget ungotten} during {@link #ungetAll()}.
     * 
     * @param reference the <code>ServiceReference</code> to track.
     * @return the reference itself
     */
    public ServiceReference track(ServiceReference reference) {
        synchronized (this.monitor) {
            if (this.references == null) {
                this.references = new HashSet<ServiceReference>();
            }
            this.references.add(reference);
        }
        return reference;
    }

    /**
     * Safely unregisters all the tracked <code>ServiceRegistrations</code>.
     */
    public void ungetAll() {
        Set<ServiceReference> toUnget = null;
        synchronized (this.monitor) {
            toUnget = this.references;
            this.references = null;
        }
        if (toUnget != null) {
            for (ServiceReference serviceReference : toUnget) {
                try {
                    this.context.ungetService(serviceReference);
                } catch (IllegalStateException e) {
                }
            }
        }
    }
}