blob: 23de8fd899329fba421e8f16e8929491fe9c9eb1 [file] [log] [blame]
Marcel Offermansa962bc92009-11-21 17:59:33 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Pierre De Ropd2ec3952009-12-04 22:40:05 +000019package org.apache.felix.dm.impl;
Marcel Offermansa962bc92009-11-21 17:59:33 +000020
21import java.lang.reflect.Constructor;
22import java.lang.reflect.Field;
Marcel Offermansea89b862010-06-24 13:14:43 +000023import java.lang.reflect.InvocationTargetException;
Marcel Offermansa962bc92009-11-21 17:59:33 +000024import java.lang.reflect.Proxy;
25import java.util.ArrayList;
26import java.util.Dictionary;
27import java.util.Enumeration;
28import java.util.HashMap;
29import java.util.Hashtable;
30import java.util.Iterator;
31import java.util.List;
32import java.util.Map;
33import java.util.Properties;
34
Marcel Offermansfaaed472010-09-08 10:07:32 +000035import org.apache.felix.dm.Component;
36import org.apache.felix.dm.ComponentDeclaration;
37import org.apache.felix.dm.ComponentDependencyDeclaration;
38import org.apache.felix.dm.ComponentStateListener;
Marcel Offermans8b93efa2010-07-02 18:27:21 +000039import org.apache.felix.dm.Dependency;
Marcel Offermans3d921212010-08-09 13:37:02 +000040import org.apache.felix.dm.DependencyActivation;
Pierre De Ropd2ec3952009-12-04 22:40:05 +000041import org.apache.felix.dm.DependencyManager;
Marcel Offermans3d921212010-08-09 13:37:02 +000042import org.apache.felix.dm.DependencyService;
Marcel Offermans706fb272010-11-15 12:52:58 +000043import org.apache.felix.dm.InvocationUtil;
Marcel Offermansa962bc92009-11-21 17:59:33 +000044import org.osgi.framework.BundleContext;
45import org.osgi.framework.ServiceRegistration;
46
47/**
Marcel Offermansfaaed472010-09-08 10:07:32 +000048 * Component implementation.
Marcel Offermansa962bc92009-11-21 17:59:33 +000049 *
50 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
51 */
Marcel Offermans5be5f142011-04-26 10:47:12 +000052public class ComponentImpl implements Component, DependencyService, ComponentDeclaration, Comparable {
Marcel Offermansa962bc92009-11-21 17:59:33 +000053 private static final Class[] VOID = new Class[] {};
54 private static final ServiceRegistration NULL_REGISTRATION;
Marcel Offermansfaaed472010-09-08 10:07:32 +000055 private static final ComponentStateListener[] SERVICE_STATE_LISTENER_TYPE = new ComponentStateListener[] {};
Marcel Offermans5be5f142011-04-26 10:47:12 +000056 private static long HIGHEST_ID = 0;
Marcel Offermansa962bc92009-11-21 17:59:33 +000057
Marcel Offermanse14b3422009-11-25 23:04:32 +000058 private final Object SYNC = new Object();
Marcel Offermansa962bc92009-11-21 17:59:33 +000059 private final BundleContext m_context;
60 private final DependencyManager m_manager;
Marcel Offermans5be5f142011-04-26 10:47:12 +000061 private final long m_id;
Marcel Offermansa962bc92009-11-21 17:59:33 +000062
63 // configuration (static)
64 private String m_callbackInit;
65 private String m_callbackStart;
66 private String m_callbackStop;
67 private String m_callbackDestroy;
68 private Object m_serviceName;
69 private Object m_implementation;
Marcel Offermans61a81142010-04-02 15:16:50 +000070 private Object m_callbackInstance;
Marcel Offermansa962bc92009-11-21 17:59:33 +000071
72 // configuration (dynamic, but does not affect state)
73 private Dictionary m_serviceProperties;
74
75 // configuration (dynamic, and affects state)
76 private ArrayList m_dependencies = new ArrayList();
77
78 // runtime state (calculated from dependencies)
79 private State m_state;
80
81 // runtime state (changes because of state changes)
82 private Object m_serviceInstance;
Marcel Offermansa1bc22a2010-12-28 18:52:24 +000083 private volatile ServiceRegistration m_registration;
Marcel Offermanse14b3422009-11-25 23:04:32 +000084 private boolean m_isBound;
85 private boolean m_isInstantiated;
Marcel Offermansa962bc92009-11-21 17:59:33 +000086
87 // service state listeners
88 private final List m_stateListeners = new ArrayList();
89
90 // work queue
91 private final SerialExecutor m_executor = new SerialExecutor();
92
93 // instance factory
94 private Object m_instanceFactory;
95 private String m_instanceFactoryCreateMethod;
96
97 // composition manager
98 private Object m_compositionManager;
99 private String m_compositionManagerGetMethod;
100 private Object m_compositionManagerInstance;
101
102 // internal logging
103 private final Logger m_logger;
Marcel Offermans5be5f142011-04-26 10:47:12 +0000104
Marcel Offermansa962bc92009-11-21 17:59:33 +0000105 private Map m_autoConfig = new HashMap();
106 private Map m_autoConfigInstance = new HashMap();
Marcel Offermans5be5f142011-04-26 10:47:12 +0000107
108 private boolean m_isStarted = false;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000109
Marcel Offermansfaaed472010-09-08 10:07:32 +0000110 public ComponentImpl(BundleContext context, DependencyManager manager, Logger logger) {
Marcel Offermans5be5f142011-04-26 10:47:12 +0000111 synchronized (VOID) {
112 m_id = HIGHEST_ID++;
113 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000114 m_logger = logger;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000115 m_state = new State((List) m_dependencies.clone(), false, false, false);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000116 m_context = context;
117 m_manager = manager;
118 m_callbackInit = "init";
119 m_callbackStart = "start";
120 m_callbackStop = "stop";
121 m_callbackDestroy = "destroy";
122 m_implementation = null;
123 m_autoConfig.put(BundleContext.class, Boolean.TRUE);
124 m_autoConfig.put(ServiceRegistration.class, Boolean.TRUE);
125 m_autoConfig.put(DependencyManager.class, Boolean.TRUE);
Marcel Offermansfaaed472010-09-08 10:07:32 +0000126 m_autoConfig.put(Component.class, Boolean.TRUE);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000127 }
128
Marcel Offermanse14b3422009-11-25 23:04:32 +0000129 private void calculateStateChanges() {
130 // see if any of the things we did caused a further change of state
131 State oldState, newState;
132 synchronized (m_dependencies) {
133 oldState = m_state;
134 newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
135 m_state = newState;
136 }
137 calculateStateChanges(oldState, newState);
138 }
139
Marcel Offermansa962bc92009-11-21 17:59:33 +0000140 private void calculateStateChanges(final State oldState, final State newState) {
Marcel Offermanse14b3422009-11-25 23:04:32 +0000141 if (oldState.isInactive() && (newState.isTrackingOptional())) {
142 m_executor.enqueue(new Runnable() {
143 public void run() {
144 activateService(newState);
145 }});
146 }
147 if (oldState.isInactive() && (newState.isWaitingForRequired())) {
148 m_executor.enqueue(new Runnable() {
149 public void run() {
150 startTrackingRequired(newState);
151 }});
152 }
153 if (oldState.isWaitingForRequired() && newState.isTrackingOptional()) {
154 m_executor.enqueue(new Runnable() {
155 public void run() {
156 activateService(newState);
157 }});
158 }
159 if ((oldState.isWaitingForRequired()) && newState.isInactive()) {
160 m_executor.enqueue(new Runnable() {
161 public void run() {
162 stopTrackingRequired(oldState);
163 }});
164 }
165 if (oldState.isTrackingOptional() && newState.isWaitingForRequiredInstantiated()) {
166 m_executor.enqueue(new Runnable() {
167 public void run() {
168 // TODO as far as I can see there is nothing left to do here
Marcel Offermans5be5f142011-04-26 10:47:12 +0000169 // unbindService(newState);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000170 }});
171 }
172 if (oldState.isTrackingOptional() && newState.isWaitingForRequired()) {
173 m_executor.enqueue(new Runnable() {
174 public void run() {
175 deactivateService(oldState);
176 }});
177 }
178 if (oldState.isTrackingOptional() && newState.isBound()) {
179 m_executor.enqueue(new Runnable() {
180 public void run() {
Marcel Offermansbedf3692010-06-06 20:07:12 +0000181 bindService(newState);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000182 }});
183 }
184 if (oldState.isTrackingOptional() && newState.isInactive()) {
185 m_executor.enqueue(new Runnable() {
186 public void run() {
187 deactivateService(oldState);
188 stopTrackingRequired(oldState);
189 }});
190 }
191 if (oldState.isWaitingForRequiredInstantiated() && newState.isWaitingForRequired()) {
192 m_executor.enqueue(new Runnable() {
193 public void run() {
194 deactivateService(oldState);
195 }});
196 }
197 if (oldState.isWaitingForRequiredInstantiated() && newState.isInactive()) {
198 m_executor.enqueue(new Runnable() {
199 public void run() {
200 deactivateService(oldState);
201 stopTrackingRequired(oldState);
202 }});
203 }
204 if (oldState.isWaitingForRequiredInstantiated() && newState.isBound()) {
205 m_executor.enqueue(new Runnable() {
206 public void run() {
Marcel Offermansbedf3692010-06-06 20:07:12 +0000207 bindService(newState);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000208 }});
209 }
210 if (oldState.isBound() && newState.isWaitingForRequiredInstantiated()) {
211 m_executor.enqueue(new Runnable() {
212 public void run() {
213 unbindService(oldState);
214 }});
215 }
216 if (oldState.isBound() && newState.isWaitingForRequired()) {
217 m_executor.enqueue(new Runnable() {
218 public void run() {
219 unbindService(oldState);
220 deactivateService(oldState);
221 }});
222 }
223 if (oldState.isBound() && newState.isInactive()) {
224 m_executor.enqueue(new Runnable() {
225 public void run() {
226 unbindService(oldState);
227 deactivateService(oldState);
228 stopTrackingRequired(oldState);
229 }});
230 }
231 m_executor.execute();
Marcel Offermansa962bc92009-11-21 17:59:33 +0000232 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000233
Marcel Offermansf9a7e342010-10-07 12:22:46 +0000234 // TODO fix code duplication between add(Dependency) and add(List)
Marcel Offermansfaaed472010-09-08 10:07:32 +0000235 public Component add(final Dependency dependency) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000236 State oldState, newState;
237 synchronized (m_dependencies) {
238 oldState = m_state;
239 m_dependencies.add(dependency);
240 }
Pierre De Rop79ac9712010-06-11 06:02:07 +0000241
Marcel Offermansf9a7e342010-10-07 12:22:46 +0000242 // if we're inactive, don't do anything, otherwise we might want to start
243 // the dependency
244 if (!oldState.isInactive()) {
245 // if the dependency is required, it should be started regardless of the state
246 // we're in
247 if (dependency.isRequired()) {
248 ((DependencyActivation) dependency).start(this);
249 }
250 else {
251 // if the dependency is optional, it should only be started if we're in
252 // bound state
253 if (oldState.isBound()) {
254 ((DependencyActivation) dependency).start(this);
255 }
256 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000257 }
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000258
Marcel Offermansa962bc92009-11-21 17:59:33 +0000259 synchronized (m_dependencies) {
Marcel Offermans0acdb1b2010-10-14 14:43:03 +0000260 oldState = m_state;
Marcel Offermans306c2522009-12-17 13:57:58 +0000261 // starting the dependency above might have triggered another state change, so
262 // we have to fetch the current state again
Marcel Offermanse14b3422009-11-25 23:04:32 +0000263 newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000264 m_state = newState;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000265 }
266 calculateStateChanges(oldState, newState);
267 return this;
268 }
Marcel Offermansf9a7e342010-10-07 12:22:46 +0000269
Marcel Offermansfaaed472010-09-08 10:07:32 +0000270 public Component add(List dependencies) {
Marcel Offermansf9a7e342010-10-07 12:22:46 +0000271 State oldState, newState;
272 synchronized (m_dependencies) {
273 oldState = m_state;
274 for (int i = 0; i < dependencies.size(); i++) {
275 m_dependencies.add(dependencies.get(i));
276 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000277 }
Marcel Offermansf9a7e342010-10-07 12:22:46 +0000278
279 // if we're inactive, don't do anything, otherwise we might want to start
280 // the dependencies
281 if (!oldState.isInactive()) {
282 for (int i = 0; i < dependencies.size(); i++) {
283 Dependency dependency = (Dependency) dependencies.get(i);
284 // if the dependency is required, it should be started regardless of the state
285 // we're in
286 if (dependency.isRequired()) {
287 ((DependencyActivation) dependency).start(this);
288 }
289 else {
290 // if the dependency is optional, it should only be started if we're in
291 // bound state
292 if (oldState.isBound()) {
293 ((DependencyActivation) dependency).start(this);
294 }
295 }
296 }
297 }
298
299 synchronized (m_dependencies) {
Pierre De Rop761a4492010-10-16 19:26:25 +0000300 oldState = m_state;
Marcel Offermansf9a7e342010-10-07 12:22:46 +0000301 // starting the dependency above might have triggered another state change, so
302 // we have to fetch the current state again
303 newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
304 m_state = newState;
305 }
306 calculateStateChanges(oldState, newState);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000307 return this;
308 }
309
Marcel Offermansfaaed472010-09-08 10:07:32 +0000310 public Component remove(Dependency dependency) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000311 State oldState, newState;
312 synchronized (m_dependencies) {
313 oldState = m_state;
314 m_dependencies.remove(dependency);
315 }
Marcel Offermans0acdb1b2010-10-14 14:43:03 +0000316 if (oldState.isAllRequiredAvailable() || ((oldState.isWaitingForRequired() || oldState.isWaitingForRequiredInstantiated()) && dependency.isRequired())) {
Pierre De Ropd2ec3952009-12-04 22:40:05 +0000317 ((DependencyActivation) dependency).stop(this);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000318 }
319 synchronized (m_dependencies) {
Marcel Offermans306c2522009-12-17 13:57:58 +0000320 // starting the dependency above might have triggered another state change, so
321 // we have to fetch the current state again
322 oldState = m_state;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000323 newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000324 m_state = newState;
325 }
326 calculateStateChanges(oldState, newState);
327 return this;
328 }
329
330 public List getDependencies() {
331 synchronized (m_dependencies) {
332 return (List) m_dependencies.clone();
333 }
334 }
335
336 public ServiceRegistration getServiceRegistration() {
337 return m_registration;
338 }
339
340 public Object getService() {
341 return m_serviceInstance;
342 }
Marcel Offermansea89b862010-06-24 13:14:43 +0000343
Marcel Offermansfaaed472010-09-08 10:07:32 +0000344 public Component getServiceInterface() {
Marcel Offermansea89b862010-06-24 13:14:43 +0000345 return this;
346 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000347
348 public void dependencyAvailable(final Dependency dependency) {
349 State oldState, newState;
350 synchronized (m_dependencies) {
351 oldState = m_state;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000352 newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000353 m_state = newState;
354 }
Marcel Offermans6cb7ac22010-01-04 09:32:37 +0000355 if (newState.isAllRequiredAvailable() || newState.isWaitingForRequiredInstantiated()) {
Marcel Offermans84a43ad2009-12-29 14:54:48 +0000356 updateInstance(dependency);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000357 }
Marcel Offermans306c2522009-12-17 13:57:58 +0000358 calculateStateChanges(oldState, newState);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000359 }
360
361 public void dependencyChanged(final Dependency dependency) {
362 State state;
363 synchronized (m_dependencies) {
364 state = m_state;
365 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000366 if (state.isAllRequiredAvailable()) {
Marcel Offermans84a43ad2009-12-29 14:54:48 +0000367 updateInstance(dependency);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000368 }
369 }
370
371 public void dependencyUnavailable(final Dependency dependency) {
372 State oldState, newState;
373 synchronized (m_dependencies) {
374 oldState = m_state;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000375 newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000376 m_state = newState;
377 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000378 if (newState.isAllRequiredAvailable()) {
Marcel Offermans84a43ad2009-12-29 14:54:48 +0000379 updateInstance(dependency);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000380 }
Marcel Offermans306c2522009-12-17 13:57:58 +0000381 calculateStateChanges(oldState, newState);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000382 }
383
384 public synchronized void start() {
Marcel Offermans5be5f142011-04-26 10:47:12 +0000385 if (!m_isStarted) {
386 m_isStarted = true;
Marcel Offermansd60b54d2011-01-21 20:38:55 +0000387 State oldState, newState;
Marcel Offermans6358e052010-01-04 14:36:08 +0000388 synchronized (m_dependencies) {
Marcel Offermansd60b54d2011-01-21 20:38:55 +0000389 oldState = m_state;
Marcel Offermans6358e052010-01-04 14:36:08 +0000390 newState = new State((List) m_dependencies.clone(), true, m_isInstantiated, m_isBound);
391 m_state = newState;
392 }
393 calculateStateChanges(oldState, newState);
394 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000395 }
396
397 public synchronized void stop() {
Marcel Offermans5be5f142011-04-26 10:47:12 +0000398 if (m_isStarted) {
399 m_isStarted = false;
Marcel Offermansd60b54d2011-01-21 20:38:55 +0000400 State oldState, newState;
Marcel Offermans6358e052010-01-04 14:36:08 +0000401 synchronized (m_dependencies) {
Marcel Offermansd60b54d2011-01-21 20:38:55 +0000402 oldState = m_state;
Marcel Offermans6358e052010-01-04 14:36:08 +0000403 newState = new State((List) m_dependencies.clone(), false, m_isInstantiated, m_isBound);
404 m_state = newState;
405 }
406 calculateStateChanges(oldState, newState);
Marcel Offermans6358e052010-01-04 14:36:08 +0000407 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000408 }
409
Marcel Offermansfaaed472010-09-08 10:07:32 +0000410 public synchronized Component setInterface(String serviceName, Dictionary properties) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000411 ensureNotActive();
412 m_serviceName = serviceName;
413 m_serviceProperties = properties;
414 return this;
415 }
416
Marcel Offermansfaaed472010-09-08 10:07:32 +0000417 public synchronized Component setInterface(String[] serviceName, Dictionary properties) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000418 ensureNotActive();
419 m_serviceName = serviceName;
420 m_serviceProperties = properties;
421 return this;
422 }
423
Marcel Offermansfaaed472010-09-08 10:07:32 +0000424 public synchronized Component setCallbacks(String init, String start, String stop, String destroy) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000425 ensureNotActive();
426 m_callbackInit = init;
427 m_callbackStart = start;
428 m_callbackStop = stop;
429 m_callbackDestroy = destroy;
430 return this;
431 }
Marcel Offermans61a81142010-04-02 15:16:50 +0000432
Marcel Offermansfaaed472010-09-08 10:07:32 +0000433 public synchronized Component setCallbacks(Object instance, String init, String start, String stop, String destroy) {
Marcel Offermans61a81142010-04-02 15:16:50 +0000434 ensureNotActive();
435 m_callbackInstance = instance;
436 m_callbackInit = init;
437 m_callbackStart = start;
438 m_callbackStop = stop;
439 m_callbackDestroy = destroy;
440 return this;
441 }
442
Marcel Offermansfaaed472010-09-08 10:07:32 +0000443 public synchronized Component setImplementation(Object implementation) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000444 ensureNotActive();
445 m_implementation = implementation;
446 return this;
447 }
448
Marcel Offermansfaaed472010-09-08 10:07:32 +0000449 public synchronized Component setFactory(Object factory, String createMethod) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000450 ensureNotActive();
451 m_instanceFactory = factory;
452 m_instanceFactoryCreateMethod = createMethod;
453 return this;
454 }
455
Marcel Offermansfaaed472010-09-08 10:07:32 +0000456 public synchronized Component setFactory(String createMethod) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000457 return setFactory(null, createMethod);
458 }
459
Marcel Offermansfaaed472010-09-08 10:07:32 +0000460 public synchronized Component setComposition(Object instance, String getMethod) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000461 ensureNotActive();
462 m_compositionManager = instance;
463 m_compositionManagerGetMethod = getMethod;
464 return this;
465 }
466
Marcel Offermansfaaed472010-09-08 10:07:32 +0000467 public synchronized Component setComposition(String getMethod) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000468 return setComposition(null, getMethod);
469 }
470
471 public String toString() {
Marcel Offermans706fb272010-11-15 12:52:58 +0000472 return this.getClass().getSimpleName() + "[" + m_serviceName + " " + m_implementation + "]";
Marcel Offermansa962bc92009-11-21 17:59:33 +0000473 }
474
475 public synchronized Dictionary getServiceProperties() {
476 if (m_serviceProperties != null) {
477 return (Dictionary) ((Hashtable) m_serviceProperties).clone();
478 }
479 return null;
480 }
481
Marcel Offermansfaaed472010-09-08 10:07:32 +0000482 public synchronized Component setServiceProperties(Dictionary serviceProperties) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000483 m_serviceProperties = serviceProperties;
Marcel Offermans937ab4f2009-12-10 10:53:01 +0000484 if ((m_registration != null) && (m_serviceName != null)) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000485 m_registration.setProperties(calculateServiceProperties());
486 }
Pierre De Rop19476fe2010-05-23 08:13:58 +0000487 return this;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000488 }
489
490 // service state listener methods
Marcel Offermansfaaed472010-09-08 10:07:32 +0000491 public void addStateListener(ComponentStateListener listener) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000492 synchronized (m_stateListeners) {
493 m_stateListeners.add(listener);
494 }
495 // when we register as a listener and the service is already started
496 // make sure we invoke the right callbacks so the listener knows
497 State state;
498 synchronized (m_dependencies) {
499 state = m_state;
500 }
Marcel Offermansdeda4322011-03-02 16:00:05 +0000501 if (state.isBound()) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000502 listener.starting(this);
503 listener.started(this);
504 }
505 }
506
Marcel Offermansfaaed472010-09-08 10:07:32 +0000507 public void removeStateListener(ComponentStateListener listener) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000508 synchronized (m_stateListeners) {
509 m_stateListeners.remove(listener);
510 }
511 }
512
Marcel Offermanse14b3422009-11-25 23:04:32 +0000513 public void removeStateListeners() {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000514 synchronized (m_stateListeners) {
515 m_stateListeners.clear();
516 }
517 }
518
519 private void stateListenersStarting() {
Marcel Offermansfaaed472010-09-08 10:07:32 +0000520 ComponentStateListener[] list = getListeners();
Marcel Offermansa962bc92009-11-21 17:59:33 +0000521 for (int i = 0; i < list.length; i++) {
522 try {
523 list[i].starting(this);
524 }
525 catch (Throwable t) {
526 m_logger.log(Logger.LOG_ERROR, "Error invoking listener starting method.", t);
527 }
528 }
529 }
530
531 private void stateListenersStarted() {
Marcel Offermansfaaed472010-09-08 10:07:32 +0000532 ComponentStateListener[] list = getListeners();
Marcel Offermansa962bc92009-11-21 17:59:33 +0000533 for (int i = 0; i < list.length; i++) {
534 try {
535 list[i].started(this);
536 }
537 catch (Throwable t) {
538 m_logger.log(Logger.LOG_ERROR, "Error invoking listener started method.", t);
539 }
540 }
541 }
542
543 private void stateListenersStopping() {
Marcel Offermansfaaed472010-09-08 10:07:32 +0000544 ComponentStateListener[] list = getListeners();
Marcel Offermansa962bc92009-11-21 17:59:33 +0000545 for (int i = 0; i < list.length; i++) {
546 try {
547 list[i].stopping(this);
548 }
549 catch (Throwable t) {
550 m_logger.log(Logger.LOG_ERROR, "Error invoking listener stopping method.", t);
551 }
552 }
553 }
554
555 private void stateListenersStopped() {
Marcel Offermansfaaed472010-09-08 10:07:32 +0000556 ComponentStateListener[] list = getListeners();
Marcel Offermansa962bc92009-11-21 17:59:33 +0000557 for (int i = 0; i < list.length; i++) {
558 try {
559 list[i].stopped(this);
560 }
561 catch (Throwable t) {
562 m_logger.log(Logger.LOG_ERROR, "Error invoking listener stopped method.", t);
563 }
564 }
565 }
566
Marcel Offermansfaaed472010-09-08 10:07:32 +0000567 private ComponentStateListener[] getListeners() {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000568 synchronized (m_stateListeners) {
Marcel Offermansfaaed472010-09-08 10:07:32 +0000569 return (ComponentStateListener[]) m_stateListeners.toArray(SERVICE_STATE_LISTENER_TYPE);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000570 }
571 }
572
Marcel Offermanse14b3422009-11-25 23:04:32 +0000573 private void activateService(State state) {
574 String init;
575 synchronized (this) {
576 init = m_callbackInit;
577 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000578 // service activation logic, first we initialize the service instance itself
579 // meaning it is created if necessary and the bundle context is set
580 initService();
Marcel Offermansa962bc92009-11-21 17:59:33 +0000581 // now is the time to configure the service, meaning all required
582 // dependencies will be set and any callbacks called
583 configureService(state);
Marcel Offermans78e5dfc2009-12-10 13:52:49 +0000584 // flag that our instance has been created
585 m_isInstantiated = true;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000586 // then we invoke the init callback so the service can further initialize
587 // itself
588 invoke(init);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000589 // see if any of this caused further state changes
590 calculateStateChanges();
591 }
592
593 private void bindService(State state) {
594 String start;
595 synchronized (this) {
596 start = m_callbackStart;
597 }
Pierre De Rop79ac9712010-06-11 06:02:07 +0000598
Marcel Offermans0acdb1b2010-10-14 14:43:03 +0000599 // configure service with extra-dependencies which might have been added from init() method.
Pierre De Rop79ac9712010-06-11 06:02:07 +0000600 configureServiceWithExtraDependencies(state);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000601 // inform the state listeners we're starting
602 stateListenersStarting();
603 // invoke the start callback, since we're now ready to be used
604 invoke(start);
605 // start tracking optional services
606 startTrackingOptional(state);
607 // register the service in the framework's service registry
608 registerService();
609 // inform the state listeners we've started
610 stateListenersStarted();
611 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000612
Marcel Offermans0acdb1b2010-10-14 14:43:03 +0000613 private void configureServiceWithExtraDependencies(State state) {
Pierre De Rop79ac9712010-06-11 06:02:07 +0000614 Iterator i = state.getDependencies().iterator();
615 while (i.hasNext()) {
616 Dependency dependency = (Dependency) i.next();
617 if (dependency.isAutoConfig() && dependency.isInstanceBound()) {
618 configureImplementation(dependency.getAutoConfigType(), dependency.getAutoConfigInstance(), dependency.getAutoConfigName());
619 }
Pierre De Rop79ac9712010-06-11 06:02:07 +0000620 }
621 }
622
Marcel Offermanse14b3422009-11-25 23:04:32 +0000623 private void unbindService(State state) {
624 String stop;
625 synchronized (this) {
626 stop = m_callbackStop;
627 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000628 // service deactivation logic, first inform the state listeners
629 // we're stopping
630 stateListenersStopping();
631 // then, unregister the service from the framework
632 unregisterService();
633 // stop tracking optional services
634 stopTrackingOptional(state);
635 // invoke the stop callback
636 invoke(stop);
637 // inform the state listeners we've stopped
638 stateListenersStopped();
Marcel Offermanse14b3422009-11-25 23:04:32 +0000639 }
640
641 private void deactivateService(State state) {
642 String destroy;
643 synchronized (this) {
644 destroy = m_callbackDestroy;
645 }
Marcel Offermans78e5dfc2009-12-10 13:52:49 +0000646 // flag that our instance was destroyed
647 m_isInstantiated = false;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000648 // invoke the destroy callback
649 invoke(destroy);
650 // destroy the service instance
651 destroyService(state);
652 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000653
Marcel Offermansa962bc92009-11-21 17:59:33 +0000654 private void invoke(String name) {
655 if (name != null) {
Marcel Offermansea89b862010-06-24 13:14:43 +0000656 // if a callback instance was specified, look for the method there, if not,
657 // ask the service for its composition instances
658 Object[] instances = m_callbackInstance != null ? new Object[] { m_callbackInstance } : getCompositionInstances();
659 invokeCallbackMethod(instances, name,
Marcel Offermansfaaed472010-09-08 10:07:32 +0000660 new Class[][] {{ Component.class }, {}},
Marcel Offermansea89b862010-06-24 13:14:43 +0000661 new Object[][] {{ this }, {}});
662 }
663 }
664
665 public void invokeCallbackMethod(Object[] instances, String methodName, Class[][] signatures, Object[][] parameters) {
666 for (int i = 0; i < instances.length; i++) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000667 try {
Marcel Offermansea89b862010-06-24 13:14:43 +0000668 InvocationUtil.invokeCallbackMethod(instances[i], methodName, signatures, parameters);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000669 }
Marcel Offermanse43114b2010-04-04 18:37:44 +0000670 catch (NoSuchMethodException e) {
Marcel Offermansea89b862010-06-24 13:14:43 +0000671 // if the method does not exist, ignore it
672 }
673 catch (InvocationTargetException e) {
674 // the method itself threw an exception, log that
675 m_logger.log(Logger.LOG_WARNING, "Invocation of '" + methodName + "' failed.", e.getCause());
Marcel Offermanse43114b2010-04-04 18:37:44 +0000676 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000677 catch (Exception e) {
Marcel Offermansea89b862010-06-24 13:14:43 +0000678 m_logger.log(Logger.LOG_WARNING, "Could not invoke '" + methodName + "'.", e);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000679 }
680 }
681 }
682
683 private void startTrackingOptional(State state) {
684 Iterator i = state.getDependencies().iterator();
685 while (i.hasNext()) {
686 Dependency dependency = (Dependency) i.next();
687 if (!dependency.isRequired()) {
Pierre De Ropd2ec3952009-12-04 22:40:05 +0000688 ((DependencyActivation) dependency).start(this);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000689 }
690 }
691 }
692
693 private void stopTrackingOptional(State state) {
694 Iterator i = state.getDependencies().iterator();
695 while (i.hasNext()) {
696 Dependency dependency = (Dependency) i.next();
697 if (!dependency.isRequired()) {
Pierre De Ropd2ec3952009-12-04 22:40:05 +0000698 ((DependencyActivation) dependency).stop(this);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000699 }
700 }
701 }
702
703 private void startTrackingRequired(State state) {
704 Iterator i = state.getDependencies().iterator();
705 while (i.hasNext()) {
706 Dependency dependency = (Dependency) i.next();
707 if (dependency.isRequired()) {
Pierre De Ropd2ec3952009-12-04 22:40:05 +0000708 ((DependencyActivation) dependency).start(this);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000709 }
710 }
711 }
712
713 private void stopTrackingRequired(State state) {
714 Iterator i = state.getDependencies().iterator();
715 while (i.hasNext()) {
716 Dependency dependency = (Dependency) i.next();
717 if (dependency.isRequired()) {
Pierre De Ropd2ec3952009-12-04 22:40:05 +0000718 ((DependencyActivation) dependency).stop(this);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000719 }
720 }
721 }
722
Marcel Offermans392c2022011-03-25 01:09:12 +0000723 private Object createInstance(Class clazz) throws SecurityException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000724 Constructor constructor = clazz.getConstructor(VOID);
725 constructor.setAccessible(true);
Marcel Offermans392c2022011-03-25 01:09:12 +0000726 return constructor.newInstance(null);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000727 }
728
Marcel Offermanse14b3422009-11-25 23:04:32 +0000729 public void initService() {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000730 if (m_serviceInstance == null) {
731 if (m_implementation instanceof Class) {
732 // instantiate
733 try {
734 m_serviceInstance = createInstance((Class) m_implementation);
735 }
736 catch (Exception e) {
737 m_logger.log(Logger.LOG_ERROR, "Could not create service instance of class " + m_implementation + ".", e);
738 }
739 }
740 else {
741 if (m_instanceFactoryCreateMethod != null) {
742 Object factory = null;
743 if (m_instanceFactory != null) {
744 if (m_instanceFactory instanceof Class) {
745 try {
746 factory = createInstance((Class) m_instanceFactory);
747 }
748 catch (Exception e) {
749 m_logger.log(Logger.LOG_ERROR, "Could not create factory instance of class " + m_instanceFactory + ".", e);
750 }
751 }
752 else {
753 factory = m_instanceFactory;
754 }
755 }
756 else {
757 // TODO review if we want to try to default to something if not specified
758 // for now the JavaDoc of setFactory(method) reflects the fact that we need
759 // to review it
760 }
761 if (factory == null) {
762 m_logger.log(Logger.LOG_ERROR, "Factory cannot be null.");
763 }
764 else {
765 try {
Marcel Offermansa6ffb992010-05-19 11:56:44 +0000766 m_serviceInstance = InvocationUtil.invokeMethod(factory, factory.getClass(), m_instanceFactoryCreateMethod, new Class[][] {{}}, new Object[][] {{}}, false);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000767 }
768 catch (Exception e) {
769 m_logger.log(Logger.LOG_ERROR, "Could not create service instance using factory " + factory + " method " + m_instanceFactoryCreateMethod + ".", e);
770 }
771 }
772 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000773 if (m_serviceInstance == null) {
Marcel Offermanscc8adbb2010-02-17 10:20:11 +0000774 if (m_implementation == null) {
775 m_logger.log(Logger.LOG_ERROR, "Implementation cannot be null.");
776 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000777 m_serviceInstance = m_implementation;
778 }
779 }
780 // configure the bundle context
781 if (((Boolean) m_autoConfig.get(BundleContext.class)).booleanValue()) {
782 configureImplementation(BundleContext.class, m_context, (String) m_autoConfigInstance.get(BundleContext.class));
783 }
784 if (((Boolean) m_autoConfig.get(ServiceRegistration.class)).booleanValue()) {
785 configureImplementation(ServiceRegistration.class, NULL_REGISTRATION, (String) m_autoConfigInstance.get(ServiceRegistration.class));
786 }
787 if (((Boolean) m_autoConfig.get(DependencyManager.class)).booleanValue()) {
788 configureImplementation(DependencyManager.class, m_manager, (String) m_autoConfigInstance.get(DependencyManager.class));
789 }
Marcel Offermansfaaed472010-09-08 10:07:32 +0000790 if (((Boolean) m_autoConfig.get(Component.class)).booleanValue()) {
791 configureImplementation(Component.class, this, (String) m_autoConfigInstance.get(Component.class));
Marcel Offermanse14b3422009-11-25 23:04:32 +0000792 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000793 }
794 }
795
Marcel Offermansfaaed472010-09-08 10:07:32 +0000796 public synchronized Component setAutoConfig(Class clazz, boolean autoConfig) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000797 m_autoConfig.put(clazz, Boolean.valueOf(autoConfig));
Marcel Offermans3d921212010-08-09 13:37:02 +0000798 return this;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000799 }
800
Marcel Offermansfaaed472010-09-08 10:07:32 +0000801 public synchronized Component setAutoConfig(Class clazz, String instanceName) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000802 m_autoConfig.put(clazz, Boolean.valueOf(instanceName != null));
803 m_autoConfigInstance.put(clazz, instanceName);
Marcel Offermans3d921212010-08-09 13:37:02 +0000804 return this;
805 }
806
807 public boolean getAutoConfig(Class clazz) {
808 Boolean result = (Boolean) m_autoConfig.get(clazz);
809 return (result != null && result.booleanValue());
810 }
811
812 public String getAutoConfigInstance(Class clazz) {
813 return (String) m_autoConfigInstance.get(clazz);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000814 }
815
816 private void configureService(State state) {
817 // configure all services (the optional dependencies might be configured
818 // as null objects but that's what we want at this point)
819 configureServices(state);
820 }
821
822 private void destroyService(State state) {
823 unconfigureServices(state);
824 m_serviceInstance = null;
825 }
826
827 private void registerService() {
828 if (m_serviceName != null) {
829 ServiceRegistrationImpl wrapper = new ServiceRegistrationImpl();
830 m_registration = wrapper;
831 if (((Boolean) m_autoConfig.get(ServiceRegistration.class)).booleanValue()) {
832 configureImplementation(ServiceRegistration.class, m_registration, (String) m_autoConfigInstance.get(ServiceRegistration.class));
833 }
834
835 // service name can either be a string or an array of strings
836 ServiceRegistration registration;
837
838 // determine service properties
839 Dictionary properties = calculateServiceProperties();
840
841 // register the service
842 try {
843 if (m_serviceName instanceof String) {
844 registration = m_context.registerService((String) m_serviceName, m_serviceInstance, properties);
845 }
846 else {
847 registration = m_context.registerService((String[]) m_serviceName, m_serviceInstance, properties);
848 }
849 wrapper.setServiceRegistration(registration);
850 }
851 catch (IllegalArgumentException iae) {
852 m_logger.log(Logger.LOG_ERROR, "Could not register service " + m_serviceInstance, iae);
853 // set the registration to an illegal state object, which will make all invocations on this
854 // wrapper fail with an ISE (which also occurs when the SR becomes invalid)
855 wrapper.setIllegalState();
856 }
857 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000858 m_isBound = true;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000859 }
860
861 private Dictionary calculateServiceProperties() {
862 Dictionary properties = new Properties();
863 addTo(properties, m_serviceProperties);
864 for (int i = 0; i < m_dependencies.size(); i++) {
865 Dependency d = (Dependency) m_dependencies.get(i);
Marcel Offermanse380c0b2011-10-17 09:03:19 +0000866 if (d.isPropagated() && d.isAvailable()) {
Marcel Offermans117aa2f2009-12-10 09:48:17 +0000867 Dictionary dict = d.getProperties();
868 addTo(properties, dict);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000869 }
870 }
871 if (properties.size() == 0) {
872 properties = null;
873 }
874 return properties;
875 }
876
877 private void addTo(Dictionary properties, Dictionary additional) {
878 if (properties == null) {
879 throw new IllegalArgumentException("Dictionary to add to cannot be null.");
880 }
881 if (additional != null) {
882 Enumeration e = additional.keys();
883 while (e.hasMoreElements()) {
884 Object key = e.nextElement();
885 properties.put(key, additional.get(key));
886 }
887 }
888 }
889
890 private void unregisterService() {
Marcel Offermanse14b3422009-11-25 23:04:32 +0000891 m_isBound = false;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000892 if (m_serviceName != null) {
893 m_registration.unregister();
894 configureImplementation(ServiceRegistration.class, NULL_REGISTRATION);
Marcel Offermansa1bc22a2010-12-28 18:52:24 +0000895 m_registration = null;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000896 }
897 }
898
899 private void updateInstance(Dependency dependency) {
Marcel Offermans937ab4f2009-12-10 10:53:01 +0000900 if (dependency.isAutoConfig()) {
901 configureImplementation(dependency.getAutoConfigType(), dependency.getAutoConfigInstance(), dependency.getAutoConfigName());
902 if (dependency.isPropagated() && m_registration != null) {
903 m_registration.setProperties(calculateServiceProperties());
Marcel Offermansa962bc92009-11-21 17:59:33 +0000904 }
905 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000906 }
907
908 /**
909 * Configure a field in the service implementation. The service implementation
910 * is searched for fields that have the same type as the class that was specified
911 * and for each of these fields, the specified instance is filled in.
912 *
913 * @param clazz the class to search for
914 * @param instance the instance to fill in
915 * @param instanceName the name of the instance to fill in, or <code>null</code> if not used
916 */
917 private void configureImplementation(Class clazz, Object instance, String instanceName) {
918 Object[] instances = getCompositionInstances();
919 if (instances != null) {
920 for (int i = 0; i < instances.length; i++) {
921 Object serviceInstance = instances[i];
922 Class serviceClazz = serviceInstance.getClass();
Marcel Offermansad760672010-03-03 15:30:01 +0000923 if (Proxy.isProxyClass(serviceClazz)) {
924 serviceInstance = Proxy.getInvocationHandler(serviceInstance);
925 serviceClazz = serviceInstance.getClass();
926 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000927 while (serviceClazz != null) {
928 Field[] fields = serviceClazz.getDeclaredFields();
929 for (int j = 0; j < fields.length; j++) {
Marcel Offermans9afe2f52010-05-11 11:33:39 +0000930 Field field = fields[j];
931 Class type = field.getType();
932 if ((instanceName == null && type.equals(clazz))
933 || (instanceName != null && field.getName().equals(instanceName) && type.isAssignableFrom(clazz))) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000934 try {
Marcel Offermans9afe2f52010-05-11 11:33:39 +0000935 field.setAccessible(true);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000936 // synchronized makes sure the field is actually written to immediately
Marcel Offermanse14b3422009-11-25 23:04:32 +0000937 synchronized (SYNC) {
Marcel Offermans9afe2f52010-05-11 11:33:39 +0000938 field.set(serviceInstance, instance);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000939 }
940 }
941 catch (Exception e) {
Marcel Offermans9afe2f52010-05-11 11:33:39 +0000942 m_logger.log(Logger.LOG_ERROR, "Could not set field " + field, e);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000943 return;
944 }
945 }
946 }
947 serviceClazz = serviceClazz.getSuperclass();
948 }
949 }
950 }
951 }
952
953 public Object[] getCompositionInstances() {
Marcel Offermanse14b3422009-11-25 23:04:32 +0000954 Object[] instances = null;
955 if (m_compositionManagerGetMethod != null) {
956 if (m_compositionManager != null) {
957 m_compositionManagerInstance = m_compositionManager;
958 }
959 else {
960 m_compositionManagerInstance = m_serviceInstance;
961 }
962 if (m_compositionManagerInstance != null) {
963 try {
Marcel Offermans1391d682010-06-17 10:17:47 +0000964 instances = (Object[]) InvocationUtil.invokeMethod(m_compositionManagerInstance, m_compositionManagerInstance.getClass(), m_compositionManagerGetMethod, new Class[][] {{}}, new Object[][] {{}}, false);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000965 }
966 catch (Exception e) {
967 m_logger.log(Logger.LOG_ERROR, "Could not obtain instances from the composition manager.", e);
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000968 instances = m_serviceInstance == null ? new Object[] {} : new Object[] { m_serviceInstance };
Marcel Offermanse14b3422009-11-25 23:04:32 +0000969 }
970 }
971 }
972 else {
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000973 instances = m_serviceInstance == null ? new Object[] {} : new Object[] { m_serviceInstance };
Marcel Offermanse14b3422009-11-25 23:04:32 +0000974 }
975 return instances;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000976 }
977
978 private void configureImplementation(Class clazz, Object instance) {
979 configureImplementation(clazz, instance, null);
980 }
981
982 private void configureServices(State state) {
983 Iterator i = state.getDependencies().iterator();
984 while (i.hasNext()) {
985 Dependency dependency = (Dependency) i.next();
Marcel Offermans001db052009-12-08 08:58:40 +0000986 if (dependency.isAutoConfig()) {
987 configureImplementation(dependency.getAutoConfigType(), dependency.getAutoConfigInstance(), dependency.getAutoConfigName());
Marcel Offermanse14b3422009-11-25 23:04:32 +0000988 }
Marcel Offermans001db052009-12-08 08:58:40 +0000989 if (dependency.isRequired()) {
990 dependency.invokeAdded(this);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000991 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000992 }
993 }
994
995 private void unconfigureServices(State state) {
996 Iterator i = state.getDependencies().iterator();
997 while (i.hasNext()) {
998 Dependency dependency = (Dependency) i.next();
Marcel Offermans001db052009-12-08 08:58:40 +0000999 if (dependency.isRequired()) {
1000 dependency.invokeRemoved(this);
Marcel Offermansa962bc92009-11-21 17:59:33 +00001001 }
1002 }
1003 }
1004
Pierre De Rop19476fe2010-05-23 08:13:58 +00001005 protected void ensureNotActive() {
Marcel Offermansa962bc92009-11-21 17:59:33 +00001006 State state;
1007 synchronized (m_dependencies) {
1008 state = m_state;
1009 }
1010 if (!state.isInactive()) {
1011 throw new IllegalStateException("Cannot modify state while active.");
1012 }
1013 }
Marcel Offermanse14b3422009-11-25 23:04:32 +00001014
1015 public boolean isRegistered() {
Marcel Offermansa962bc92009-11-21 17:59:33 +00001016 State state;
1017 synchronized (m_dependencies) {
1018 state = m_state;
1019 }
Marcel Offermans0f6605e2009-12-10 10:31:35 +00001020 return (state.isAllRequiredAvailable());
1021 }
1022
Marcel Offermans0acdb1b2010-10-14 14:43:03 +00001023 public boolean isInstantiated() {
1024 State state;
1025 synchronized (m_dependencies) {
1026 state = m_state;
1027 }
1028 return (state.isTrackingOptional() || state.isBound() || state.isWaitingForRequiredInstantiated());
1029 }
1030
Marcel Offermansa962bc92009-11-21 17:59:33 +00001031 // ServiceComponent interface
1032
Marcel Offermansfaaed472010-09-08 10:07:32 +00001033 static class SCDImpl implements ComponentDependencyDeclaration {
Marcel Offermansa962bc92009-11-21 17:59:33 +00001034 private final String m_name;
1035 private final int m_state;
1036 private final String m_type;
1037
1038 public SCDImpl(String name, int state, String type) {
1039 m_name = name;
1040 m_state = state;
1041 m_type = type;
1042 }
1043
1044 public String getName() {
1045 return m_name;
1046 }
1047
1048 public int getState() {
1049 return m_state;
1050 }
1051
1052 public String getType() {
1053 return m_type;
1054 }
1055 }
1056
Marcel Offermansfaaed472010-09-08 10:07:32 +00001057 public ComponentDependencyDeclaration[] getComponentDependencies() {
Marcel Offermansa962bc92009-11-21 17:59:33 +00001058 List deps = getDependencies();
1059 if (deps != null) {
Marcel Offermansfaaed472010-09-08 10:07:32 +00001060 ComponentDependencyDeclaration[] result = new ComponentDependencyDeclaration[deps.size()];
Marcel Offermansa962bc92009-11-21 17:59:33 +00001061 for (int i = 0; i < result.length; i++) {
1062 Dependency dep = (Dependency) deps.get(i);
Marcel Offermansfaaed472010-09-08 10:07:32 +00001063 if (dep instanceof ComponentDependencyDeclaration) {
1064 result[i] = (ComponentDependencyDeclaration) dep;
Marcel Offermansa962bc92009-11-21 17:59:33 +00001065 }
1066 else {
1067 result[i] = new SCDImpl(dep.toString(), (dep.isAvailable() ? 1 : 0) + (dep.isRequired() ? 2 : 0), dep.getClass().getName());
1068 }
1069 }
1070 return result;
1071 }
1072 return null;
1073 }
1074
1075 public String getName() {
Marcel Offermansbd15a442010-09-07 07:50:09 +00001076 Object serviceName = m_serviceName;
1077 if (serviceName instanceof String[]) {
Marcel Offermansa962bc92009-11-21 17:59:33 +00001078 StringBuffer sb = new StringBuffer();
Marcel Offermansbd15a442010-09-07 07:50:09 +00001079 String[] names = (String[]) serviceName;
Marcel Offermansa962bc92009-11-21 17:59:33 +00001080 for (int i = 0; i < names.length; i++) {
1081 if (i > 0) {
1082 sb.append(", ");
1083 }
1084 sb.append(names[i]);
1085 }
Marcel Offermans5be5f142011-04-26 10:47:12 +00001086 sb.append('(');
1087 sb.append(propertiesToString());
1088 sb.append(')');
Marcel Offermansa962bc92009-11-21 17:59:33 +00001089 return sb.toString();
1090 }
Marcel Offermansbd15a442010-09-07 07:50:09 +00001091 else if (serviceName instanceof String) {
Marcel Offermans5be5f142011-04-26 10:47:12 +00001092 return serviceName.toString() + "(" + propertiesToString() + ")";
Marcel Offermansa962bc92009-11-21 17:59:33 +00001093 }
1094 else {
Marcel Offermansbd15a442010-09-07 07:50:09 +00001095 Object implementation = m_implementation;
1096 if (implementation != null) {
1097 return implementation.toString();
1098 }
1099 else {
1100 return super.toString();
1101 }
Marcel Offermansa962bc92009-11-21 17:59:33 +00001102 }
1103 }
Marcel Offermans5be5f142011-04-26 10:47:12 +00001104
1105 private String propertiesToString() {
1106 StringBuffer result = new StringBuffer();
1107 Dictionary properties = calculateServiceProperties();
1108 if (properties != null) {
1109 Enumeration enumeration = properties.keys();
1110 while (enumeration.hasMoreElements()) {
Marcel Offermans66df0b82011-04-27 21:48:41 +00001111 Object key = enumeration.nextElement();
Marcel Offermans5be5f142011-04-26 10:47:12 +00001112 if (result.length() > 0) {
1113 result.append(',');
1114 }
Marcel Offermans66df0b82011-04-27 21:48:41 +00001115 result.append(key.toString());
Marcel Offermans5be5f142011-04-26 10:47:12 +00001116 result.append('=');
1117 Object value = properties.get(key);
1118 if (value instanceof String[]) {
1119 String[] values = (String[]) value;
1120 result.append('{');
1121 for (int i = 0; i < values.length; i++) {
1122 if (i > 0) {
1123 result.append(',');
1124 }
1125 result.append(values[i].toString());
1126 }
1127 result.append('}');
1128 }
1129 else {
1130 result.append(value.toString());
1131 }
1132 }
1133 }
1134 return result.toString();
1135 }
Marcel Offermansa962bc92009-11-21 17:59:33 +00001136
1137 public int getState() {
1138 return (isRegistered() ? 1 : 0);
1139 }
1140
Marcel Offermansea89b862010-06-24 13:14:43 +00001141 public DependencyManager getDependencyManager() {
1142 return m_manager;
1143 }
1144
Marcel Offermansa962bc92009-11-21 17:59:33 +00001145 static {
Marcel Offermansfaaed472010-09-08 10:07:32 +00001146 NULL_REGISTRATION = (ServiceRegistration) Proxy.newProxyInstance(ComponentImpl.class.getClassLoader(), new Class[] {ServiceRegistration.class}, new DefaultNullObject());
Marcel Offermansa962bc92009-11-21 17:59:33 +00001147 }
Marcel Offermans5be5f142011-04-26 10:47:12 +00001148
1149 public BundleContext getBundleContext() {
1150 return m_context;
1151 }
1152
1153 public int compareTo(Object object) {
1154 if (object instanceof ComponentImpl) {
1155 ComponentImpl other = (ComponentImpl) object;
1156 long id1 = this.getBundleContext().getBundle().getBundleId();
1157 long id2 = ((ComponentImpl) other).getBundleContext().getBundle().getBundleId();
1158 if (id1 == id2) {
1159 return (int)(this.m_id - other.m_id);
1160 }
1161 return (int)(id1 - id2);
1162 }
1163 return -1;
1164 }
Marcel Offermansa962bc92009-11-21 17:59:33 +00001165}