blob: 25674d83ce40b86ca32f793fe17834a6fb9a2415 [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;
Pierre De Rop438a6852013-10-25 18:39:03 +000026import java.util.Arrays;
Marcel Offermansa962bc92009-11-21 17:59:33 +000027import java.util.Dictionary;
28import java.util.Enumeration;
29import java.util.HashMap;
30import java.util.Hashtable;
31import java.util.Iterator;
32import java.util.List;
33import java.util.Map;
34import java.util.Properties;
35
Marcel Offermansfaaed472010-09-08 10:07:32 +000036import org.apache.felix.dm.Component;
37import org.apache.felix.dm.ComponentDeclaration;
38import org.apache.felix.dm.ComponentDependencyDeclaration;
39import org.apache.felix.dm.ComponentStateListener;
Marcel Offermans8b93efa2010-07-02 18:27:21 +000040import org.apache.felix.dm.Dependency;
Marcel Offermans3d921212010-08-09 13:37:02 +000041import org.apache.felix.dm.DependencyActivation;
Pierre De Ropd2ec3952009-12-04 22:40:05 +000042import org.apache.felix.dm.DependencyManager;
Marcel Offermans3d921212010-08-09 13:37:02 +000043import org.apache.felix.dm.DependencyService;
Marcel Offermans706fb272010-11-15 12:52:58 +000044import org.apache.felix.dm.InvocationUtil;
Marcel Offermansa962bc92009-11-21 17:59:33 +000045import org.osgi.framework.BundleContext;
46import org.osgi.framework.ServiceRegistration;
47
48/**
Marcel Offermansfaaed472010-09-08 10:07:32 +000049 * Component implementation.
Marcel Offermansa962bc92009-11-21 17:59:33 +000050 *
51 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
52 */
Marcel Offermans5be5f142011-04-26 10:47:12 +000053public class ComponentImpl implements Component, DependencyService, ComponentDeclaration, Comparable {
Marcel Offermansa962bc92009-11-21 17:59:33 +000054 private static final Class[] VOID = new Class[] {};
55 private static final ServiceRegistration NULL_REGISTRATION;
Marcel Offermansfaaed472010-09-08 10:07:32 +000056 private static final ComponentStateListener[] SERVICE_STATE_LISTENER_TYPE = new ComponentStateListener[] {};
Marcel Offermans5be5f142011-04-26 10:47:12 +000057 private static long HIGHEST_ID = 0;
Marcel Offermansa962bc92009-11-21 17:59:33 +000058
Marcel Offermanse14b3422009-11-25 23:04:32 +000059 private final Object SYNC = new Object();
Marcel Offermansa962bc92009-11-21 17:59:33 +000060 private final BundleContext m_context;
61 private final DependencyManager m_manager;
Marcel Offermans5be5f142011-04-26 10:47:12 +000062 private final long m_id;
Marcel Offermansa962bc92009-11-21 17:59:33 +000063
64 // configuration (static)
65 private String m_callbackInit;
66 private String m_callbackStart;
67 private String m_callbackStop;
68 private String m_callbackDestroy;
Pierre De Rop438a6852013-10-25 18:39:03 +000069 private volatile Object m_serviceName;
70 private volatile Object m_implementation;
71 private volatile Object m_callbackInstance;
Marcel Offermansa962bc92009-11-21 17:59:33 +000072
73 // configuration (dynamic, but does not affect state)
Pierre De Rop438a6852013-10-25 18:39:03 +000074 private volatile Dictionary m_serviceProperties;
Marcel Offermansa962bc92009-11-21 17:59:33 +000075
76 // configuration (dynamic, and affects state)
Pierre De Rop438a6852013-10-25 18:39:03 +000077 private final ArrayList m_dependencies = new ArrayList();
Marcel Offermansa962bc92009-11-21 17:59:33 +000078
79 // runtime state (calculated from dependencies)
80 private State m_state;
81
82 // runtime state (changes because of state changes)
Pierre De Rop438a6852013-10-25 18:39:03 +000083 private volatile Object m_serviceInstance;
Marcel Offermansa1bc22a2010-12-28 18:52:24 +000084 private volatile ServiceRegistration m_registration;
Pierre De Rop438a6852013-10-25 18:39:03 +000085 private volatile boolean m_isBound;
86 private volatile boolean m_isInstantiated;
Marcel Offermansa962bc92009-11-21 17:59:33 +000087
88 // service state listeners
89 private final List m_stateListeners = new ArrayList();
90
91 // work queue
92 private final SerialExecutor m_executor = new SerialExecutor();
93
94 // instance factory
Pierre De Rop438a6852013-10-25 18:39:03 +000095 private volatile Object m_instanceFactory;
96 private volatile String m_instanceFactoryCreateMethod;
Marcel Offermansa962bc92009-11-21 17:59:33 +000097
98 // composition manager
Pierre De Rop438a6852013-10-25 18:39:03 +000099 private volatile Object m_compositionManager;
100 private volatile String m_compositionManagerGetMethod;
101 private volatile Object m_compositionManagerInstance;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000102
103 // internal logging
104 private final Logger m_logger;
Marcel Offermans5be5f142011-04-26 10:47:12 +0000105
Pierre De Rop438a6852013-10-25 18:39:03 +0000106 private final Map m_autoConfig = new HashMap();
107 private final Map m_autoConfigInstance = new HashMap();
Marcel Offermans5be5f142011-04-26 10:47:12 +0000108
109 private boolean m_isStarted = false;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000110
Marcel Offermansfaaed472010-09-08 10:07:32 +0000111 public ComponentImpl(BundleContext context, DependencyManager manager, Logger logger) {
Marcel Offermans5be5f142011-04-26 10:47:12 +0000112 synchronized (VOID) {
113 m_id = HIGHEST_ID++;
114 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000115 m_logger = logger;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000116 m_state = new State((List) m_dependencies.clone(), false, false, false);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000117 m_context = context;
118 m_manager = manager;
119 m_callbackInit = "init";
120 m_callbackStart = "start";
121 m_callbackStop = "stop";
122 m_callbackDestroy = "destroy";
123 m_implementation = null;
124 m_autoConfig.put(BundleContext.class, Boolean.TRUE);
125 m_autoConfig.put(ServiceRegistration.class, Boolean.TRUE);
126 m_autoConfig.put(DependencyManager.class, Boolean.TRUE);
Marcel Offermansfaaed472010-09-08 10:07:32 +0000127 m_autoConfig.put(Component.class, Boolean.TRUE);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000128 }
129
Marcel Offermanse14b3422009-11-25 23:04:32 +0000130 private void calculateStateChanges() {
131 // see if any of the things we did caused a further change of state
132 State oldState, newState;
133 synchronized (m_dependencies) {
134 oldState = m_state;
135 newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
136 m_state = newState;
137 }
138 calculateStateChanges(oldState, newState);
139 }
140
Marcel Offermansa962bc92009-11-21 17:59:33 +0000141 private void calculateStateChanges(final State oldState, final State newState) {
Marcel Offermanse14b3422009-11-25 23:04:32 +0000142 if (oldState.isInactive() && (newState.isTrackingOptional())) {
143 m_executor.enqueue(new Runnable() {
144 public void run() {
145 activateService(newState);
146 }});
147 }
148 if (oldState.isInactive() && (newState.isWaitingForRequired())) {
149 m_executor.enqueue(new Runnable() {
150 public void run() {
151 startTrackingRequired(newState);
152 }});
153 }
154 if (oldState.isWaitingForRequired() && newState.isTrackingOptional()) {
155 m_executor.enqueue(new Runnable() {
156 public void run() {
157 activateService(newState);
158 }});
159 }
160 if ((oldState.isWaitingForRequired()) && newState.isInactive()) {
161 m_executor.enqueue(new Runnable() {
162 public void run() {
163 stopTrackingRequired(oldState);
164 }});
165 }
166 if (oldState.isTrackingOptional() && newState.isWaitingForRequiredInstantiated()) {
167 m_executor.enqueue(new Runnable() {
168 public void run() {
169 // TODO as far as I can see there is nothing left to do here
Marcel Offermans5be5f142011-04-26 10:47:12 +0000170 // unbindService(newState);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000171 }});
172 }
173 if (oldState.isTrackingOptional() && newState.isWaitingForRequired()) {
174 m_executor.enqueue(new Runnable() {
175 public void run() {
176 deactivateService(oldState);
177 }});
178 }
179 if (oldState.isTrackingOptional() && newState.isBound()) {
180 m_executor.enqueue(new Runnable() {
181 public void run() {
Marcel Offermansbedf3692010-06-06 20:07:12 +0000182 bindService(newState);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000183 }});
184 }
185 if (oldState.isTrackingOptional() && newState.isInactive()) {
186 m_executor.enqueue(new Runnable() {
187 public void run() {
188 deactivateService(oldState);
189 stopTrackingRequired(oldState);
190 }});
191 }
192 if (oldState.isWaitingForRequiredInstantiated() && newState.isWaitingForRequired()) {
193 m_executor.enqueue(new Runnable() {
194 public void run() {
195 deactivateService(oldState);
196 }});
197 }
198 if (oldState.isWaitingForRequiredInstantiated() && newState.isInactive()) {
199 m_executor.enqueue(new Runnable() {
200 public void run() {
201 deactivateService(oldState);
202 stopTrackingRequired(oldState);
203 }});
204 }
205 if (oldState.isWaitingForRequiredInstantiated() && newState.isBound()) {
206 m_executor.enqueue(new Runnable() {
207 public void run() {
Marcel Offermansbedf3692010-06-06 20:07:12 +0000208 bindService(newState);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000209 }});
210 }
211 if (oldState.isBound() && newState.isWaitingForRequiredInstantiated()) {
212 m_executor.enqueue(new Runnable() {
213 public void run() {
214 unbindService(oldState);
215 }});
216 }
217 if (oldState.isBound() && newState.isWaitingForRequired()) {
218 m_executor.enqueue(new Runnable() {
219 public void run() {
220 unbindService(oldState);
221 deactivateService(oldState);
222 }});
223 }
224 if (oldState.isBound() && newState.isInactive()) {
225 m_executor.enqueue(new Runnable() {
226 public void run() {
227 unbindService(oldState);
228 deactivateService(oldState);
229 stopTrackingRequired(oldState);
230 }});
231 }
232 m_executor.execute();
Marcel Offermansa962bc92009-11-21 17:59:33 +0000233 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000234
Marcel Offermansf9a7e342010-10-07 12:22:46 +0000235 // TODO fix code duplication between add(Dependency) and add(List)
Marcel Offermansfaaed472010-09-08 10:07:32 +0000236 public Component add(final Dependency dependency) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000237 State oldState, newState;
238 synchronized (m_dependencies) {
239 oldState = m_state;
240 m_dependencies.add(dependency);
241 }
Pierre De Rop79ac9712010-06-11 06:02:07 +0000242
Marcel Offermansf9a7e342010-10-07 12:22:46 +0000243 // if we're inactive, don't do anything, otherwise we might want to start
244 // the dependency
245 if (!oldState.isInactive()) {
246 // if the dependency is required, it should be started regardless of the state
247 // we're in
248 if (dependency.isRequired()) {
249 ((DependencyActivation) dependency).start(this);
250 }
251 else {
252 // if the dependency is optional, it should only be started if we're in
253 // bound state
254 if (oldState.isBound()) {
255 ((DependencyActivation) dependency).start(this);
256 }
257 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000258 }
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000259
Marcel Offermansa962bc92009-11-21 17:59:33 +0000260 synchronized (m_dependencies) {
Marcel Offermans0acdb1b2010-10-14 14:43:03 +0000261 oldState = m_state;
Marcel Offermans306c2522009-12-17 13:57:58 +0000262 // starting the dependency above might have triggered another state change, so
263 // we have to fetch the current state again
Marcel Offermanse14b3422009-11-25 23:04:32 +0000264 newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000265 m_state = newState;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000266 }
267 calculateStateChanges(oldState, newState);
268 return this;
269 }
Marcel Offermansf9a7e342010-10-07 12:22:46 +0000270
Marcel Offermansfaaed472010-09-08 10:07:32 +0000271 public Component add(List dependencies) {
Marcel Offermansf9a7e342010-10-07 12:22:46 +0000272 State oldState, newState;
273 synchronized (m_dependencies) {
274 oldState = m_state;
275 for (int i = 0; i < dependencies.size(); i++) {
276 m_dependencies.add(dependencies.get(i));
277 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000278 }
Marcel Offermansf9a7e342010-10-07 12:22:46 +0000279
280 // if we're inactive, don't do anything, otherwise we might want to start
281 // the dependencies
282 if (!oldState.isInactive()) {
283 for (int i = 0; i < dependencies.size(); i++) {
284 Dependency dependency = (Dependency) dependencies.get(i);
285 // if the dependency is required, it should be started regardless of the state
286 // we're in
287 if (dependency.isRequired()) {
288 ((DependencyActivation) dependency).start(this);
289 }
290 else {
291 // if the dependency is optional, it should only be started if we're in
292 // bound state
293 if (oldState.isBound()) {
294 ((DependencyActivation) dependency).start(this);
295 }
296 }
297 }
298 }
299
300 synchronized (m_dependencies) {
Pierre De Rop761a4492010-10-16 19:26:25 +0000301 oldState = m_state;
Marcel Offermansf9a7e342010-10-07 12:22:46 +0000302 // starting the dependency above might have triggered another state change, so
303 // we have to fetch the current state again
304 newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
305 m_state = newState;
306 }
307 calculateStateChanges(oldState, newState);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000308 return this;
309 }
310
Marcel Offermansfaaed472010-09-08 10:07:32 +0000311 public Component remove(Dependency dependency) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000312 State oldState, newState;
313 synchronized (m_dependencies) {
314 oldState = m_state;
315 m_dependencies.remove(dependency);
316 }
Marcel Offermans0acdb1b2010-10-14 14:43:03 +0000317 if (oldState.isAllRequiredAvailable() || ((oldState.isWaitingForRequired() || oldState.isWaitingForRequiredInstantiated()) && dependency.isRequired())) {
Pierre De Ropd2ec3952009-12-04 22:40:05 +0000318 ((DependencyActivation) dependency).stop(this);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000319 }
320 synchronized (m_dependencies) {
Marcel Offermans306c2522009-12-17 13:57:58 +0000321 // starting the dependency above might have triggered another state change, so
322 // we have to fetch the current state again
323 oldState = m_state;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000324 newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000325 m_state = newState;
326 }
327 calculateStateChanges(oldState, newState);
328 return this;
329 }
330
331 public List getDependencies() {
332 synchronized (m_dependencies) {
333 return (List) m_dependencies.clone();
334 }
335 }
336
337 public ServiceRegistration getServiceRegistration() {
338 return m_registration;
339 }
340
341 public Object getService() {
342 return m_serviceInstance;
343 }
Marcel Offermansea89b862010-06-24 13:14:43 +0000344
Marcel Offermansfaaed472010-09-08 10:07:32 +0000345 public Component getServiceInterface() {
Marcel Offermansea89b862010-06-24 13:14:43 +0000346 return this;
347 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000348
349 public void dependencyAvailable(final Dependency dependency) {
350 State oldState, newState;
351 synchronized (m_dependencies) {
352 oldState = m_state;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000353 newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000354 m_state = newState;
355 }
Marcel Offermans6cb7ac22010-01-04 09:32:37 +0000356 if (newState.isAllRequiredAvailable() || newState.isWaitingForRequiredInstantiated()) {
Marcel Offermans84a43ad2009-12-29 14:54:48 +0000357 updateInstance(dependency);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000358 }
Marcel Offermans306c2522009-12-17 13:57:58 +0000359 calculateStateChanges(oldState, newState);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000360 }
361
362 public void dependencyChanged(final Dependency dependency) {
363 State state;
364 synchronized (m_dependencies) {
365 state = m_state;
366 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000367 if (state.isAllRequiredAvailable()) {
Marcel Offermans84a43ad2009-12-29 14:54:48 +0000368 updateInstance(dependency);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000369 }
370 }
371
372 public void dependencyUnavailable(final Dependency dependency) {
373 State oldState, newState;
374 synchronized (m_dependencies) {
375 oldState = m_state;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000376 newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000377 m_state = newState;
378 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000379 if (newState.isAllRequiredAvailable()) {
Marcel Offermans84a43ad2009-12-29 14:54:48 +0000380 updateInstance(dependency);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000381 }
Marcel Offermans306c2522009-12-17 13:57:58 +0000382 calculateStateChanges(oldState, newState);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000383 }
384
Marcel Offermansfacde682012-06-04 11:56:07 +0000385 public void start() {
386 boolean needsStarting = false;
387 synchronized (this) {
388 if (!m_isStarted) {
389 m_isStarted = true;
390 needsStarting = true;
391 }
392 }
393 if (needsStarting) {
Marcel Offermansd60b54d2011-01-21 20:38:55 +0000394 State oldState, newState;
Marcel Offermans6358e052010-01-04 14:36:08 +0000395 synchronized (m_dependencies) {
Marcel Offermansd60b54d2011-01-21 20:38:55 +0000396 oldState = m_state;
Marcel Offermans6358e052010-01-04 14:36:08 +0000397 newState = new State((List) m_dependencies.clone(), true, m_isInstantiated, m_isBound);
398 m_state = newState;
399 }
400 calculateStateChanges(oldState, newState);
401 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000402 }
403
Marcel Offermansfacde682012-06-04 11:56:07 +0000404 public void stop() {
405 boolean needsStopping = false;
406 synchronized (this) {
407 if (m_isStarted) {
408 m_isStarted = false;
409 needsStopping = true;
410 }
411 }
412 if (needsStopping) {
Marcel Offermansd60b54d2011-01-21 20:38:55 +0000413 State oldState, newState;
Marcel Offermans6358e052010-01-04 14:36:08 +0000414 synchronized (m_dependencies) {
Marcel Offermansd60b54d2011-01-21 20:38:55 +0000415 oldState = m_state;
Marcel Offermans6358e052010-01-04 14:36:08 +0000416 newState = new State((List) m_dependencies.clone(), false, m_isInstantiated, m_isBound);
417 m_state = newState;
418 }
419 calculateStateChanges(oldState, newState);
Marcel Offermans6358e052010-01-04 14:36:08 +0000420 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000421 }
422
Marcel Offermansfaaed472010-09-08 10:07:32 +0000423 public synchronized Component setInterface(String serviceName, Dictionary properties) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000424 ensureNotActive();
425 m_serviceName = serviceName;
426 m_serviceProperties = properties;
427 return this;
428 }
429
Marcel Offermansfaaed472010-09-08 10:07:32 +0000430 public synchronized Component setInterface(String[] serviceName, Dictionary properties) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000431 ensureNotActive();
432 m_serviceName = serviceName;
433 m_serviceProperties = properties;
434 return this;
435 }
436
Marcel Offermansfaaed472010-09-08 10:07:32 +0000437 public synchronized Component setCallbacks(String init, String start, String stop, String destroy) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000438 ensureNotActive();
439 m_callbackInit = init;
440 m_callbackStart = start;
441 m_callbackStop = stop;
442 m_callbackDestroy = destroy;
443 return this;
444 }
Marcel Offermans61a81142010-04-02 15:16:50 +0000445
Marcel Offermansfaaed472010-09-08 10:07:32 +0000446 public synchronized Component setCallbacks(Object instance, String init, String start, String stop, String destroy) {
Marcel Offermans61a81142010-04-02 15:16:50 +0000447 ensureNotActive();
448 m_callbackInstance = instance;
449 m_callbackInit = init;
450 m_callbackStart = start;
451 m_callbackStop = stop;
452 m_callbackDestroy = destroy;
453 return this;
454 }
455
Marcel Offermansfaaed472010-09-08 10:07:32 +0000456 public synchronized Component setImplementation(Object implementation) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000457 ensureNotActive();
458 m_implementation = implementation;
459 return this;
460 }
461
Marcel Offermansfaaed472010-09-08 10:07:32 +0000462 public synchronized Component setFactory(Object factory, String createMethod) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000463 ensureNotActive();
464 m_instanceFactory = factory;
465 m_instanceFactoryCreateMethod = createMethod;
466 return this;
467 }
468
Marcel Offermansfaaed472010-09-08 10:07:32 +0000469 public synchronized Component setFactory(String createMethod) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000470 return setFactory(null, createMethod);
471 }
472
Marcel Offermansfaaed472010-09-08 10:07:32 +0000473 public synchronized Component setComposition(Object instance, String getMethod) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000474 ensureNotActive();
475 m_compositionManager = instance;
476 m_compositionManagerGetMethod = getMethod;
477 return this;
478 }
479
Marcel Offermansfaaed472010-09-08 10:07:32 +0000480 public synchronized Component setComposition(String getMethod) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000481 return setComposition(null, getMethod);
482 }
483
484 public String toString() {
Marcel Offermans706fb272010-11-15 12:52:58 +0000485 return this.getClass().getSimpleName() + "[" + m_serviceName + " " + m_implementation + "]";
Marcel Offermansa962bc92009-11-21 17:59:33 +0000486 }
487
488 public synchronized Dictionary getServiceProperties() {
489 if (m_serviceProperties != null) {
490 return (Dictionary) ((Hashtable) m_serviceProperties).clone();
491 }
492 return null;
493 }
494
Marcel Offermansfacde682012-06-04 11:56:07 +0000495 public Component setServiceProperties(Dictionary serviceProperties) {
496 boolean needsProperties = false;
497 Dictionary properties = null;
498 synchronized (this) {
499 m_serviceProperties = serviceProperties;
500 if ((m_registration != null) && (m_serviceName != null)) {
501 properties = calculateServiceProperties();
502 needsProperties = true;
503 }
504 }
505 if (needsProperties) {
506 m_registration.setProperties(properties);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000507 }
Pierre De Rop19476fe2010-05-23 08:13:58 +0000508 return this;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000509 }
510
511 // service state listener methods
Marcel Offermansfaaed472010-09-08 10:07:32 +0000512 public void addStateListener(ComponentStateListener listener) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000513 synchronized (m_stateListeners) {
514 m_stateListeners.add(listener);
515 }
516 // when we register as a listener and the service is already started
517 // make sure we invoke the right callbacks so the listener knows
518 State state;
519 synchronized (m_dependencies) {
520 state = m_state;
521 }
Marcel Offermansdeda4322011-03-02 16:00:05 +0000522 if (state.isBound()) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000523 listener.starting(this);
524 listener.started(this);
525 }
526 }
527
Marcel Offermansfaaed472010-09-08 10:07:32 +0000528 public void removeStateListener(ComponentStateListener listener) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000529 synchronized (m_stateListeners) {
530 m_stateListeners.remove(listener);
531 }
532 }
533
Marcel Offermanse14b3422009-11-25 23:04:32 +0000534 public void removeStateListeners() {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000535 synchronized (m_stateListeners) {
536 m_stateListeners.clear();
537 }
538 }
539
540 private void stateListenersStarting() {
Marcel Offermansfaaed472010-09-08 10:07:32 +0000541 ComponentStateListener[] list = getListeners();
Marcel Offermansa962bc92009-11-21 17:59:33 +0000542 for (int i = 0; i < list.length; i++) {
543 try {
544 list[i].starting(this);
545 }
546 catch (Throwable t) {
547 m_logger.log(Logger.LOG_ERROR, "Error invoking listener starting method.", t);
548 }
549 }
550 }
551
552 private void stateListenersStarted() {
Marcel Offermansfaaed472010-09-08 10:07:32 +0000553 ComponentStateListener[] list = getListeners();
Marcel Offermansa962bc92009-11-21 17:59:33 +0000554 for (int i = 0; i < list.length; i++) {
555 try {
556 list[i].started(this);
557 }
558 catch (Throwable t) {
559 m_logger.log(Logger.LOG_ERROR, "Error invoking listener started method.", t);
560 }
561 }
562 }
563
564 private void stateListenersStopping() {
Marcel Offermansfaaed472010-09-08 10:07:32 +0000565 ComponentStateListener[] list = getListeners();
Marcel Offermansa962bc92009-11-21 17:59:33 +0000566 for (int i = 0; i < list.length; i++) {
567 try {
568 list[i].stopping(this);
569 }
570 catch (Throwable t) {
571 m_logger.log(Logger.LOG_ERROR, "Error invoking listener stopping method.", t);
572 }
573 }
574 }
575
576 private void stateListenersStopped() {
Marcel Offermansfaaed472010-09-08 10:07:32 +0000577 ComponentStateListener[] list = getListeners();
Marcel Offermansa962bc92009-11-21 17:59:33 +0000578 for (int i = 0; i < list.length; i++) {
579 try {
580 list[i].stopped(this);
581 }
582 catch (Throwable t) {
583 m_logger.log(Logger.LOG_ERROR, "Error invoking listener stopped method.", t);
584 }
585 }
586 }
587
Marcel Offermansfaaed472010-09-08 10:07:32 +0000588 private ComponentStateListener[] getListeners() {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000589 synchronized (m_stateListeners) {
Marcel Offermansfaaed472010-09-08 10:07:32 +0000590 return (ComponentStateListener[]) m_stateListeners.toArray(SERVICE_STATE_LISTENER_TYPE);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000591 }
592 }
593
Marcel Offermanse14b3422009-11-25 23:04:32 +0000594 private void activateService(State state) {
595 String init;
596 synchronized (this) {
597 init = m_callbackInit;
598 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000599 // service activation logic, first we initialize the service instance itself
600 // meaning it is created if necessary and the bundle context is set
601 initService();
Marcel Offermansa962bc92009-11-21 17:59:33 +0000602 // now is the time to configure the service, meaning all required
603 // dependencies will be set and any callbacks called
604 configureService(state);
Marcel Offermans78e5dfc2009-12-10 13:52:49 +0000605 // flag that our instance has been created
606 m_isInstantiated = true;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000607 // then we invoke the init callback so the service can further initialize
608 // itself
609 invoke(init);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000610 // see if any of this caused further state changes
611 calculateStateChanges();
612 }
613
614 private void bindService(State state) {
615 String start;
616 synchronized (this) {
617 start = m_callbackStart;
618 }
Pierre De Rop79ac9712010-06-11 06:02:07 +0000619
Marcel Offermans0acdb1b2010-10-14 14:43:03 +0000620 // configure service with extra-dependencies which might have been added from init() method.
Pierre De Rop79ac9712010-06-11 06:02:07 +0000621 configureServiceWithExtraDependencies(state);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000622 // inform the state listeners we're starting
623 stateListenersStarting();
624 // invoke the start callback, since we're now ready to be used
625 invoke(start);
626 // start tracking optional services
627 startTrackingOptional(state);
628 // register the service in the framework's service registry
629 registerService();
630 // inform the state listeners we've started
631 stateListenersStarted();
632 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000633
Marcel Offermans0acdb1b2010-10-14 14:43:03 +0000634 private void configureServiceWithExtraDependencies(State state) {
Pierre De Rop79ac9712010-06-11 06:02:07 +0000635 Iterator i = state.getDependencies().iterator();
636 while (i.hasNext()) {
637 Dependency dependency = (Dependency) i.next();
638 if (dependency.isAutoConfig() && dependency.isInstanceBound()) {
639 configureImplementation(dependency.getAutoConfigType(), dependency.getAutoConfigInstance(), dependency.getAutoConfigName());
640 }
Pierre De Rop79ac9712010-06-11 06:02:07 +0000641 }
642 }
643
Marcel Offermanse14b3422009-11-25 23:04:32 +0000644 private void unbindService(State state) {
645 String stop;
646 synchronized (this) {
647 stop = m_callbackStop;
648 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000649 // service deactivation logic, first inform the state listeners
650 // we're stopping
651 stateListenersStopping();
652 // then, unregister the service from the framework
653 unregisterService();
654 // stop tracking optional services
655 stopTrackingOptional(state);
656 // invoke the stop callback
657 invoke(stop);
658 // inform the state listeners we've stopped
659 stateListenersStopped();
Marcel Offermanse14b3422009-11-25 23:04:32 +0000660 }
661
662 private void deactivateService(State state) {
663 String destroy;
664 synchronized (this) {
665 destroy = m_callbackDestroy;
666 }
Marcel Offermans78e5dfc2009-12-10 13:52:49 +0000667 // flag that our instance was destroyed
668 m_isInstantiated = false;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000669 // invoke the destroy callback
670 invoke(destroy);
671 // destroy the service instance
672 destroyService(state);
673 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000674
Marcel Offermansa962bc92009-11-21 17:59:33 +0000675 private void invoke(String name) {
676 if (name != null) {
Marcel Offermansea89b862010-06-24 13:14:43 +0000677 // if a callback instance was specified, look for the method there, if not,
678 // ask the service for its composition instances
679 Object[] instances = m_callbackInstance != null ? new Object[] { m_callbackInstance } : getCompositionInstances();
680 invokeCallbackMethod(instances, name,
Marcel Offermansfaaed472010-09-08 10:07:32 +0000681 new Class[][] {{ Component.class }, {}},
Marcel Offermansea89b862010-06-24 13:14:43 +0000682 new Object[][] {{ this }, {}});
683 }
684 }
685
686 public void invokeCallbackMethod(Object[] instances, String methodName, Class[][] signatures, Object[][] parameters) {
687 for (int i = 0; i < instances.length; i++) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000688 try {
Marcel Offermansea89b862010-06-24 13:14:43 +0000689 InvocationUtil.invokeCallbackMethod(instances[i], methodName, signatures, parameters);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000690 }
Marcel Offermanse43114b2010-04-04 18:37:44 +0000691 catch (NoSuchMethodException e) {
Marcel Offermansea89b862010-06-24 13:14:43 +0000692 // if the method does not exist, ignore it
693 }
694 catch (InvocationTargetException e) {
695 // the method itself threw an exception, log that
696 m_logger.log(Logger.LOG_WARNING, "Invocation of '" + methodName + "' failed.", e.getCause());
Marcel Offermanse43114b2010-04-04 18:37:44 +0000697 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000698 catch (Exception e) {
Marcel Offermansea89b862010-06-24 13:14:43 +0000699 m_logger.log(Logger.LOG_WARNING, "Could not invoke '" + methodName + "'.", e);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000700 }
701 }
702 }
703
704 private void startTrackingOptional(State state) {
705 Iterator i = state.getDependencies().iterator();
706 while (i.hasNext()) {
707 Dependency dependency = (Dependency) i.next();
708 if (!dependency.isRequired()) {
Pierre De Ropd2ec3952009-12-04 22:40:05 +0000709 ((DependencyActivation) dependency).start(this);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000710 }
711 }
712 }
713
714 private void stopTrackingOptional(State state) {
715 Iterator i = state.getDependencies().iterator();
716 while (i.hasNext()) {
717 Dependency dependency = (Dependency) i.next();
718 if (!dependency.isRequired()) {
Pierre De Ropd2ec3952009-12-04 22:40:05 +0000719 ((DependencyActivation) dependency).stop(this);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000720 }
721 }
722 }
723
724 private void startTrackingRequired(State state) {
725 Iterator i = state.getDependencies().iterator();
726 while (i.hasNext()) {
727 Dependency dependency = (Dependency) i.next();
728 if (dependency.isRequired()) {
Pierre De Ropd2ec3952009-12-04 22:40:05 +0000729 ((DependencyActivation) dependency).start(this);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000730 }
731 }
732 }
733
734 private void stopTrackingRequired(State state) {
735 Iterator i = state.getDependencies().iterator();
736 while (i.hasNext()) {
737 Dependency dependency = (Dependency) i.next();
738 if (dependency.isRequired()) {
Pierre De Ropd2ec3952009-12-04 22:40:05 +0000739 ((DependencyActivation) dependency).stop(this);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000740 }
741 }
742 }
743
Marcel Offermans392c2022011-03-25 01:09:12 +0000744 private Object createInstance(Class clazz) throws SecurityException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000745 Constructor constructor = clazz.getConstructor(VOID);
746 constructor.setAccessible(true);
Marcel Offermans392c2022011-03-25 01:09:12 +0000747 return constructor.newInstance(null);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000748 }
749
Marcel Offermanse14b3422009-11-25 23:04:32 +0000750 public void initService() {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000751 if (m_serviceInstance == null) {
752 if (m_implementation instanceof Class) {
753 // instantiate
754 try {
755 m_serviceInstance = createInstance((Class) m_implementation);
756 }
757 catch (Exception e) {
758 m_logger.log(Logger.LOG_ERROR, "Could not create service instance of class " + m_implementation + ".", e);
759 }
760 }
761 else {
762 if (m_instanceFactoryCreateMethod != null) {
763 Object factory = null;
764 if (m_instanceFactory != null) {
765 if (m_instanceFactory instanceof Class) {
766 try {
767 factory = createInstance((Class) m_instanceFactory);
768 }
769 catch (Exception e) {
770 m_logger.log(Logger.LOG_ERROR, "Could not create factory instance of class " + m_instanceFactory + ".", e);
771 }
772 }
773 else {
774 factory = m_instanceFactory;
775 }
776 }
777 else {
778 // TODO review if we want to try to default to something if not specified
779 // for now the JavaDoc of setFactory(method) reflects the fact that we need
780 // to review it
781 }
782 if (factory == null) {
783 m_logger.log(Logger.LOG_ERROR, "Factory cannot be null.");
784 }
785 else {
786 try {
Marcel Offermansa6ffb992010-05-19 11:56:44 +0000787 m_serviceInstance = InvocationUtil.invokeMethod(factory, factory.getClass(), m_instanceFactoryCreateMethod, new Class[][] {{}}, new Object[][] {{}}, false);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000788 }
789 catch (Exception e) {
790 m_logger.log(Logger.LOG_ERROR, "Could not create service instance using factory " + factory + " method " + m_instanceFactoryCreateMethod + ".", e);
791 }
792 }
793 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000794 if (m_serviceInstance == null) {
Marcel Offermanscc8adbb2010-02-17 10:20:11 +0000795 if (m_implementation == null) {
796 m_logger.log(Logger.LOG_ERROR, "Implementation cannot be null.");
797 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000798 m_serviceInstance = m_implementation;
799 }
800 }
801 // configure the bundle context
802 if (((Boolean) m_autoConfig.get(BundleContext.class)).booleanValue()) {
803 configureImplementation(BundleContext.class, m_context, (String) m_autoConfigInstance.get(BundleContext.class));
804 }
805 if (((Boolean) m_autoConfig.get(ServiceRegistration.class)).booleanValue()) {
806 configureImplementation(ServiceRegistration.class, NULL_REGISTRATION, (String) m_autoConfigInstance.get(ServiceRegistration.class));
807 }
808 if (((Boolean) m_autoConfig.get(DependencyManager.class)).booleanValue()) {
809 configureImplementation(DependencyManager.class, m_manager, (String) m_autoConfigInstance.get(DependencyManager.class));
810 }
Marcel Offermansfaaed472010-09-08 10:07:32 +0000811 if (((Boolean) m_autoConfig.get(Component.class)).booleanValue()) {
812 configureImplementation(Component.class, this, (String) m_autoConfigInstance.get(Component.class));
Marcel Offermanse14b3422009-11-25 23:04:32 +0000813 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000814 }
815 }
816
Marcel Offermansfaaed472010-09-08 10:07:32 +0000817 public synchronized Component setAutoConfig(Class clazz, boolean autoConfig) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000818 m_autoConfig.put(clazz, Boolean.valueOf(autoConfig));
Marcel Offermans3d921212010-08-09 13:37:02 +0000819 return this;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000820 }
821
Marcel Offermansfaaed472010-09-08 10:07:32 +0000822 public synchronized Component setAutoConfig(Class clazz, String instanceName) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000823 m_autoConfig.put(clazz, Boolean.valueOf(instanceName != null));
824 m_autoConfigInstance.put(clazz, instanceName);
Marcel Offermans3d921212010-08-09 13:37:02 +0000825 return this;
826 }
827
828 public boolean getAutoConfig(Class clazz) {
829 Boolean result = (Boolean) m_autoConfig.get(clazz);
830 return (result != null && result.booleanValue());
831 }
832
833 public String getAutoConfigInstance(Class clazz) {
834 return (String) m_autoConfigInstance.get(clazz);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000835 }
836
837 private void configureService(State state) {
838 // configure all services (the optional dependencies might be configured
839 // as null objects but that's what we want at this point)
840 configureServices(state);
841 }
842
843 private void destroyService(State state) {
844 unconfigureServices(state);
845 m_serviceInstance = null;
846 }
847
848 private void registerService() {
849 if (m_serviceName != null) {
850 ServiceRegistrationImpl wrapper = new ServiceRegistrationImpl();
851 m_registration = wrapper;
852 if (((Boolean) m_autoConfig.get(ServiceRegistration.class)).booleanValue()) {
853 configureImplementation(ServiceRegistration.class, m_registration, (String) m_autoConfigInstance.get(ServiceRegistration.class));
854 }
855
856 // service name can either be a string or an array of strings
857 ServiceRegistration registration;
858
859 // determine service properties
860 Dictionary properties = calculateServiceProperties();
861
862 // register the service
863 try {
864 if (m_serviceName instanceof String) {
865 registration = m_context.registerService((String) m_serviceName, m_serviceInstance, properties);
866 }
867 else {
868 registration = m_context.registerService((String[]) m_serviceName, m_serviceInstance, properties);
869 }
870 wrapper.setServiceRegistration(registration);
871 }
872 catch (IllegalArgumentException iae) {
873 m_logger.log(Logger.LOG_ERROR, "Could not register service " + m_serviceInstance, iae);
874 // set the registration to an illegal state object, which will make all invocations on this
875 // wrapper fail with an ISE (which also occurs when the SR becomes invalid)
876 wrapper.setIllegalState();
877 }
878 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000879 m_isBound = true;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000880 }
881
882 private Dictionary calculateServiceProperties() {
883 Dictionary properties = new Properties();
884 addTo(properties, m_serviceProperties);
885 for (int i = 0; i < m_dependencies.size(); i++) {
886 Dependency d = (Dependency) m_dependencies.get(i);
Marcel Offermanse380c0b2011-10-17 09:03:19 +0000887 if (d.isPropagated() && d.isAvailable()) {
Marcel Offermans117aa2f2009-12-10 09:48:17 +0000888 Dictionary dict = d.getProperties();
889 addTo(properties, dict);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000890 }
891 }
892 if (properties.size() == 0) {
893 properties = null;
894 }
895 return properties;
896 }
897
898 private void addTo(Dictionary properties, Dictionary additional) {
899 if (properties == null) {
900 throw new IllegalArgumentException("Dictionary to add to cannot be null.");
901 }
902 if (additional != null) {
903 Enumeration e = additional.keys();
904 while (e.hasMoreElements()) {
905 Object key = e.nextElement();
906 properties.put(key, additional.get(key));
907 }
908 }
909 }
910
911 private void unregisterService() {
Marcel Offermanse14b3422009-11-25 23:04:32 +0000912 m_isBound = false;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000913 if (m_serviceName != null) {
914 m_registration.unregister();
915 configureImplementation(ServiceRegistration.class, NULL_REGISTRATION);
Marcel Offermansa1bc22a2010-12-28 18:52:24 +0000916 m_registration = null;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000917 }
918 }
919
920 private void updateInstance(Dependency dependency) {
Marcel Offermans937ab4f2009-12-10 10:53:01 +0000921 if (dependency.isAutoConfig()) {
922 configureImplementation(dependency.getAutoConfigType(), dependency.getAutoConfigInstance(), dependency.getAutoConfigName());
Marcel Offermansfacde682012-06-04 11:56:07 +0000923 }
924 if (dependency.isPropagated() && m_registration != null) {
925 m_registration.setProperties(calculateServiceProperties());
Marcel Offermansa962bc92009-11-21 17:59:33 +0000926 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000927 }
928
929 /**
930 * Configure a field in the service implementation. The service implementation
931 * is searched for fields that have the same type as the class that was specified
932 * and for each of these fields, the specified instance is filled in.
933 *
934 * @param clazz the class to search for
935 * @param instance the instance to fill in
936 * @param instanceName the name of the instance to fill in, or <code>null</code> if not used
937 */
938 private void configureImplementation(Class clazz, Object instance, String instanceName) {
939 Object[] instances = getCompositionInstances();
940 if (instances != null) {
941 for (int i = 0; i < instances.length; i++) {
942 Object serviceInstance = instances[i];
943 Class serviceClazz = serviceInstance.getClass();
Marcel Offermansad760672010-03-03 15:30:01 +0000944 if (Proxy.isProxyClass(serviceClazz)) {
945 serviceInstance = Proxy.getInvocationHandler(serviceInstance);
946 serviceClazz = serviceInstance.getClass();
947 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000948 while (serviceClazz != null) {
949 Field[] fields = serviceClazz.getDeclaredFields();
950 for (int j = 0; j < fields.length; j++) {
Marcel Offermans9afe2f52010-05-11 11:33:39 +0000951 Field field = fields[j];
952 Class type = field.getType();
953 if ((instanceName == null && type.equals(clazz))
954 || (instanceName != null && field.getName().equals(instanceName) && type.isAssignableFrom(clazz))) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000955 try {
Marcel Offermans9afe2f52010-05-11 11:33:39 +0000956 field.setAccessible(true);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000957 // synchronized makes sure the field is actually written to immediately
Marcel Offermanse14b3422009-11-25 23:04:32 +0000958 synchronized (SYNC) {
Marcel Offermans9afe2f52010-05-11 11:33:39 +0000959 field.set(serviceInstance, instance);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000960 }
961 }
962 catch (Exception e) {
Marcel Offermans9afe2f52010-05-11 11:33:39 +0000963 m_logger.log(Logger.LOG_ERROR, "Could not set field " + field, e);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000964 return;
965 }
966 }
967 }
968 serviceClazz = serviceClazz.getSuperclass();
969 }
970 }
971 }
972 }
973
974 public Object[] getCompositionInstances() {
Marcel Offermanse14b3422009-11-25 23:04:32 +0000975 Object[] instances = null;
976 if (m_compositionManagerGetMethod != null) {
977 if (m_compositionManager != null) {
978 m_compositionManagerInstance = m_compositionManager;
979 }
980 else {
981 m_compositionManagerInstance = m_serviceInstance;
982 }
983 if (m_compositionManagerInstance != null) {
984 try {
Marcel Offermans1391d682010-06-17 10:17:47 +0000985 instances = (Object[]) InvocationUtil.invokeMethod(m_compositionManagerInstance, m_compositionManagerInstance.getClass(), m_compositionManagerGetMethod, new Class[][] {{}}, new Object[][] {{}}, false);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000986 }
987 catch (Exception e) {
988 m_logger.log(Logger.LOG_ERROR, "Could not obtain instances from the composition manager.", e);
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000989 instances = m_serviceInstance == null ? new Object[] {} : new Object[] { m_serviceInstance };
Marcel Offermanse14b3422009-11-25 23:04:32 +0000990 }
991 }
992 }
993 else {
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000994 instances = m_serviceInstance == null ? new Object[] {} : new Object[] { m_serviceInstance };
Marcel Offermanse14b3422009-11-25 23:04:32 +0000995 }
996 return instances;
Marcel Offermansa962bc92009-11-21 17:59:33 +0000997 }
998
999 private void configureImplementation(Class clazz, Object instance) {
1000 configureImplementation(clazz, instance, null);
1001 }
1002
1003 private void configureServices(State state) {
1004 Iterator i = state.getDependencies().iterator();
1005 while (i.hasNext()) {
1006 Dependency dependency = (Dependency) i.next();
Marcel Offermans001db052009-12-08 08:58:40 +00001007 if (dependency.isAutoConfig()) {
1008 configureImplementation(dependency.getAutoConfigType(), dependency.getAutoConfigInstance(), dependency.getAutoConfigName());
Marcel Offermanse14b3422009-11-25 23:04:32 +00001009 }
Marcel Offermans001db052009-12-08 08:58:40 +00001010 if (dependency.isRequired()) {
1011 dependency.invokeAdded(this);
Marcel Offermanse14b3422009-11-25 23:04:32 +00001012 }
Marcel Offermansa962bc92009-11-21 17:59:33 +00001013 }
1014 }
1015
1016 private void unconfigureServices(State state) {
1017 Iterator i = state.getDependencies().iterator();
1018 while (i.hasNext()) {
1019 Dependency dependency = (Dependency) i.next();
Marcel Offermans001db052009-12-08 08:58:40 +00001020 if (dependency.isRequired()) {
1021 dependency.invokeRemoved(this);
Marcel Offermansa962bc92009-11-21 17:59:33 +00001022 }
1023 }
1024 }
1025
Pierre De Rop19476fe2010-05-23 08:13:58 +00001026 protected void ensureNotActive() {
Marcel Offermansa962bc92009-11-21 17:59:33 +00001027 State state;
1028 synchronized (m_dependencies) {
1029 state = m_state;
1030 }
1031 if (!state.isInactive()) {
1032 throw new IllegalStateException("Cannot modify state while active.");
1033 }
1034 }
Marcel Offermanse14b3422009-11-25 23:04:32 +00001035
1036 public boolean isRegistered() {
Marcel Offermansa962bc92009-11-21 17:59:33 +00001037 State state;
1038 synchronized (m_dependencies) {
1039 state = m_state;
1040 }
Marcel Offermans0f6605e2009-12-10 10:31:35 +00001041 return (state.isAllRequiredAvailable());
1042 }
1043
Marcel Offermans0acdb1b2010-10-14 14:43:03 +00001044 public boolean isInstantiated() {
1045 State state;
1046 synchronized (m_dependencies) {
1047 state = m_state;
1048 }
1049 return (state.isTrackingOptional() || state.isBound() || state.isWaitingForRequiredInstantiated());
1050 }
1051
Marcel Offermansa962bc92009-11-21 17:59:33 +00001052 // ServiceComponent interface
1053
Marcel Offermansfaaed472010-09-08 10:07:32 +00001054 static class SCDImpl implements ComponentDependencyDeclaration {
Marcel Offermansa962bc92009-11-21 17:59:33 +00001055 private final String m_name;
1056 private final int m_state;
1057 private final String m_type;
1058
1059 public SCDImpl(String name, int state, String type) {
1060 m_name = name;
1061 m_state = state;
1062 m_type = type;
1063 }
1064
1065 public String getName() {
1066 return m_name;
1067 }
1068
1069 public int getState() {
1070 return m_state;
1071 }
1072
1073 public String getType() {
1074 return m_type;
1075 }
1076 }
1077
Marcel Offermansfaaed472010-09-08 10:07:32 +00001078 public ComponentDependencyDeclaration[] getComponentDependencies() {
Marcel Offermansa962bc92009-11-21 17:59:33 +00001079 List deps = getDependencies();
1080 if (deps != null) {
Marcel Offermansfaaed472010-09-08 10:07:32 +00001081 ComponentDependencyDeclaration[] result = new ComponentDependencyDeclaration[deps.size()];
Marcel Offermansa962bc92009-11-21 17:59:33 +00001082 for (int i = 0; i < result.length; i++) {
1083 Dependency dep = (Dependency) deps.get(i);
Marcel Offermansfaaed472010-09-08 10:07:32 +00001084 if (dep instanceof ComponentDependencyDeclaration) {
1085 result[i] = (ComponentDependencyDeclaration) dep;
Marcel Offermansa962bc92009-11-21 17:59:33 +00001086 }
1087 else {
1088 result[i] = new SCDImpl(dep.toString(), (dep.isAvailable() ? 1 : 0) + (dep.isRequired() ? 2 : 0), dep.getClass().getName());
1089 }
1090 }
1091 return result;
1092 }
1093 return null;
1094 }
1095
1096 public String getName() {
Marcel Offermansbd15a442010-09-07 07:50:09 +00001097 Object serviceName = m_serviceName;
1098 if (serviceName instanceof String[]) {
Marcel Offermansa962bc92009-11-21 17:59:33 +00001099 StringBuffer sb = new StringBuffer();
Marcel Offermansbd15a442010-09-07 07:50:09 +00001100 String[] names = (String[]) serviceName;
Marcel Offermansa962bc92009-11-21 17:59:33 +00001101 for (int i = 0; i < names.length; i++) {
1102 if (i > 0) {
1103 sb.append(", ");
1104 }
1105 sb.append(names[i]);
1106 }
Marcel Offermans5be5f142011-04-26 10:47:12 +00001107 sb.append('(');
1108 sb.append(propertiesToString());
1109 sb.append(')');
Marcel Offermansa962bc92009-11-21 17:59:33 +00001110 return sb.toString();
1111 }
Marcel Offermansbd15a442010-09-07 07:50:09 +00001112 else if (serviceName instanceof String) {
Marcel Offermans5be5f142011-04-26 10:47:12 +00001113 return serviceName.toString() + "(" + propertiesToString() + ")";
Marcel Offermansa962bc92009-11-21 17:59:33 +00001114 }
1115 else {
Marcel Offermansbd15a442010-09-07 07:50:09 +00001116 Object implementation = m_implementation;
1117 if (implementation != null) {
1118 return implementation.toString();
1119 }
1120 else {
1121 return super.toString();
1122 }
Marcel Offermansa962bc92009-11-21 17:59:33 +00001123 }
1124 }
Marcel Offermans5be5f142011-04-26 10:47:12 +00001125
1126 private String propertiesToString() {
1127 StringBuffer result = new StringBuffer();
1128 Dictionary properties = calculateServiceProperties();
1129 if (properties != null) {
1130 Enumeration enumeration = properties.keys();
1131 while (enumeration.hasMoreElements()) {
Marcel Offermans66df0b82011-04-27 21:48:41 +00001132 Object key = enumeration.nextElement();
Marcel Offermans5be5f142011-04-26 10:47:12 +00001133 if (result.length() > 0) {
1134 result.append(',');
1135 }
Marcel Offermans66df0b82011-04-27 21:48:41 +00001136 result.append(key.toString());
Marcel Offermans5be5f142011-04-26 10:47:12 +00001137 result.append('=');
1138 Object value = properties.get(key);
1139 if (value instanceof String[]) {
1140 String[] values = (String[]) value;
1141 result.append('{');
1142 for (int i = 0; i < values.length; i++) {
1143 if (i > 0) {
1144 result.append(',');
1145 }
1146 result.append(values[i].toString());
1147 }
1148 result.append('}');
1149 }
1150 else {
1151 result.append(value.toString());
1152 }
1153 }
1154 }
1155 return result.toString();
1156 }
Marcel Offermansa962bc92009-11-21 17:59:33 +00001157
1158 public int getState() {
1159 return (isRegistered() ? 1 : 0);
1160 }
1161
Marcel Offermansea89b862010-06-24 13:14:43 +00001162 public DependencyManager getDependencyManager() {
1163 return m_manager;
1164 }
1165
Marcel Offermansa962bc92009-11-21 17:59:33 +00001166 static {
Marcel Offermansfaaed472010-09-08 10:07:32 +00001167 NULL_REGISTRATION = (ServiceRegistration) Proxy.newProxyInstance(ComponentImpl.class.getClassLoader(), new Class[] {ServiceRegistration.class}, new DefaultNullObject());
Marcel Offermansa962bc92009-11-21 17:59:33 +00001168 }
Marcel Offermans5be5f142011-04-26 10:47:12 +00001169
1170 public BundleContext getBundleContext() {
1171 return m_context;
1172 }
1173
1174 public int compareTo(Object object) {
1175 if (object instanceof ComponentImpl) {
1176 ComponentImpl other = (ComponentImpl) object;
1177 long id1 = this.getBundleContext().getBundle().getBundleId();
1178 long id2 = ((ComponentImpl) other).getBundleContext().getBundle().getBundleId();
1179 if (id1 == id2) {
1180 return (int)(this.m_id - other.m_id);
1181 }
1182 return (int)(id1 - id2);
1183 }
1184 return -1;
1185 }
Marcel Offermansa962bc92009-11-21 17:59:33 +00001186}