blob: 9b0a541e25083596c49086de280e93e0b40d77a7 [file] [log] [blame]
Pierre De Rop3a00a212015-03-01 09:27:46 +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 */
19package org.apache.felix.dm;
20
21import java.lang.ref.WeakReference;
22import java.util.ArrayList;
23import java.util.Collections;
24import java.util.HashSet;
25import java.util.Iterator;
26import java.util.List;
27import java.util.Set;
28import java.util.concurrent.ConcurrentHashMap;
29
30import org.apache.felix.dm.impl.AdapterServiceImpl;
31import org.apache.felix.dm.impl.AspectServiceImpl;
32import org.apache.felix.dm.impl.BundleAdapterImpl;
33import org.apache.felix.dm.impl.BundleDependencyImpl;
34import org.apache.felix.dm.impl.ComponentImpl;
35import org.apache.felix.dm.impl.ComponentScheduler;
36import org.apache.felix.dm.impl.ConfigurationDependencyImpl;
37import org.apache.felix.dm.impl.FactoryConfigurationAdapterImpl;
38import org.apache.felix.dm.impl.ResourceAdapterImpl;
39import org.apache.felix.dm.impl.ResourceDependencyImpl;
40import org.apache.felix.dm.impl.ServiceDependencyImpl;
41import org.apache.felix.dm.impl.TemporalServiceDependencyImpl;
42import org.apache.felix.dm.impl.index.AdapterFilterIndex;
43import org.apache.felix.dm.impl.index.AspectFilterIndex;
44import org.apache.felix.dm.impl.index.ServiceRegistryCache;
45import org.apache.felix.dm.impl.index.multiproperty.MultiPropertyFilterIndex;
46import org.apache.felix.dm.impl.metatype.PropertyMetaDataImpl;
47import org.osgi.framework.Bundle;
48import org.osgi.framework.BundleContext;
49import org.osgi.framework.BundleException;
50import org.osgi.framework.FrameworkUtil;
51
52/**
53 * The dependency manager manages all components and their dependencies. Using
54 * this API you can declare all components and their dependencies. Under normal
55 * circumstances, you get passed an instance of this class through the
56 * <code>DependencyActivatorBase</code> subclass you use as your
57 * <code>BundleActivator</code>, but it is also possible to create your
58 * own instance.
59 *
60 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
61 */
62public class DependencyManager {
63 /**
64 * The DependencyManager Activator will wait for a threadpool before creating any DM components if the following
65 * OSGi system property is set to true.
66 */
67 public final static String PARALLEL = "org.apache.felix.dependencymanager.parallel";
68
69 public static final String ASPECT = "org.apache.felix.dependencymanager.aspect";
70 public static final String SERVICEREGISTRY_CACHE_INDICES = "org.apache.felix.dependencymanager.filterindex";
71 public static final String METHOD_CACHE_SIZE = "org.apache.felix.dependencymanager.methodcache";
72
73 private final BundleContext m_context;
74 private final Logger m_logger;
75 private final ConcurrentHashMap<Component, Component> m_components = new ConcurrentHashMap<>();
76
77 // service registry cache
78 private static ServiceRegistryCache m_serviceRegistryCache;
79 private static final Set<WeakReference<DependencyManager>> m_dependencyManagers = new HashSet<>();
80 static {
81 try {
82 Bundle bundle = FrameworkUtil.getBundle(DependencyManager.class);
83 if (bundle != null && bundle.getState() != Bundle.ACTIVE) {
84 bundle.start();
85 BundleContext bundleContext = bundle.getBundleContext();
86 String index = bundleContext.getProperty(SERVICEREGISTRY_CACHE_INDICES);
87 if (index != null) {
88 m_serviceRegistryCache = new ServiceRegistryCache(bundleContext);
89 m_serviceRegistryCache.open(); // TODO close it somewhere
90 String[] props = index.split(";");
91 for (int i = 0; i < props.length; i++) {
92 if (props[i].equals("*aspect*")) {
93 m_serviceRegistryCache.addFilterIndex(new AspectFilterIndex());
94 }
95 else if (props[i].equals("*adapter*")) {
96 m_serviceRegistryCache.addFilterIndex(new AdapterFilterIndex());
97 }
98 else {
99 m_serviceRegistryCache.addFilterIndex(new MultiPropertyFilterIndex(props[i]));
100 }
101 }
102 }
103 }
104 }
105 catch (BundleException e) {
106 // if we cannot start ourselves, we cannot use the indices
107 e.printStackTrace();
108 }
109 }
110
111 /**
112 * Creates a new dependency manager. You need to supply the
113 * <code>BundleContext</code> to be used by the dependency
114 * manager to register services and communicate with the
115 * framework.
116 *
117 * @param context the bundle context
118 */
119 public DependencyManager(BundleContext context) {
120 this(context, new Logger(context));
121 }
122
123 DependencyManager(BundleContext context, Logger logger) {
124 m_context = createContext(context);
125 m_logger = logger;
126 synchronized (m_dependencyManagers) {
127 m_dependencyManagers.add(new WeakReference<DependencyManager>(this));
128 }
129 }
130
131 /**
132 * Returns the list of currently created dependency managers.
133 * @return the list of currently created dependency managers
134 */
135 public static List<DependencyManager> getDependencyManagers() {
136 List<DependencyManager> result = new ArrayList<>();
137 synchronized (m_dependencyManagers) {
138 Iterator<WeakReference<DependencyManager>> iterator = m_dependencyManagers.iterator();
139 while (iterator.hasNext()) {
140 WeakReference<DependencyManager> reference = iterator.next();
141 DependencyManager manager = reference.get();
142 if (manager != null) {
143 try {
144 manager.getBundleContext().getBundle();
145 result.add(manager);
146 continue;
147 }
148 catch (IllegalStateException e) {
149 }
150 }
151 iterator.remove();
152 }
153 }
154 return result;
155 }
156
157 /**
158 * Returns the bundle context associated with this dependency manager.
159 * @return the bundle context associated with this dependency manager.
160 */
161 public BundleContext getBundleContext() {
162 return m_context;
163 }
164
165 /**
166 * Adds a new component to the dependency manager. After the service is added
167 * it will be started immediately.
168 *
169 * @param c the service to add
170 */
171 public void add(Component c) {
172 m_components.put(c, c);
173 ComponentScheduler.instance().add(c);
174 }
175
176 /**
177 * Removes a service from the dependency manager. Before the service is removed
178 * it is stopped first.
179 *
180 * @param c the component to remove
181 */
182 public void remove(Component c) {
183 ComponentScheduler.instance().remove(c);
184 m_components.remove(c);
185 }
186
187 /**
188 * Creates a new component.
189 *
190 * @return the new component
191 */
192 public Component createComponent() {
193 return new ComponentImpl(m_context, this, m_logger);
194 }
195
196 /**
197 * Creates a new service dependency.
198 *
199 * @return the service dependency
200 */
201 public ServiceDependency createServiceDependency() {
202 return new ServiceDependencyImpl();
203 }
204
205 /**
206 * Creates a new configuration dependency.
207 *
208 * @return the configuration dependency
209 */
210 public ConfigurationDependency createConfigurationDependency() {
211 return new ConfigurationDependencyImpl(m_context, m_logger);
212 }
213
214 /**
215 * Creates a new bundle dependency.
216 *
217 * @return a new BundleDependency instance.
218 */
219 public BundleDependency createBundleDependency() {
220 return new BundleDependencyImpl();
221 }
222
223 /**
224 * Creates a new resource dependency.
225 *
226 * @return the resource dependency
227 */
228 public ResourceDependency createResourceDependency() {
229 return new ResourceDependencyImpl();
230 }
231
232 /**
233 * Creates a new timed required service dependency. A timed dependency blocks the invoker thread is the required dependency
234 * is currently unavailable, until it comes up again.
235 *
236 * @return a new timed service dependency
237 */
238 public ServiceDependency createTemporalServiceDependency(long timeout) {
239 return new TemporalServiceDependencyImpl(m_context, timeout);
240 }
241
242 /**
243 * Creates a new adapter. The adapter will be applied to any service that
244 * matches the specified interface and filter. For each matching service
245 * an adapter will be created based on the adapter implementation class.
246 * The adapter will be registered with the specified interface and existing properties
247 * from the original service plus any extra properties you supply here.
248 * It will also inherit all dependencies, and if you declare the original
249 * service as a member it will be injected.
250 *
251 * <h3>Usage Example</h3>
252 *
253 * <blockquote><pre>
254 * manager.createAdapterService(AdapteeService.class, "(foo=bar)")
255 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
256 * .setImplementation(AdapterImpl.class);
257 * </pre></blockquote>
258 *
259 * @param serviceInterface the service interface to apply the adapter to
260 * @param serviceFilter the filter condition to use with the service interface
261 * @return a service that acts as a factory for generating adapters
262 */
263 public Component createAdapterService(Class<?> serviceInterface, String serviceFilter) {
264 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, null, null, null, null, true);
265 }
266
267 /**
268 * Creates a new adapter. The adapter will be applied to any service that
269 * matches the specified interface and filter. For each matching service
270 * an adapter will be created based on the adapter implementation class.
271 * The adapter will be registered with the specified interface and existing properties
272 * from the original service plus any extra properties you supply here.
273 * It will also inherit all dependencies, and if you declare the original
274 * service as a member it will be injected.
275 *
276 * <h3>Usage Example</h3>
277 *
278 * <blockquote><pre>
279 * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "m_service")
280 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
281 * .setImplementation(AdapterImpl.class);
282 * </pre></blockquote>
283 *
284 * @param serviceInterface the service interface to apply the adapter to
285 * @param serviceFilter the filter condition to use with the service interface
286 * @param autoConfig the name of the member to inject the service into
287 * @return a service that acts as a factory for generating adapters
288 */
289 public Component createAdapterService(Class<?> serviceInterface, String serviceFilter, String autoConfig) {
290 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, autoConfig, null, null, null, null, null, true);
291 }
292
293 /**
294 * Creates a new adapter. The adapter will be applied to any service that
295 * matches the specified interface and filter. For each matching service
296 * an adapter will be created based on the adapter implementation class.
297 * The adapter will be registered with the specified interface and existing properties
298 * from the original service plus any extra properties you supply here.
299 * It will also inherit all dependencies, and if you declare the original
300 * service as a member it will be injected.
301 *
302 * <h3>Usage Example</h3>
303 *
304 * <blockquote><pre>
305 * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove")
306 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
307 * .setImplementation(AdapterImpl.class);
308 * </pre></blockquote>
309 *
310 * @param serviceInterface the service interface to apply the adapter to
311 * @param serviceFilter the filter condition to use with the service interface
312 * @param add name of the callback method to invoke on add
313 * @param change name of the callback method to invoke on change
314 * @param remove name of the callback method to invoke on remove
315 * @return a service that acts as a factory for generating adapters
316 */
317 public Component createAdapterService(Class<?> serviceInterface, String serviceFilter, String add, String change,
318 String remove)
319 {
320 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, add, change, remove, null, true);
321 }
322
323 /**
324 * Creates a new adapter. The adapter will be applied to any service that
325 * matches the specified interface and filter. For each matching service
326 * an adapter will be created based on the adapter implementation class.
327 * The adapter will be registered with the specified interface and existing properties
328 * from the original service plus any extra properties you supply here.
329 * It will also inherit all dependencies, and if you declare the original
330 * service as a member it will be injected.
331 *
332 * <h3>Usage Example</h3>
333 *
334 * <blockquote><pre>
335 * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove", "swap")
336 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
337 * .setImplementation(AdapterImpl.class);
338 * </pre></blockquote>
339 *
340 * @param serviceInterface the service interface to apply the adapter to
341 * @param serviceFilter the filter condition to use with the service interface
342 * @param add name of the callback method to invoke on add
343 * @param change name of the callback method to invoke on change
344 * @param remove name of the callback method to invoke on remove
345 * @param swap name of the callback method to invoke on swap
346 * @return a service that acts as a factory for generating adapters
347 */
348 public Component createAdapterService(Class<?> serviceInterface, String serviceFilter, String add, String change,
349 String remove, String swap)
350 {
351 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, add, change, remove, swap, true);
352 }
353
354 /**
355 * Creates a new adapter. The adapter will be applied to any service that
356 * matches the specified interface and filter. For each matching service
357 * an adapter will be created based on the adapter implementation class.
358 * The adapter will be registered with the specified interface (and existing properties
359 * from the original service if you set the propagate flag) plus any extra properties you supply here.
360 * It will also inherit all dependencies, and if you declare the original
361 * service as a member it will be injected.
362 *
363 * <h3>Usage Example</h3>
364 *
365 * <blockquote><pre>
366 * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove", "swap")
367 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
368 * .setImplementation(AdapterImpl.class);
369 * </pre></blockquote>
370 *
371 * @param serviceInterface the service interface to apply the adapter to
372 * @param serviceFilter the filter condition to use with the service interface
373 * @param autoConfig the name of the member to inject the service into, or null.
374 * @param callbackInstance the instance to invoke the callbacks on, or null if the callbacks have to be invoked on the adapter itself
375 * @param add name of the callback method to invoke on add
376 * @param change name of the callback method to invoke on change
377 * @param remove name of the callback method to invoke on remove
378 * @param swap name of the callback method to invoke on swap
379 * @param propagate true if the adaptee service properties should be propagated to the adapter service consumers
380 * @return a service that acts as a factory for generating adapters
381 */
382 public Component createAdapterService(Class<?> serviceInterface, String serviceFilter,
383 String autoConfig, Object callbackInstance, String add, String change, String remove,
384 String swap, boolean propagate)
385 {
386 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, autoConfig, callbackInstance, add, change, remove, swap, propagate);
387 }
388
389 /**
390 * Creates a new Managed Service Factory Configuration Adapter. For each new Config Admin factory configuration matching
391 * the factoryPid, an adapter will be created based on the adapter implementation class.
392 * The adapter will be registered with the specified interface, and with the specified adapter service properties.
393 * Depending on the <code>propagate</code> parameter, every public factory configuration properties
394 * (which don't start with ".") will be propagated along with the adapter service properties.
395 * It will also inherit all dependencies.
396 *
397 * <h3>Usage Example</h3>
398 *
399 * <blockquote><pre>
400 * manager.createFactoryConfigurationAdapterService("MyFactoryPid", "update", true)
401 * // The interface to use when registering adapter
402 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
403 * // the implementation of the adapter
404 * .setImplementation(AdapterServiceImpl.class);
405 * </pre></blockquote>
406 *
407 * @param factoryPid the pid matching the factory configuration
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000408 * @param update the adapter method name that will be notified when the factory configuration is created/updated.<p>
409 * The following signatures are supported:<p>
410 * <ul><li> updated(Dictionary)
411 * <li> updated(Component, Dictionary)
412 * </ul>
Pierre De Rop3a00a212015-03-01 09:27:46 +0000413 * @param propagate true if public factory configuration should be propagated to the adapter service properties
414 * @return a service that acts as a factory for generating the managed service factory configuration adapter
415 */
416 public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate) {
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000417 return new FactoryConfigurationAdapterImpl(this, factoryPid, update, propagate, null);
Pierre De Rop3a00a212015-03-01 09:27:46 +0000418 }
419
420 /**
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000421 * Creates a new Managed Service Factory Configuration Adapter using a specific update callback instance.
422 * For each new Config Admin factory configuration matching the factoryPid, an adapter will be created
423 * based on the adapter implementation class.
424 * The adapter will be registered with the specified interface, and with the specified adapter service properties.
425 * Depending on the <code>propagate</code> parameter, every public factory configuration properties
426 * (which don't start with ".") will be propagated along with the adapter service properties.
427 * It will also inherit all dependencies.
428 *
429 * @param factoryPid the pid matching the factory configuration
430 * @param update the adapter method name that will be notified when the factory configuration is created/updated.<p>
431 * The following signatures are supported:<p>
432 * <ul><li> updated(Dictionary)
433 * <li> updated(Component, Dictionary)
434 * </ul>
435 * @param propagate true if public factory configuration should be propagated to the adapter service properties
436 * @param callbackInstance the object on which the updated callback will be invoked.
437 * @return a service that acts as a factory for generating the managed service factory configuration adapter
438 */
439 public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate, Object callbackInstance) {
440 return new FactoryConfigurationAdapterImpl(this, factoryPid, update, propagate, callbackInstance);
441 }
442
443 /**
Pierre De Rop3a00a212015-03-01 09:27:46 +0000444 * Creates a new Managed Service Factory Configuration Adapter with meta type support. For each new Config Admin
445 * factory configuration matching the factoryPid, an adapter will be created based on the adapter implementation
446 * class. The adapter will be registered with the specified interface, and with the specified adapter service
447 * properties. Depending on the <code>propagate</code> parameter, every public factory configuration properties
448 * (which don't start with ".") will be propagated along with the adapter service properties.
449 * It will also inherit all dependencies.
450 *
451 * <h3>Usage Example</h3>
452 *
453 * <blockquote><pre>
454 * PropertyMetaData[] propertiesMetaData = new PropertyMetaData[] {
455 * manager.createPropertyMetaData()
456 * .setCardinality(Integer.MAX_VALUE)
457 * .setType(String.class)
458 * .setHeading("English words")
459 * .setDescription("Declare here some valid english words")
460 * .setDefaults(new String[] {"hello", "world"})
461 * .setId("words")
462 * };
463 *
464 * manager.add(createFactoryConfigurationAdapterService("FactoryPid",
465 * "updated",
466 * true, // propagate CM settings
467 * "EnglishDictionary",
468 * "English dictionary configuration properties",
469 * null,
470 * propertiesMetaData)
471 * .setImplementation(Adapter.class));
472 * </pre></blockquote>
473 *
474 * @param factoryPid the pid matching the factory configuration
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000475 * @param update the adapter method name that will be notified when the factory configuration is created/updated.<p>
476 * The following signatures are supported:<p>
477 * <ul><li> updated(Dictionary)
478 * <li> updated(Component, Dictionary)
479 * </ul>
Pierre De Rop3a00a212015-03-01 09:27:46 +0000480 * @param propagate true if public factory configuration should be propagated to the adapter service properties
481 * @param heading The label used to display the tab name (or section) where the properties are displayed.
482 * Example: "Printer Service"
483 * @param desc A human readable description of the factory PID this configuration is associated with.
484 * Example: "Configuration for the PrinterService bundle"
485 * @param localization Points to the basename of the Properties file that can localize the Meta Type informations.
486 * The default localization base name for the properties is OSGI-INF/l10n/bundle, but can
487 * be overridden by the manifest Bundle-Localization header (see core specification, in section Localization
488 * on page 68). You can specify a specific localization basename file using this parameter
489 * (e.g. <code>"person"</code> will match person_du_NL.properties in the root bundle directory).
490 * @param propertiesMetaData Array of MetaData regarding configuration properties
491 * @return a service that acts as a factory for generating the managed service factory configuration adapter
492 */
493 public Component createAdapterFactoryConfigurationService(String factoryPid, String update, boolean propagate,
494 String heading, String desc, String localization, PropertyMetaData[] propertiesMetaData)
495 {
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000496 return new FactoryConfigurationAdapterImpl(this, factoryPid, update, propagate, null, m_context, m_logger, heading,
Pierre De Rop3a00a212015-03-01 09:27:46 +0000497 desc, localization, propertiesMetaData);
498 }
499
500 /**
501 * Creates a new bundle adapter. The adapter will be applied to any bundle that
502 * matches the specified bundle state mask and filter condition. For each matching
503 * bundle an adapter will be created based on the adapter implementation class.
504 * The adapter will be registered with the specified interface
505 *
506 * TODO and existing properties from the original resource plus any extra properties you supply here.
507 * It will also inherit all dependencies, and if you declare the original
508 * service as a member it will be injected.
509 *
510 * <h3>Usage Example</h3>
511 *
512 * <blockquote><pre>
513 * manager.createBundleAdapterService(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE,
514 * "(Bundle-SymbolicName=org.apache.felix.dependencymanager)",
515 * true)
516 * // The interface to use when registering adapter
517 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
518 * // the implementation of the adapter
519 * .setImplementation(AdapterServiceImpl.class);
520 * </pre></blockquote>
521 *
522 * @param bundleStateMask the bundle state mask to apply
523 * @param bundleFilter the filter to apply to the bundle manifest
524 * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
525 * @return a service that acts as a factory for generating bundle adapters
526 */
527 public Component createBundleAdapterService(int bundleStateMask, String bundleFilter, boolean propagate) {
528 return new BundleAdapterImpl(this, bundleStateMask, bundleFilter, propagate);
529 }
530
531 /**
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000532 * Creates a new bundle adapter using specific callback instance.
533 * The adapter will be applied to any bundle that matches the specified bundle state mask and filter condition.
534 * For each matching bundle an adapter will be created based on the adapter implementation class, and
535 * The adapter will be registered with the specified interface.
536 *
537 * @param bundleStateMask the bundle state mask to apply
538 * @param bundleFilter the filter to apply to the bundle manifest
539 * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
540 * @param callbackInstance the instance to invoke the callbacks on, or null if the callbacks have to be invoked on the adapter itself
541 * @param add name of the callback method to invoke on add
542 * @param change name of the callback method to invoke on change
543 * @param remove name of the callback method to invoke on remove
544 * @return a service that acts as a factory for generating bundle adapters
545 */
546 public Component createBundleAdapterService(int bundleStateMask, String bundleFilter, boolean propagate,
547 Object callbackInstance, String add, String change, String remove) {
548 return new BundleAdapterImpl(this, bundleStateMask, bundleFilter, propagate, callbackInstance, add, change, remove);
549 }
550
551 /**
Pierre De Rop3a00a212015-03-01 09:27:46 +0000552 * Creates a new resource adapter. The adapter will be applied to any resource that
553 * matches the specified filter condition. For each matching resource
554 * an adapter will be created based on the adapter implementation class.
555 * The adapter will be registered with the specified interface and existing properties
556 * from the original resource plus any extra properties you supply here.
557 * It will also inherit all dependencies, and if you declare the original
558 * service as a member it will be injected.
559 *
560 * <h3>Usage Example</h3>
561 *
562 * <blockquote><pre>
563 * manager.createResourceAdapterService("(&(path=/test)(repository=TestRepository))", true)
564 * // The interface to use when registering adapter
565 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
566 * // the implementation of the adapter
567 * .setImplementation(AdapterServiceImpl.class);
568 * </pre></blockquote>
569 *
570 * @param resourceFilter the filter condition to use with the resource
571 * @param propagate <code>true</code> if properties from the resource should be propagated to the service
572 * @param callbackInstance instance to invoke the callback on
573 * @param callbackChanged the name of the callback method
574 * @return a service that acts as a factory for generating resource adapters
575 */
576 public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance,
577 String callbackChanged)
578 {
579 return new ResourceAdapterImpl(this, resourceFilter, propagate, callbackInstance, null, callbackChanged);
580 }
581
582 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
583 public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance,
584 String callbackSet, String callbackChanged)
585 {
586 return new ResourceAdapterImpl(this, resourceFilter, propagate, callbackInstance, callbackSet, callbackChanged);
587 }
588
589 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
590 public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance,
591 String propagateCallbackMethod, Object callbackInstance, String callbackChanged)
592 {
593 return new ResourceAdapterImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod,
594 callbackInstance, null, callbackChanged);
595 }
596
597 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
598 public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance,
599 String propagateCallbackMethod, Object callbackInstance, String callbackSet, String callbackChanged)
600 {
601 return new ResourceAdapterImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod,
602 callbackInstance, callbackSet, callbackChanged);
603 }
604
605 /**
606 * Returns a list of components.
607 *
608 * @return a list of components
609 */
610 public List<Component> getComponents() {
611 return Collections.list(m_components.elements());
612 }
613
614 /**
615 * Creates a new aspect. The aspect will be applied to any service that
616 * matches the specified interface and filter. For each matching service
617 * an aspect will be created based on the aspect implementation class.
618 * The aspect will be registered with the same interface and properties
619 * as the original service, plus any extra properties you supply here.
620 * It will also inherit all dependencies, and if you declare the original
621 * service as a member it will be injected.
622 *
623 * <h3>Usage Example</h3>
624 *
625 * <blockquote><pre>
626 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "m_service")
627 * .setImplementation(ExistingServiceAspect.class)
628 * );
629 * </pre></blockquote>
630 *
631 * @param serviceInterface the service interface to apply the aspect to
632 * @param serviceFilter the filter condition to use with the service interface
633 * @param ranking the level used to organize the aspect chain ordering
634 * @param autoConfig the aspect implementation field name where to inject original service.
635 * If null, any field matching the original service will be injected.
636 * @return a service that acts as a factory for generating aspects
637 */
638 public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, String autoConfig) {
639 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, autoConfig, null, null, null, null);
640 }
641
642 /**
643 * Creates a new aspect. The aspect will be applied to any service that
644 * matches the specified interface and filter. For each matching service
645 * an aspect will be created based on the aspect implementation class.
646 * The aspect will be registered with the same interface and properties
647 * as the original service, plus any extra properties you supply here.
648 * It will also inherit all dependencies, and if you declare the original
649 * service as a member it will be injected.
650 *
651 * <h3>Usage Example</h3>
652 *
653 * <blockquote><pre>
654 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10)
655 * .setImplementation(ExistingServiceAspect.class)
656 * );
657 * </pre></blockquote>
658 *
659 * @param serviceInterface the service interface to apply the aspect to
660 * @param serviceFilter the filter condition to use with the service interface
661 * @param ranking the level used to organize the aspect chain ordering
662 * @return a service that acts as a factory for generating aspects
663 */
664 public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking) {
665 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, null, null, null);
666 }
667
668 /**
669 * Creates a new aspect. The aspect will be applied to any service that
670 * matches the specified interface and filter. For each matching service
671 * an aspect will be created based on the aspect implementation class.
672 * The aspect will be registered with the same interface and properties
673 * as the original service, plus any extra properties you supply here.
674 * It will also inherit all dependencies, and if you declare the original
675 * service as a member it will be injected.
676 *
677 * <h3>Usage Example</h3>
678 *
679 * <blockquote><pre>
680 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
681 * .setImplementation(ExistingServiceAspect.class)
682 * );
683 * </pre></blockquote>
684 *
685 * @param serviceInterface the service interface to apply the aspect to
686 * @param serviceFilter the filter condition to use with the service interface
687 * @param ranking the level used to organize the aspect chain ordering
688 * @param add name of the callback method to invoke on add
689 * @param change name of the callback method to invoke on change
690 * @param remove name of the callback method to invoke on remove
691 * @return a service that acts as a factory for generating aspects
692 */
693 public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, String add,
694 String change, String remove)
695 {
696 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, add, change, remove, null);
697 }
698
699 /**
700 * Creates a new aspect. The aspect will be applied to any service that
701 * matches the specified interface and filter. For each matching service
702 * an aspect will be created based on the aspect implementation class.
703 * The aspect will be registered with the same interface and properties
704 * as the original service, plus any extra properties you supply here.
705 * It will also inherit all dependencies, and if you declare the original
706 * service as a member it will be injected.
707 *
708 * <h3>Usage Example</h3>
709 *
710 * <blockquote><pre>
711 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
712 * .setImplementation(ExistingServiceAspect.class)
713 * );
714 * </pre></blockquote>
715 *
716 * @param serviceInterface the service interface to apply the aspect to
717 * @param serviceFilter the filter condition to use with the service interface
718 * @param ranking the level used to organize the aspect chain ordering
719 * @param add name of the callback method to invoke on add
720 * @param change name of the callback method to invoke on change
721 * @param remove name of the callback method to invoke on remove
722 * @param swap name of the callback method to invoke on swap
723 * @return a service that acts as a factory for generating aspects
724 */
725 public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, String add,
726 String change, String remove, String swap)
727 {
728 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, add, change, remove, swap);
729 }
730
731 /**
732 * Removes all components and their dependencies.
733 */
734 public void clear() {
735 for (Component component : m_components.keySet()) {
736 remove(component);
737 }
738 m_components.clear();
739 }
740
741 /**
742 * Creates a new configuration property metadata.
743 *
744 * @return the configuration property metadata.
745 */
746 public PropertyMetaData createPropertyMetaData() {
747 return new PropertyMetaDataImpl();
748 }
749
750 private BundleContext createContext(BundleContext context) {
751 if (m_serviceRegistryCache != null) {
752 return m_serviceRegistryCache.createBundleContextInterceptor(context);
753 }
754 else {
755 return context;
756 }
757 }
758}