KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > framework > internal > core > ServiceUse


1 /*******************************************************************************
2  * Copyright (c) 2003, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.osgi.framework.internal.core;
13
14 import java.security.AccessController JavaDoc;
15 import java.security.PrivilegedAction JavaDoc;
16 import org.eclipse.osgi.framework.debug.Debug;
17 import org.eclipse.osgi.util.NLS;
18 import org.osgi.framework.*;
19
20 /**
21  * This class represents the use of a service by a bundle. One is created for each
22  * service acquired by a bundle. This class manages the calls to ServiceFactory
23  * and the bundle's use count.
24  */

25
26 public class ServiceUse {
27     /** ServiceFactory object if the service instance represents a factory,
28      null otherwise */

29     protected ServiceFactory factory;
30     /** Service object either registered or that returned by
31      ServiceFactory.getService() */

32     protected Object JavaDoc service;
33     /** BundleContext associated with this service use */
34     protected BundleContextImpl context;
35     /** ServiceDescription of the registered service */
36     protected ServiceRegistrationImpl registration;
37     /** bundle's use count for this service */
38     protected int useCount;
39
40     /** Internal framework object. */
41
42     /**
43      * Constructs a service use encapsulating the service object.
44      * Objects of this class should be constrcuted while holding the
45      * registrations lock.
46      *
47      * @param context bundle getting the service
48      * @param registration ServiceRegistration of the service
49      */

50     protected ServiceUse(BundleContextImpl context, ServiceRegistrationImpl registration) {
51         this.context = context;
52         this.registration = registration;
53         this.useCount = 0;
54
55         Object JavaDoc service = registration.service;
56         if (service instanceof ServiceFactory) {
57             factory = (ServiceFactory) service;
58             this.service = null;
59         } else {
60             this.factory = null;
61             this.service = service;
62         }
63     }
64
65     /**
66      * Get a service's service object.
67      * Retrieves the service object for a service.
68      * A bundle's use of a service is tracked by a
69      * use count. Each time a service's service object is returned by
70      * {@link #getService}, the context bundle's use count for the service
71      * is incremented by one. Each time the service is release by
72      * {@link #ungetService}, the context bundle's use count
73      * for the service is decremented by one.
74      * When a bundle's use count for a service
75      * drops to zero, the bundle should no longer use the service.
76      *
77      * <p>The following steps are followed to get the service object:
78      * <ol>
79      * <li>The context bundle's use count for this service is incremented by one.
80      * <li>If the context bundle's use count for the service is now one and
81      * the service was registered with a {@link ServiceFactory},
82      * the {@link ServiceFactory#getService ServiceFactory.getService} method
83      * is called to create a service object for the context bundle.
84      * This service object is cached by the framework.
85      * While the context bundle's use count for the service is greater than zero,
86      * subsequent calls to get the services's service object for the context bundle
87      * will return the cached service object.
88      * <br>If the service object returned by the {@link ServiceFactory}
89      * is not an <code>instanceof</code>
90      * all the classes named when the service was registered or
91      * the {@link ServiceFactory} throws an exception,
92      * <code>null</code> is returned and a
93      * {@link FrameworkEvent} of type {@link FrameworkEvent#ERROR} is broadcast.
94      * <li>The service object for the service is returned.
95      * </ol>
96      *
97      * @return A service object for the service associated with this
98      * reference.
99      */

100     protected Object JavaDoc getService() {
101         if ((useCount == 0) && (factory != null)) {
102             AbstractBundle factorybundle = registration.context.bundle;
103             Object JavaDoc service;
104
105             try {
106                 service = AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
107                     public Object JavaDoc run() {
108                         return factory.getService(context.bundle, registration);
109                     }
110                 });
111             } catch (Throwable JavaDoc t) {
112                 if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
113                     Debug.println(factory + ".getService() exception: " + t.getMessage()); //$NON-NLS-1$
114
Debug.printStackTrace(t);
115                 }
116                 // allow the adaptor to handle this unexpected error
117
context.framework.adaptor.handleRuntimeError(t);
118                 BundleException be = new BundleException(NLS.bind(Msg.SERVICE_FACTORY_EXCEPTION, factory.getClass().getName(), "getService"), t); //$NON-NLS-1$
119
context.framework.publishFrameworkEvent(FrameworkEvent.ERROR, factorybundle, be);
120                 return (null);
121             }
122
123             if (service == null) {
124                 if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
125                     Debug.println(factory + ".getService() returned null."); //$NON-NLS-1$
126
}
127
128                 BundleException be = new BundleException(NLS.bind(Msg.SERVICE_OBJECT_NULL_EXCEPTION, factory.getClass().getName()));
129                 context.framework.publishFrameworkEvent(FrameworkEvent.ERROR, factorybundle, be);
130
131                 return (null);
132             }
133
134             String JavaDoc[] clazzes = registration.clazzes;
135             String JavaDoc invalidService = BundleContextImpl.checkServiceClass(clazzes, service);
136             if (invalidService != null) {
137                 if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
138                     Debug.println("Service object is not an instanceof " + invalidService); //$NON-NLS-1$
139
}
140                 throw new IllegalArgumentException JavaDoc(NLS.bind(Msg.SERVICE_NOT_INSTANCEOF_CLASS_EXCEPTION, invalidService));
141             }
142             this.service = service;
143         }
144
145         useCount++;
146
147         return (this.service);
148     }
149
150     /**
151      * Unget a service's service object.
152      * Releases the service object for a service.
153      * If the context bundle's use count for the service is zero, this method
154      * returns <code>false</code>. Otherwise, the context bundle's use count for the
155      * service is decremented by one.
156      *
157      * <p>The service's service object
158      * should no longer be used and all references to it should be destroyed
159      * when a bundle's use count for the service
160      * drops to zero.
161      *
162      * <p>The following steps are followed to unget the service object:
163      * <ol>
164      * <li>If the context bundle's use count for the service is zero or
165      * the service has been unregistered,
166      * <code>false</code> is returned.
167      * <li>The context bundle's use count for this service is decremented by one.
168      * <li>If the context bundle's use count for the service is now zero and
169      * the service was registered with a {@link ServiceFactory},
170      * the {@link ServiceFactory#ungetService ServiceFactory.ungetService} method
171      * is called to release the service object for the context bundle.
172      * <li><code>true</code> is returned.
173      * </ol>
174      *
175      * @return <code>true</code> if the context bundle's use count for the service
176      * is zero otherwise <code>false</code>.
177      */

178     protected boolean ungetService() {
179         if (useCount == 0) {
180             return (true);
181         }
182
183         useCount--;
184
185         if (useCount == 0) {
186             if (factory != null) {
187                 try {
188                     AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
189                         public Object JavaDoc run() {
190                             factory.ungetService(context.bundle, registration, service);
191
192                             return null;
193                         }
194                     });
195                 } catch (Throwable JavaDoc t) {
196                     if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
197                         Debug.println(factory + ".ungetService() exception"); //$NON-NLS-1$
198
Debug.printStackTrace(t);
199                     }
200
201                     AbstractBundle factorybundle = registration.context.bundle;
202                     BundleException be = new BundleException(NLS.bind(Msg.SERVICE_FACTORY_EXCEPTION, factory.getClass().getName(), "ungetService"), t); //$NON-NLS-1$
203
context.framework.publishFrameworkEvent(FrameworkEvent.ERROR, factorybundle, be);
204                 }
205
206                 service = null;
207             }
208
209             return (true);
210         }
211
212         return (false);
213     }
214
215     /**
216      * Release a service's service object.
217      * <ol>
218      * <li>The bundle's use count for this service is set to zero.
219      * <li>If the service was registered with a {@link ServiceFactory},
220      * the {@link ServiceFactory#ungetService ServiceFactory.ungetService} method
221      * is called to release the service object for the bundle.
222      * </ol>
223      */

224     protected void releaseService() {
225         if ((useCount > 0) && (factory != null)) {
226             try {
227                 AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
228                     public Object JavaDoc run() {
229                         factory.ungetService(context.bundle, registration, service);
230
231                         return null;
232                     }
233                 });
234             } catch (Throwable JavaDoc t) {
235                 if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
236                     Debug.println(factory + ".ungetService() exception"); //$NON-NLS-1$
237
Debug.printStackTrace(t);
238                 }
239
240                 AbstractBundle factorybundle = registration.context.bundle;
241                 BundleException be = new BundleException(NLS.bind(Msg.SERVICE_FACTORY_EXCEPTION, factory.getClass().getName(), "ungetService"), t); //$NON-NLS-1$
242
context.framework.publishFrameworkEvent(FrameworkEvent.ERROR, factorybundle, be);
243             }
244
245             service = null;
246         }
247
248         useCount = 0;
249     }
250 }
251
Popular Tags