Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 3459242886c4589d9f7162790c3b188eedbf417a (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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
/*******************************************************************************
 * Copyright (c) 2003, 2008 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.osgi.internal.serviceregistry;

import org.osgi.framework.*;

/**
 * A reference to a service.
 * 
 * <p>
 * The Framework returns <code>ServiceReference</code> objects from the
 * <code>BundleContext.getServiceReference</code> and
 * <code>BundleContext.getServiceReferences</code> methods.
 * <p>
 * A <code>ServiceReference</code> object may be shared between bundles and
 * can be used to examine the properties of the service and to get the service
 * object.
 * <p>
 * Every service registered in the Framework has a unique
 * <code>ServiceRegistration</code> object and may have multiple, distinct
 * <code>ServiceReference</code> objects referring to it.
 * <code>ServiceReference</code> objects associated with a
 * <code>ServiceRegistration</code> object have the same <code>hashCode</code>
 * and are considered equal (more specifically, their <code>equals()</code>
 * method will return <code>true</code> when compared).
 * <p>
 * If the same service object is registered multiple times,
 * <code>ServiceReference</code> objects associated with different
 * <code>ServiceRegistration</code> objects are not equal.
 * 
 * @see BundleContext#getServiceReference
 * @see BundleContext#getServiceReferences
 * @see BundleContext#getService
 * @ThreadSafe
 */
public class ServiceReferenceImpl implements ServiceReference, Comparable {
	/** Registered Service object. */
	private final ServiceRegistrationImpl registration;

	/**
	 * Construct a reference.
	 *
	 */
	ServiceReferenceImpl(ServiceRegistrationImpl registration) {
		this.registration = registration;
		/* We must not dereference registration in the constructor
		 * since it is "leaked" to us in the ServiceRegistrationImpl
		 * constructor.
		 */
	}

	/**
	 * Returns the property value to which the specified property key is mapped
	 * in the properties <code>Dictionary</code> object of the service
	 * referenced by this <code>ServiceReference</code> object.
	 * 
	 * <p>
	 * Property keys are case-insensitive.
	 * 
	 * <p>
	 * This method must continue to return property values after the service has
	 * been unregistered. This is so references to unregistered services (for
	 * example, <code>ServiceReference</code> objects stored in the log) can
	 * still be interrogated.
	 * 
	 * @param key The property key.
	 * @return The property value to which the key is mapped; <code>null</code>
	 *         if there is no property named after the key.
	 */
	public Object getProperty(String key) {
		return registration.getProperty(key);
	}

	/**
	 * Returns an array of the keys in the properties <code>Dictionary</code>
	 * object of the service referenced by this <code>ServiceReference</code>
	 * object.
	 * 
	 * <p>
	 * This method will continue to return the keys after the service has been
	 * unregistered. This is so references to unregistered services (for
	 * example, <code>ServiceReference</code> objects stored in the log) can
	 * still be interrogated.
	 * 
	 * <p>
	 * This method is <i>case-preserving </i>; this means that every key in the
	 * returned array must have the same case as the corresponding key in the
	 * properties <code>Dictionary</code> that was passed to the
	 * {@link BundleContext#registerService(String[],Object,java.util.Dictionary)}
	 * or {@link ServiceRegistration#setProperties} methods.
	 * 
	 * @return An array of property keys.
	 */
	public String[] getPropertyKeys() {
		return registration.getPropertyKeys();
	}

	/**
	 * Returns the bundle that registered the service referenced by this
	 * <code>ServiceReference</code> object.
	 * 
	 * <p>
	 * This method must return <code>null</code> when the service has been
	 * unregistered. This can be used to determine if the service has been
	 * unregistered.
	 * 
	 * @return The bundle that registered the service referenced by this
	 *         <code>ServiceReference</code> object; <code>null</code> if
	 *         that service has already been unregistered.
	 * @see BundleContext#registerService(String[],Object,java.util.Dictionary)
	 */
	public Bundle getBundle() {
		return registration.getBundle();
	}

	/**
	 * Returns the bundles that are using the service referenced by this
	 * <code>ServiceReference</code> object. Specifically, this method returns
	 * the bundles whose usage count for that service is greater than zero.
	 * 
	 * @return An array of bundles whose usage count for the service referenced
	 *         by this <code>ServiceReference</code> object is greater than
	 *         zero; <code>null</code> if no bundles are currently using that
	 *         service.
	 * 
	 * @since 1.1
	 */
	public Bundle[] getUsingBundles() {
		return registration.getUsingBundles();
	}

	/**
	 * Tests if the bundle that registered the service referenced by this
	 * <code>ServiceReference</code> and the specified bundle use the same
	 * source for the package of the specified class name.
	 * <p>
	 * This method performs the following checks:
	 * <ol>
	 * <li>Get the package name from the specified class name.</li>
	 * <li>For the bundle that registered the service referenced by this
	 * <code>ServiceReference</code> (registrant bundle); find the source for
	 * the package. If no source is found then return <code>true</code> if the
	 * registrant bundle is equal to the specified bundle; otherwise return
	 * <code>false</code>.</li>
	 * <li>If the package source of the registrant bundle is equal to the
	 * package source of the specified bundle then return <code>true</code>;
	 * otherwise return <code>false</code>.</li>
	 * </ol>
	 * 
	 * @param bundle The <code>Bundle</code> object to check.
	 * @param className The class name to check.
	 * @return <code>true</code> if the bundle which registered the service
	 *         referenced by this <code>ServiceReference</code> and the
	 *         specified bundle use the same source for the package of the
	 *         specified class name. Otherwise <code>false</code> is returned.
	 * 
	 * @since 1.3
	 */
	public boolean isAssignableTo(Bundle bundle, String className) {
		return registration.isAssignableTo(bundle, className);
	}

	/**
	 * Compares this <code>ServiceReference</code> with the specified
	 * <code>ServiceReference</code> for order.
	 * 
	 * <p>
	 * If this <code>ServiceReference</code> and the specified
	 * <code>ServiceReference</code> have the same
	 * {@link Constants#SERVICE_ID service id} they are equal. This
	 * <code>ServiceReference</code> is less than the specified
	 * <code>ServiceReference</code> if it has a lower
	 * {@link Constants#SERVICE_RANKING service ranking} and greater if it has a
	 * higher service ranking. Otherwise, if this <code>ServiceReference</code>
	 * and the specified <code>ServiceReference</code> have the same
	 * {@link Constants#SERVICE_RANKING service ranking}, this
	 * <code>ServiceReference</code> is less than the specified
	 * <code>ServiceReference</code> if it has a higher
	 * {@link Constants#SERVICE_ID service id} and greater if it has a lower
	 * service id.
	 * 
	 * @param object The <code>ServiceReference</code> to be compared.
	 * @return Returns a negative integer, zero, or a positive integer if this
	 *         <code>ServiceReference</code> is less than, equal to, or
	 *         greater than the specified <code>ServiceReference</code>.
	 * @since 1.4
	 */
	public int compareTo(Object object) {
		ServiceReferenceImpl other = (ServiceReferenceImpl) object;
		return registration.compareTo(other.registration);
	}

	/**
	 * Returns a hash code value for the object.
	 *
	 * @return  a hash code value for this object.
	 */
	public int hashCode() {
		return registration.hashCode();
	}

	/**
	 * Indicates whether some other object is "equal to" this one.
	 *
	 * @param   obj   the reference object with which to compare.
	 * @return  <code>true</code> if this object is the same as the obj
	 *          argument; <code>false</code> otherwise.
	 */
	public boolean equals(Object obj) {
		if (obj == this) {
			return true;
		}

		if (!(obj instanceof ServiceReferenceImpl)) {
			return false;
		}

		ServiceReferenceImpl other = (ServiceReferenceImpl) obj;

		return registration == other.registration;
	}

	/**
	 * Return a string representation of this reference.
	 *
	 * @return String
	 */
	public String toString() {
		return registration.toString();
	}

	/**
	 * Return the ServiceRegistrationImpl for this ServiceReferenceImpl.
	 * 
	 * @return The ServiceRegistrationImpl for this ServiceReferenceImpl.
	 */
	public ServiceRegistrationImpl getRegistration() {
		return registration;
	}

	/**
	 * Return the classes under which the referenced service was registered.
	 *
	 * @return array of class names.
	 */
	String[] getClasses() {
		return registration.getClasses();
	}
}

Back to the top