blob: 87ea8dfa6689a55dd79f19281b3c044d2b87edd1 [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);
Pierre De Rop85fc8f02015-07-27 21:50:09 +000083 if (bundle != null) {
84 if (bundle.getState() != Bundle.ACTIVE) {
85 bundle.start();
86 }
Pierre De Rop3a00a212015-03-01 09:27:46 +000087 BundleContext bundleContext = bundle.getBundleContext();
88 String index = bundleContext.getProperty(SERVICEREGISTRY_CACHE_INDICES);
89 if (index != null) {
90 m_serviceRegistryCache = new ServiceRegistryCache(bundleContext);
91 m_serviceRegistryCache.open(); // TODO close it somewhere
92 String[] props = index.split(";");
93 for (int i = 0; i < props.length; i++) {
94 if (props[i].equals("*aspect*")) {
95 m_serviceRegistryCache.addFilterIndex(new AspectFilterIndex());
96 }
97 else if (props[i].equals("*adapter*")) {
98 m_serviceRegistryCache.addFilterIndex(new AdapterFilterIndex());
99 }
100 else {
101 m_serviceRegistryCache.addFilterIndex(new MultiPropertyFilterIndex(props[i]));
102 }
103 }
104 }
105 }
106 }
107 catch (BundleException e) {
108 // if we cannot start ourselves, we cannot use the indices
109 e.printStackTrace();
110 }
111 }
112
113 /**
114 * Creates a new dependency manager. You need to supply the
115 * <code>BundleContext</code> to be used by the dependency
116 * manager to register services and communicate with the
117 * framework.
118 *
119 * @param context the bundle context
120 */
121 public DependencyManager(BundleContext context) {
122 this(context, new Logger(context));
123 }
124
125 DependencyManager(BundleContext context, Logger logger) {
126 m_context = createContext(context);
127 m_logger = logger;
128 synchronized (m_dependencyManagers) {
129 m_dependencyManagers.add(new WeakReference<DependencyManager>(this));
130 }
131 }
132
133 /**
134 * Returns the list of currently created dependency managers.
135 * @return the list of currently created dependency managers
136 */
137 public static List<DependencyManager> getDependencyManagers() {
138 List<DependencyManager> result = new ArrayList<>();
139 synchronized (m_dependencyManagers) {
140 Iterator<WeakReference<DependencyManager>> iterator = m_dependencyManagers.iterator();
141 while (iterator.hasNext()) {
142 WeakReference<DependencyManager> reference = iterator.next();
143 DependencyManager manager = reference.get();
144 if (manager != null) {
145 try {
146 manager.getBundleContext().getBundle();
147 result.add(manager);
148 continue;
149 }
150 catch (IllegalStateException e) {
151 }
152 }
153 iterator.remove();
154 }
155 }
156 return result;
157 }
158
159 /**
160 * Returns the bundle context associated with this dependency manager.
161 * @return the bundle context associated with this dependency manager.
162 */
163 public BundleContext getBundleContext() {
164 return m_context;
165 }
166
167 /**
168 * Adds a new component to the dependency manager. After the service is added
169 * it will be started immediately.
170 *
171 * @param c the service to add
172 */
173 public void add(Component c) {
174 m_components.put(c, c);
175 ComponentScheduler.instance().add(c);
176 }
177
178 /**
179 * Removes a service from the dependency manager. Before the service is removed
180 * it is stopped first.
181 *
182 * @param c the component to remove
183 */
184 public void remove(Component c) {
185 ComponentScheduler.instance().remove(c);
186 m_components.remove(c);
187 }
188
189 /**
190 * Creates a new component.
191 *
192 * @return the new component
193 */
194 public Component createComponent() {
195 return new ComponentImpl(m_context, this, m_logger);
196 }
197
198 /**
199 * Creates a new service dependency.
200 *
201 * @return the service dependency
202 */
203 public ServiceDependency createServiceDependency() {
204 return new ServiceDependencyImpl();
205 }
206
207 /**
208 * Creates a new configuration dependency.
209 *
210 * @return the configuration dependency
211 */
212 public ConfigurationDependency createConfigurationDependency() {
213 return new ConfigurationDependencyImpl(m_context, m_logger);
214 }
215
216 /**
217 * Creates a new bundle dependency.
218 *
219 * @return a new BundleDependency instance.
220 */
221 public BundleDependency createBundleDependency() {
222 return new BundleDependencyImpl();
223 }
224
225 /**
226 * Creates a new resource dependency.
227 *
228 * @return the resource dependency
229 */
230 public ResourceDependency createResourceDependency() {
231 return new ResourceDependencyImpl();
232 }
233
234 /**
235 * Creates a new timed required service dependency. A timed dependency blocks the invoker thread is the required dependency
236 * is currently unavailable, until it comes up again.
237 *
238 * @return a new timed service dependency
239 */
240 public ServiceDependency createTemporalServiceDependency(long timeout) {
241 return new TemporalServiceDependencyImpl(m_context, timeout);
242 }
243
244 /**
245 * Creates a new adapter. The adapter will be applied to any service that
246 * matches the specified interface and filter. For each matching service
247 * an adapter will be created based on the adapter implementation class.
248 * The adapter will be registered with the specified interface and existing properties
249 * from the original service plus any extra properties you supply here.
250 * It will also inherit all dependencies, and if you declare the original
251 * service as a member it will be injected.
252 *
253 * <h3>Usage Example</h3>
254 *
255 * <blockquote><pre>
256 * manager.createAdapterService(AdapteeService.class, "(foo=bar)")
257 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
258 * .setImplementation(AdapterImpl.class);
259 * </pre></blockquote>
260 *
261 * @param serviceInterface the service interface to apply the adapter to
262 * @param serviceFilter the filter condition to use with the service interface
263 * @return a service that acts as a factory for generating adapters
264 */
265 public Component createAdapterService(Class<?> serviceInterface, String serviceFilter) {
266 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, null, null, null, null, true);
267 }
268
269 /**
270 * Creates a new adapter. The adapter will be applied to any service that
271 * matches the specified interface and filter. For each matching service
272 * an adapter will be created based on the adapter implementation class.
273 * The adapter will be registered with the specified interface and existing properties
274 * from the original service plus any extra properties you supply here.
275 * It will also inherit all dependencies, and if you declare the original
276 * service as a member it will be injected.
277 *
278 * <h3>Usage Example</h3>
279 *
280 * <blockquote><pre>
281 * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "m_service")
282 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
283 * .setImplementation(AdapterImpl.class);
284 * </pre></blockquote>
285 *
286 * @param serviceInterface the service interface to apply the adapter to
287 * @param serviceFilter the filter condition to use with the service interface
288 * @param autoConfig the name of the member to inject the service into
289 * @return a service that acts as a factory for generating adapters
290 */
291 public Component createAdapterService(Class<?> serviceInterface, String serviceFilter, String autoConfig) {
292 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, autoConfig, null, null, null, null, null, true);
293 }
294
295 /**
296 * Creates a new adapter. The adapter will be applied to any service that
297 * matches the specified interface and filter. For each matching service
298 * an adapter will be created based on the adapter implementation class.
299 * The adapter will be registered with the specified interface and existing properties
300 * from the original service plus any extra properties you supply here.
301 * It will also inherit all dependencies, and if you declare the original
302 * service as a member it will be injected.
303 *
304 * <h3>Usage Example</h3>
305 *
306 * <blockquote><pre>
307 * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove")
308 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
309 * .setImplementation(AdapterImpl.class);
310 * </pre></blockquote>
311 *
312 * @param serviceInterface the service interface to apply the adapter to
313 * @param serviceFilter the filter condition to use with the service interface
314 * @param add name of the callback method to invoke on add
315 * @param change name of the callback method to invoke on change
316 * @param remove name of the callback method to invoke on remove
317 * @return a service that acts as a factory for generating adapters
318 */
319 public Component createAdapterService(Class<?> serviceInterface, String serviceFilter, String add, String change,
320 String remove)
321 {
322 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, add, change, remove, null, true);
323 }
324
325 /**
326 * Creates a new adapter. The adapter will be applied to any service that
327 * matches the specified interface and filter. For each matching service
328 * an adapter will be created based on the adapter implementation class.
329 * The adapter will be registered with the specified interface and existing properties
330 * from the original service plus any extra properties you supply here.
331 * It will also inherit all dependencies, and if you declare the original
332 * service as a member it will be injected.
333 *
334 * <h3>Usage Example</h3>
335 *
336 * <blockquote><pre>
337 * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove", "swap")
338 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
339 * .setImplementation(AdapterImpl.class);
340 * </pre></blockquote>
341 *
342 * @param serviceInterface the service interface to apply the adapter to
343 * @param serviceFilter the filter condition to use with the service interface
344 * @param add name of the callback method to invoke on add
345 * @param change name of the callback method to invoke on change
346 * @param remove name of the callback method to invoke on remove
347 * @param swap name of the callback method to invoke on swap
348 * @return a service that acts as a factory for generating adapters
349 */
350 public Component createAdapterService(Class<?> serviceInterface, String serviceFilter, String add, String change,
351 String remove, String swap)
352 {
353 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, add, change, remove, swap, true);
354 }
355
356 /**
357 * Creates a new adapter. The adapter will be applied to any service that
358 * matches the specified interface and filter. For each matching service
359 * an adapter will be created based on the adapter implementation class.
360 * The adapter will be registered with the specified interface (and existing properties
361 * from the original service if you set the propagate flag) plus any extra properties you supply here.
362 * It will also inherit all dependencies, and if you declare the original
363 * service as a member it will be injected.
364 *
365 * <h3>Usage Example</h3>
366 *
367 * <blockquote><pre>
368 * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove", "swap")
369 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
370 * .setImplementation(AdapterImpl.class);
371 * </pre></blockquote>
372 *
373 * @param serviceInterface the service interface to apply the adapter to
374 * @param serviceFilter the filter condition to use with the service interface
375 * @param autoConfig the name of the member to inject the service into, or null.
376 * @param callbackInstance the instance to invoke the callbacks on, or null if the callbacks have to be invoked on the adapter itself
377 * @param add name of the callback method to invoke on add
378 * @param change name of the callback method to invoke on change
379 * @param remove name of the callback method to invoke on remove
380 * @param swap name of the callback method to invoke on swap
381 * @param propagate true if the adaptee service properties should be propagated to the adapter service consumers
382 * @return a service that acts as a factory for generating adapters
383 */
384 public Component createAdapterService(Class<?> serviceInterface, String serviceFilter,
385 String autoConfig, Object callbackInstance, String add, String change, String remove,
386 String swap, boolean propagate)
387 {
388 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, autoConfig, callbackInstance, add, change, remove, swap, propagate);
389 }
390
391 /**
392 * Creates a new Managed Service Factory Configuration Adapter. For each new Config Admin factory configuration matching
393 * the factoryPid, an adapter will be created based on the adapter implementation class.
394 * The adapter will be registered with the specified interface, and with the specified adapter service properties.
395 * Depending on the <code>propagate</code> parameter, every public factory configuration properties
396 * (which don't start with ".") will be propagated along with the adapter service properties.
397 * It will also inherit all dependencies.
398 *
399 * <h3>Usage Example</h3>
400 *
401 * <blockquote><pre>
402 * manager.createFactoryConfigurationAdapterService("MyFactoryPid", "update", true)
403 * // The interface to use when registering adapter
404 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
405 * // the implementation of the adapter
406 * .setImplementation(AdapterServiceImpl.class);
407 * </pre></blockquote>
408 *
409 * @param factoryPid the pid matching the factory configuration
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000410 * @param update the adapter method name that will be notified when the factory configuration is created/updated.<p>
411 * The following signatures are supported:<p>
412 * <ul><li> updated(Dictionary)
413 * <li> updated(Component, Dictionary)
414 * </ul>
Pierre De Rop3a00a212015-03-01 09:27:46 +0000415 * @param propagate true if public factory configuration should be propagated to the adapter service properties
416 * @return a service that acts as a factory for generating the managed service factory configuration adapter
417 */
418 public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate) {
Pierre De Rop17274a72016-02-09 23:43:14 +0000419 return new FactoryConfigurationAdapterImpl(this, factoryPid, update, propagate, null, null);
Pierre De Rop3a00a212015-03-01 09:27:46 +0000420 }
421
422 /**
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000423 * Creates a new Managed Service Factory Configuration Adapter using a specific update callback instance.
424 * For each new Config Admin factory configuration matching the factoryPid, an adapter will be created
425 * based on the adapter implementation class.
426 * The adapter will be registered with the specified interface, and with the specified adapter service properties.
427 * Depending on the <code>propagate</code> parameter, every public factory configuration properties
428 * (which don't start with ".") will be propagated along with the adapter service properties.
429 * It will also inherit all dependencies.
430 *
431 * @param factoryPid the pid matching the factory configuration
432 * @param update the adapter method name that will be notified when the factory configuration is created/updated.<p>
433 * The following signatures are supported:<p>
434 * <ul><li> updated(Dictionary)
435 * <li> updated(Component, Dictionary)
436 * </ul>
437 * @param propagate true if public factory configuration should be propagated to the adapter service properties
438 * @param callbackInstance the object on which the updated callback will be invoked.
439 * @return a service that acts as a factory for generating the managed service factory configuration adapter
440 */
441 public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate, Object callbackInstance) {
Pierre De Rop17274a72016-02-09 23:43:14 +0000442 return new FactoryConfigurationAdapterImpl(this, factoryPid, update, propagate, callbackInstance, null);
443 }
444
445 /**
446 * Creates a new Managed Service Factory Configuration Adapter. For each new Config Admin factory configuration matching
447 * the factoryPid, an adapter will be created based on the adapter implementation class.
448 * The adapter will be registered with the specified interface, and with the specified adapter service properties.
449 * Depending on the <code>propagate</code> parameter, every public factory configuration properties
450 * (which don't start with ".") will be propagated along with the adapter service properties.
451 * It will also inherit all dependencies.
452 *
453 * <h3>Usage Example</h3>
454 *
455 * <blockquote><pre>
456 * manager.createFactoryConfigurationAdapterService("MyFactoryPid", "update", true)
457 * // The interface to use when registering adapter
458 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
459 * // the implementation of the adapter
460 * .setImplementation(AdapterServiceImpl.class);
461 * </pre></blockquote>
462 *
463 * @param factoryPid the pid matching the factory configuration
464 * @param update the adapter method name that will be notified when the factory configuration is created/updated.<p>
465 * The following signatures are supported:<p>
466 * <ul><li> updated(Dictionary)
467 * <li> updated(Component, Dictionary)
468 * </ul>
469 * @param propagate true if public factory configuration should be propagated to the adapter service properties
Pierre De Rop9e5cdba2016-02-17 20:35:16 +0000470 * @param configType the configuration type to use instead of a dictionary. See the javadoc from {@link ConfigurationDependency} for
471 * more informations about type-safe configuration.
Pierre De Rop17274a72016-02-09 23:43:14 +0000472 * @return a service that acts as a factory for generating the managed service factory configuration adapter
Pierre De Rop9e5cdba2016-02-17 20:35:16 +0000473 * @see ConfigurationDependency
Pierre De Rop17274a72016-02-09 23:43:14 +0000474 */
475 public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate, Class<?> configType) {
476 return new FactoryConfigurationAdapterImpl(this, factoryPid, update, propagate, null, configType);
477 }
478
479 /**
480 * Creates a new Managed Service Factory Configuration Adapter using a specific update callback instance.
481 * For each new Config Admin factory configuration matching the factoryPid, an adapter will be created
482 * based on the adapter implementation class.
483 * The adapter will be registered with the specified interface, and with the specified adapter service properties.
484 * Depending on the <code>propagate</code> parameter, every public factory configuration properties
485 * (which don't start with ".") will be propagated along with the adapter service properties.
486 * It will also inherit all dependencies.
487 *
488 * @param factoryPid the pid matching the factory configuration
489 * @param update the adapter method name that will be notified when the factory configuration is created/updated.<p>
490 * The following signatures are supported:<p>
491 * <ul><li> updated(Dictionary)
492 * <li> updated(Component, Dictionary)
493 * </ul>
494 * @param propagate true if public factory configuration should be propagated to the adapter service properties
495 * @param callbackInstance the object on which the updated callback will be invoked.
Pierre De Rop9e5cdba2016-02-17 20:35:16 +0000496 * @param configType the configuration type to use instead of a dictionary. See the javadoc from {@link ConfigurationDependency} for
497 * more informations about type-safe configuration.
Pierre De Rop17274a72016-02-09 23:43:14 +0000498 * @return a service that acts as a factory for generating the managed service factory configuration adapter
499 */
500 public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate, Object callbackInstance, Class<?> configType) {
501 return new FactoryConfigurationAdapterImpl(this, factoryPid, update, propagate, callbackInstance, configType);
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000502 }
503
504 /**
Pierre De Rop3a00a212015-03-01 09:27:46 +0000505 * Creates a new Managed Service Factory Configuration Adapter with meta type support. For each new Config Admin
506 * factory configuration matching the factoryPid, an adapter will be created based on the adapter implementation
507 * class. The adapter will be registered with the specified interface, and with the specified adapter service
508 * properties. Depending on the <code>propagate</code> parameter, every public factory configuration properties
509 * (which don't start with ".") will be propagated along with the adapter service properties.
510 * It will also inherit all dependencies.
511 *
512 * <h3>Usage Example</h3>
513 *
514 * <blockquote><pre>
515 * PropertyMetaData[] propertiesMetaData = new PropertyMetaData[] {
516 * manager.createPropertyMetaData()
517 * .setCardinality(Integer.MAX_VALUE)
518 * .setType(String.class)
519 * .setHeading("English words")
520 * .setDescription("Declare here some valid english words")
521 * .setDefaults(new String[] {"hello", "world"})
522 * .setId("words")
523 * };
524 *
525 * manager.add(createFactoryConfigurationAdapterService("FactoryPid",
526 * "updated",
527 * true, // propagate CM settings
528 * "EnglishDictionary",
529 * "English dictionary configuration properties",
530 * null,
531 * propertiesMetaData)
532 * .setImplementation(Adapter.class));
533 * </pre></blockquote>
534 *
535 * @param factoryPid the pid matching the factory configuration
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000536 * @param update the adapter method name that will be notified when the factory configuration is created/updated.<p>
537 * The following signatures are supported:<p>
538 * <ul><li> updated(Dictionary)
539 * <li> updated(Component, Dictionary)
540 * </ul>
Pierre De Rop3a00a212015-03-01 09:27:46 +0000541 * @param propagate true if public factory configuration should be propagated to the adapter service properties
542 * @param heading The label used to display the tab name (or section) where the properties are displayed.
543 * Example: "Printer Service"
544 * @param desc A human readable description of the factory PID this configuration is associated with.
545 * Example: "Configuration for the PrinterService bundle"
546 * @param localization Points to the basename of the Properties file that can localize the Meta Type informations.
547 * The default localization base name for the properties is OSGI-INF/l10n/bundle, but can
548 * be overridden by the manifest Bundle-Localization header (see core specification, in section Localization
549 * on page 68). You can specify a specific localization basename file using this parameter
550 * (e.g. <code>"person"</code> will match person_du_NL.properties in the root bundle directory).
551 * @param propertiesMetaData Array of MetaData regarding configuration properties
552 * @return a service that acts as a factory for generating the managed service factory configuration adapter
553 */
554 public Component createAdapterFactoryConfigurationService(String factoryPid, String update, boolean propagate,
555 String heading, String desc, String localization, PropertyMetaData[] propertiesMetaData)
556 {
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000557 return new FactoryConfigurationAdapterImpl(this, factoryPid, update, propagate, null, m_context, m_logger, heading,
Pierre De Rop3a00a212015-03-01 09:27:46 +0000558 desc, localization, propertiesMetaData);
559 }
560
561 /**
562 * Creates a new bundle adapter. The adapter will be applied to any bundle that
563 * matches the specified bundle state mask and filter condition. For each matching
564 * bundle an adapter will be created based on the adapter implementation class.
565 * The adapter will be registered with the specified interface
566 *
567 * TODO and existing properties from the original resource plus any extra properties you supply here.
568 * It will also inherit all dependencies, and if you declare the original
569 * service as a member it will be injected.
570 *
571 * <h3>Usage Example</h3>
572 *
573 * <blockquote><pre>
574 * manager.createBundleAdapterService(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE,
575 * "(Bundle-SymbolicName=org.apache.felix.dependencymanager)",
576 * true)
577 * // The interface to use when registering adapter
578 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
579 * // the implementation of the adapter
580 * .setImplementation(AdapterServiceImpl.class);
581 * </pre></blockquote>
582 *
583 * @param bundleStateMask the bundle state mask to apply
584 * @param bundleFilter the filter to apply to the bundle manifest
585 * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
586 * @return a service that acts as a factory for generating bundle adapters
587 */
588 public Component createBundleAdapterService(int bundleStateMask, String bundleFilter, boolean propagate) {
589 return new BundleAdapterImpl(this, bundleStateMask, bundleFilter, propagate);
590 }
591
592 /**
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000593 * Creates a new bundle adapter using specific callback instance.
594 * The adapter will be applied to any bundle that matches the specified bundle state mask and filter condition.
595 * For each matching bundle an adapter will be created based on the adapter implementation class, and
596 * The adapter will be registered with the specified interface.
597 *
598 * @param bundleStateMask the bundle state mask to apply
599 * @param bundleFilter the filter to apply to the bundle manifest
600 * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
601 * @param callbackInstance the instance to invoke the callbacks on, or null if the callbacks have to be invoked on the adapter itself
602 * @param add name of the callback method to invoke on add
603 * @param change name of the callback method to invoke on change
604 * @param remove name of the callback method to invoke on remove
605 * @return a service that acts as a factory for generating bundle adapters
606 */
607 public Component createBundleAdapterService(int bundleStateMask, String bundleFilter, boolean propagate,
608 Object callbackInstance, String add, String change, String remove) {
609 return new BundleAdapterImpl(this, bundleStateMask, bundleFilter, propagate, callbackInstance, add, change, remove);
610 }
611
612 /**
Pierre De Rop3a00a212015-03-01 09:27:46 +0000613 * Creates a new resource adapter. The adapter will be applied to any resource that
614 * matches the specified filter condition. For each matching resource
615 * an adapter will be created based on the adapter implementation class.
616 * The adapter will be registered with the specified interface and existing properties
617 * from the original resource plus any extra properties you supply here.
618 * It will also inherit all dependencies, and if you declare the original
619 * service as a member it will be injected.
620 *
621 * <h3>Usage Example</h3>
622 *
623 * <blockquote><pre>
624 * manager.createResourceAdapterService("(&(path=/test)(repository=TestRepository))", true)
625 * // The interface to use when registering adapter
626 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
627 * // the implementation of the adapter
628 * .setImplementation(AdapterServiceImpl.class);
629 * </pre></blockquote>
630 *
631 * @param resourceFilter the filter condition to use with the resource
632 * @param propagate <code>true</code> if properties from the resource should be propagated to the service
633 * @param callbackInstance instance to invoke the callback on
634 * @param callbackChanged the name of the callback method
635 * @return a service that acts as a factory for generating resource adapters
636 */
637 public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance,
638 String callbackChanged)
639 {
640 return new ResourceAdapterImpl(this, resourceFilter, propagate, callbackInstance, null, callbackChanged);
641 }
642
643 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
644 public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance,
645 String callbackSet, String callbackChanged)
646 {
647 return new ResourceAdapterImpl(this, resourceFilter, propagate, callbackInstance, callbackSet, callbackChanged);
648 }
649
650 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
651 public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance,
652 String propagateCallbackMethod, Object callbackInstance, String callbackChanged)
653 {
654 return new ResourceAdapterImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod,
655 callbackInstance, null, callbackChanged);
656 }
657
658 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
659 public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance,
660 String propagateCallbackMethod, Object callbackInstance, String callbackSet, String callbackChanged)
661 {
662 return new ResourceAdapterImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod,
663 callbackInstance, callbackSet, callbackChanged);
664 }
665
666 /**
667 * Returns a list of components.
668 *
669 * @return a list of components
670 */
671 public List<Component> getComponents() {
672 return Collections.list(m_components.elements());
673 }
674
675 /**
676 * Creates a new aspect. The aspect will be applied to any service that
677 * matches the specified interface and filter. For each matching service
678 * an aspect will be created based on the aspect implementation class.
679 * The aspect will be registered with the same interface and properties
680 * as the original service, plus any extra properties you supply here.
681 * It will also inherit all dependencies, and if you declare the original
682 * service as a member it will be injected.
683 *
684 * <h3>Usage Example</h3>
685 *
686 * <blockquote><pre>
687 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "m_service")
688 * .setImplementation(ExistingServiceAspect.class)
689 * );
690 * </pre></blockquote>
691 *
692 * @param serviceInterface the service interface to apply the aspect to
693 * @param serviceFilter the filter condition to use with the service interface
694 * @param ranking the level used to organize the aspect chain ordering
695 * @param autoConfig the aspect implementation field name where to inject original service.
696 * If null, any field matching the original service will be injected.
697 * @return a service that acts as a factory for generating aspects
698 */
699 public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, String autoConfig) {
Pierre De Rop32b68c82016-01-11 21:52:47 +0000700 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, autoConfig, null, null, null, null, null);
Pierre De Rop3a00a212015-03-01 09:27:46 +0000701 }
702
703 /**
704 * Creates a new aspect. The aspect will be applied to any service that
705 * matches the specified interface and filter. For each matching service
706 * an aspect will be created based on the aspect implementation class.
707 * The aspect will be registered with the same interface and properties
708 * as the original service, plus any extra properties you supply here.
709 * It will also inherit all dependencies, and if you declare the original
710 * service as a member it will be injected.
711 *
712 * <h3>Usage Example</h3>
713 *
714 * <blockquote><pre>
715 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10)
716 * .setImplementation(ExistingServiceAspect.class)
717 * );
718 * </pre></blockquote>
719 *
720 * @param serviceInterface the service interface to apply the aspect to
721 * @param serviceFilter the filter condition to use with the service interface
722 * @param ranking the level used to organize the aspect chain ordering
723 * @return a service that acts as a factory for generating aspects
724 */
725 public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking) {
Pierre De Rop32b68c82016-01-11 21:52:47 +0000726 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, null, null, null, null);
Pierre De Rop3a00a212015-03-01 09:27:46 +0000727 }
728
729 /**
730 * Creates a new aspect. The aspect will be applied to any service that
731 * matches the specified interface and filter. For each matching service
732 * an aspect will be created based on the aspect implementation class.
733 * The aspect will be registered with the same interface and properties
734 * as the original service, plus any extra properties you supply here.
735 * It will also inherit all dependencies, and if you declare the original
736 * service as a member it will be injected.
737 *
738 * <h3>Usage Example</h3>
739 *
740 * <blockquote><pre>
741 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
742 * .setImplementation(ExistingServiceAspect.class)
743 * );
744 * </pre></blockquote>
745 *
746 * @param serviceInterface the service interface to apply the aspect to
747 * @param serviceFilter the filter condition to use with the service interface
748 * @param ranking the level used to organize the aspect chain ordering
749 * @param add name of the callback method to invoke on add
750 * @param change name of the callback method to invoke on change
751 * @param remove name of the callback method to invoke on remove
752 * @return a service that acts as a factory for generating aspects
753 */
754 public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, String add,
755 String change, String remove)
756 {
Pierre De Rop32b68c82016-01-11 21:52:47 +0000757 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, add, change, remove, null);
Pierre De Rop3a00a212015-03-01 09:27:46 +0000758 }
759
760 /**
761 * Creates a new aspect. The aspect will be applied to any service that
762 * matches the specified interface and filter. For each matching service
763 * an aspect will be created based on the aspect implementation class.
764 * The aspect will be registered with the same interface and properties
765 * as the original service, plus any extra properties you supply here.
766 * It will also inherit all dependencies, and if you declare the original
767 * service as a member it will be injected.
768 *
769 * <h3>Usage Example</h3>
770 *
771 * <blockquote><pre>
772 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
773 * .setImplementation(ExistingServiceAspect.class)
774 * );
775 * </pre></blockquote>
776 *
777 * @param serviceInterface the service interface to apply the aspect to
778 * @param serviceFilter the filter condition to use with the service interface
779 * @param ranking the level used to organize the aspect chain ordering
780 * @param add name of the callback method to invoke on add
781 * @param change name of the callback method to invoke on change
782 * @param remove name of the callback method to invoke on remove
783 * @param swap name of the callback method to invoke on swap
784 * @return a service that acts as a factory for generating aspects
785 */
786 public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, String add,
787 String change, String remove, String swap)
788 {
Pierre De Rop32b68c82016-01-11 21:52:47 +0000789 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, add, change, remove, swap);
790 }
791
792 /**
793 * Creates a new aspect. The aspect will be applied to any service that
794 * matches the specified interface and filter. For each matching service
795 * an aspect will be created based on the aspect implementation class.
796 * The aspect will be registered with the same interface and properties
797 * as the original service, plus any extra properties you supply here.
798 * It will also inherit all dependencies, and if you declare the original
799 * service as a member it will be injected.
800 *
801 * <h3>Usage Example</h3>
802 *
803 * <blockquote><pre>
804 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
805 * .setImplementation(ExistingServiceAspect.class)
806 * );
807 * </pre></blockquote>
808 *
809 * @param serviceInterface the service interface to apply the aspect to
810 * @param serviceFilter the filter condition to use with the service interface
811 * @param ranking the level used to organize the aspect chain ordering
812 * @param callbackInstance the instance to invoke the callbacks on, or null if the callbacks have to be invoked on the aspect itself
813 * @param add name of the callback method to invoke on add
814 * @param change name of the callback method to invoke on change
815 * @param remove name of the callback method to invoke on remove
816 * @param swap name of the callback method to invoke on swap
817 * @return a service that acts as a factory for generating aspects
818 */
819 public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, Object callbackInstance,
820 String add, String change, String remove, String swap)
821 {
822 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, callbackInstance, add, change, remove, swap);
Pierre De Rop3a00a212015-03-01 09:27:46 +0000823 }
824
825 /**
826 * Removes all components and their dependencies.
827 */
828 public void clear() {
829 for (Component component : m_components.keySet()) {
830 remove(component);
831 }
832 m_components.clear();
833 }
834
835 /**
836 * Creates a new configuration property metadata.
837 *
838 * @return the configuration property metadata.
839 */
840 public PropertyMetaData createPropertyMetaData() {
841 return new PropertyMetaDataImpl();
842 }
843
844 private BundleContext createContext(BundleContext context) {
845 if (m_serviceRegistryCache != null) {
846 return m_serviceRegistryCache.createBundleContextInterceptor(context);
847 }
848 else {
849 return context;
850 }
851 }
852}