blob: 8a2103742d50df5397b8ba3b6a5390c15b97c886 [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
470 * @param configType the configuration type to use instead of a dictionary or map.
471 * @return a service that acts as a factory for generating the managed service factory configuration adapter
472 */
473 public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate, Class<?> configType) {
474 return new FactoryConfigurationAdapterImpl(this, factoryPid, update, propagate, null, configType);
475 }
476
477 /**
478 * Creates a new Managed Service Factory Configuration Adapter using a specific update callback instance.
479 * For each new Config Admin factory configuration matching the factoryPid, an adapter will be created
480 * based on the adapter implementation class.
481 * The adapter will be registered with the specified interface, and with the specified adapter service properties.
482 * Depending on the <code>propagate</code> parameter, every public factory configuration properties
483 * (which don't start with ".") will be propagated along with the adapter service properties.
484 * It will also inherit all dependencies.
485 *
486 * @param factoryPid the pid matching the factory configuration
487 * @param update the adapter method name that will be notified when the factory configuration is created/updated.<p>
488 * The following signatures are supported:<p>
489 * <ul><li> updated(Dictionary)
490 * <li> updated(Component, Dictionary)
491 * </ul>
492 * @param propagate true if public factory configuration should be propagated to the adapter service properties
493 * @param callbackInstance the object on which the updated callback will be invoked.
494 * @param configType the configuration type to use instead of a dictionary or map.
495 * @return a service that acts as a factory for generating the managed service factory configuration adapter
496 */
497 public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate, Object callbackInstance, Class<?> configType) {
498 return new FactoryConfigurationAdapterImpl(this, factoryPid, update, propagate, callbackInstance, configType);
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000499 }
500
501 /**
Pierre De Rop3a00a212015-03-01 09:27:46 +0000502 * Creates a new Managed Service Factory Configuration Adapter with meta type support. For each new Config Admin
503 * factory configuration matching the factoryPid, an adapter will be created based on the adapter implementation
504 * class. The adapter will be registered with the specified interface, and with the specified adapter service
505 * properties. Depending on the <code>propagate</code> parameter, every public factory configuration properties
506 * (which don't start with ".") will be propagated along with the adapter service properties.
507 * It will also inherit all dependencies.
508 *
509 * <h3>Usage Example</h3>
510 *
511 * <blockquote><pre>
512 * PropertyMetaData[] propertiesMetaData = new PropertyMetaData[] {
513 * manager.createPropertyMetaData()
514 * .setCardinality(Integer.MAX_VALUE)
515 * .setType(String.class)
516 * .setHeading("English words")
517 * .setDescription("Declare here some valid english words")
518 * .setDefaults(new String[] {"hello", "world"})
519 * .setId("words")
520 * };
521 *
522 * manager.add(createFactoryConfigurationAdapterService("FactoryPid",
523 * "updated",
524 * true, // propagate CM settings
525 * "EnglishDictionary",
526 * "English dictionary configuration properties",
527 * null,
528 * propertiesMetaData)
529 * .setImplementation(Adapter.class));
530 * </pre></blockquote>
531 *
532 * @param factoryPid the pid matching the factory configuration
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000533 * @param update the adapter method name that will be notified when the factory configuration is created/updated.<p>
534 * The following signatures are supported:<p>
535 * <ul><li> updated(Dictionary)
536 * <li> updated(Component, Dictionary)
537 * </ul>
Pierre De Rop3a00a212015-03-01 09:27:46 +0000538 * @param propagate true if public factory configuration should be propagated to the adapter service properties
539 * @param heading The label used to display the tab name (or section) where the properties are displayed.
540 * Example: "Printer Service"
541 * @param desc A human readable description of the factory PID this configuration is associated with.
542 * Example: "Configuration for the PrinterService bundle"
543 * @param localization Points to the basename of the Properties file that can localize the Meta Type informations.
544 * The default localization base name for the properties is OSGI-INF/l10n/bundle, but can
545 * be overridden by the manifest Bundle-Localization header (see core specification, in section Localization
546 * on page 68). You can specify a specific localization basename file using this parameter
547 * (e.g. <code>"person"</code> will match person_du_NL.properties in the root bundle directory).
548 * @param propertiesMetaData Array of MetaData regarding configuration properties
549 * @return a service that acts as a factory for generating the managed service factory configuration adapter
550 */
551 public Component createAdapterFactoryConfigurationService(String factoryPid, String update, boolean propagate,
552 String heading, String desc, String localization, PropertyMetaData[] propertiesMetaData)
553 {
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000554 return new FactoryConfigurationAdapterImpl(this, factoryPid, update, propagate, null, m_context, m_logger, heading,
Pierre De Rop3a00a212015-03-01 09:27:46 +0000555 desc, localization, propertiesMetaData);
556 }
557
558 /**
559 * Creates a new bundle adapter. The adapter will be applied to any bundle that
560 * matches the specified bundle state mask and filter condition. For each matching
561 * bundle an adapter will be created based on the adapter implementation class.
562 * The adapter will be registered with the specified interface
563 *
564 * TODO and existing properties from the original resource plus any extra properties you supply here.
565 * It will also inherit all dependencies, and if you declare the original
566 * service as a member it will be injected.
567 *
568 * <h3>Usage Example</h3>
569 *
570 * <blockquote><pre>
571 * manager.createBundleAdapterService(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE,
572 * "(Bundle-SymbolicName=org.apache.felix.dependencymanager)",
573 * true)
574 * // The interface to use when registering adapter
575 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
576 * // the implementation of the adapter
577 * .setImplementation(AdapterServiceImpl.class);
578 * </pre></blockquote>
579 *
580 * @param bundleStateMask the bundle state mask to apply
581 * @param bundleFilter the filter to apply to the bundle manifest
582 * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
583 * @return a service that acts as a factory for generating bundle adapters
584 */
585 public Component createBundleAdapterService(int bundleStateMask, String bundleFilter, boolean propagate) {
586 return new BundleAdapterImpl(this, bundleStateMask, bundleFilter, propagate);
587 }
588
589 /**
Pierre De Ropc40d93f2015-05-04 20:25:57 +0000590 * Creates a new bundle adapter using specific callback instance.
591 * The adapter will be applied to any bundle that matches the specified bundle state mask and filter condition.
592 * For each matching bundle an adapter will be created based on the adapter implementation class, and
593 * The adapter will be registered with the specified interface.
594 *
595 * @param bundleStateMask the bundle state mask to apply
596 * @param bundleFilter the filter to apply to the bundle manifest
597 * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
598 * @param callbackInstance the instance to invoke the callbacks on, or null if the callbacks have to be invoked on the adapter itself
599 * @param add name of the callback method to invoke on add
600 * @param change name of the callback method to invoke on change
601 * @param remove name of the callback method to invoke on remove
602 * @return a service that acts as a factory for generating bundle adapters
603 */
604 public Component createBundleAdapterService(int bundleStateMask, String bundleFilter, boolean propagate,
605 Object callbackInstance, String add, String change, String remove) {
606 return new BundleAdapterImpl(this, bundleStateMask, bundleFilter, propagate, callbackInstance, add, change, remove);
607 }
608
609 /**
Pierre De Rop3a00a212015-03-01 09:27:46 +0000610 * Creates a new resource adapter. The adapter will be applied to any resource that
611 * matches the specified filter condition. For each matching resource
612 * an adapter will be created based on the adapter implementation class.
613 * The adapter will be registered with the specified interface and existing properties
614 * from the original resource plus any extra properties you supply here.
615 * It will also inherit all dependencies, and if you declare the original
616 * service as a member it will be injected.
617 *
618 * <h3>Usage Example</h3>
619 *
620 * <blockquote><pre>
621 * manager.createResourceAdapterService("(&(path=/test)(repository=TestRepository))", true)
622 * // The interface to use when registering adapter
623 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
624 * // the implementation of the adapter
625 * .setImplementation(AdapterServiceImpl.class);
626 * </pre></blockquote>
627 *
628 * @param resourceFilter the filter condition to use with the resource
629 * @param propagate <code>true</code> if properties from the resource should be propagated to the service
630 * @param callbackInstance instance to invoke the callback on
631 * @param callbackChanged the name of the callback method
632 * @return a service that acts as a factory for generating resource adapters
633 */
634 public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance,
635 String callbackChanged)
636 {
637 return new ResourceAdapterImpl(this, resourceFilter, propagate, callbackInstance, null, callbackChanged);
638 }
639
640 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
641 public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance,
642 String callbackSet, String callbackChanged)
643 {
644 return new ResourceAdapterImpl(this, resourceFilter, propagate, callbackInstance, callbackSet, callbackChanged);
645 }
646
647 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
648 public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance,
649 String propagateCallbackMethod, Object callbackInstance, String callbackChanged)
650 {
651 return new ResourceAdapterImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod,
652 callbackInstance, null, callbackChanged);
653 }
654
655 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
656 public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance,
657 String propagateCallbackMethod, Object callbackInstance, String callbackSet, String callbackChanged)
658 {
659 return new ResourceAdapterImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod,
660 callbackInstance, callbackSet, callbackChanged);
661 }
662
663 /**
664 * Returns a list of components.
665 *
666 * @return a list of components
667 */
668 public List<Component> getComponents() {
669 return Collections.list(m_components.elements());
670 }
671
672 /**
673 * Creates a new aspect. The aspect will be applied to any service that
674 * matches the specified interface and filter. For each matching service
675 * an aspect will be created based on the aspect implementation class.
676 * The aspect will be registered with the same interface and properties
677 * as the original service, plus any extra properties you supply here.
678 * It will also inherit all dependencies, and if you declare the original
679 * service as a member it will be injected.
680 *
681 * <h3>Usage Example</h3>
682 *
683 * <blockquote><pre>
684 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "m_service")
685 * .setImplementation(ExistingServiceAspect.class)
686 * );
687 * </pre></blockquote>
688 *
689 * @param serviceInterface the service interface to apply the aspect to
690 * @param serviceFilter the filter condition to use with the service interface
691 * @param ranking the level used to organize the aspect chain ordering
692 * @param autoConfig the aspect implementation field name where to inject original service.
693 * If null, any field matching the original service will be injected.
694 * @return a service that acts as a factory for generating aspects
695 */
696 public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, String autoConfig) {
Pierre De Rop32b68c82016-01-11 21:52:47 +0000697 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, autoConfig, null, null, null, null, null);
Pierre De Rop3a00a212015-03-01 09:27:46 +0000698 }
699
700 /**
701 * Creates a new aspect. The aspect will be applied to any service that
702 * matches the specified interface and filter. For each matching service
703 * an aspect will be created based on the aspect implementation class.
704 * The aspect will be registered with the same interface and properties
705 * as the original service, plus any extra properties you supply here.
706 * It will also inherit all dependencies, and if you declare the original
707 * service as a member it will be injected.
708 *
709 * <h3>Usage Example</h3>
710 *
711 * <blockquote><pre>
712 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10)
713 * .setImplementation(ExistingServiceAspect.class)
714 * );
715 * </pre></blockquote>
716 *
717 * @param serviceInterface the service interface to apply the aspect to
718 * @param serviceFilter the filter condition to use with the service interface
719 * @param ranking the level used to organize the aspect chain ordering
720 * @return a service that acts as a factory for generating aspects
721 */
722 public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking) {
Pierre De Rop32b68c82016-01-11 21:52:47 +0000723 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, null, null, null, null);
Pierre De Rop3a00a212015-03-01 09:27:46 +0000724 }
725
726 /**
727 * Creates a new aspect. The aspect will be applied to any service that
728 * matches the specified interface and filter. For each matching service
729 * an aspect will be created based on the aspect implementation class.
730 * The aspect will be registered with the same interface and properties
731 * as the original service, plus any extra properties you supply here.
732 * It will also inherit all dependencies, and if you declare the original
733 * service as a member it will be injected.
734 *
735 * <h3>Usage Example</h3>
736 *
737 * <blockquote><pre>
738 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
739 * .setImplementation(ExistingServiceAspect.class)
740 * );
741 * </pre></blockquote>
742 *
743 * @param serviceInterface the service interface to apply the aspect to
744 * @param serviceFilter the filter condition to use with the service interface
745 * @param ranking the level used to organize the aspect chain ordering
746 * @param add name of the callback method to invoke on add
747 * @param change name of the callback method to invoke on change
748 * @param remove name of the callback method to invoke on remove
749 * @return a service that acts as a factory for generating aspects
750 */
751 public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, String add,
752 String change, String remove)
753 {
Pierre De Rop32b68c82016-01-11 21:52:47 +0000754 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, add, change, remove, null);
Pierre De Rop3a00a212015-03-01 09:27:46 +0000755 }
756
757 /**
758 * Creates a new aspect. The aspect will be applied to any service that
759 * matches the specified interface and filter. For each matching service
760 * an aspect will be created based on the aspect implementation class.
761 * The aspect will be registered with the same interface and properties
762 * as the original service, plus any extra properties you supply here.
763 * It will also inherit all dependencies, and if you declare the original
764 * service as a member it will be injected.
765 *
766 * <h3>Usage Example</h3>
767 *
768 * <blockquote><pre>
769 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
770 * .setImplementation(ExistingServiceAspect.class)
771 * );
772 * </pre></blockquote>
773 *
774 * @param serviceInterface the service interface to apply the aspect to
775 * @param serviceFilter the filter condition to use with the service interface
776 * @param ranking the level used to organize the aspect chain ordering
777 * @param add name of the callback method to invoke on add
778 * @param change name of the callback method to invoke on change
779 * @param remove name of the callback method to invoke on remove
780 * @param swap name of the callback method to invoke on swap
781 * @return a service that acts as a factory for generating aspects
782 */
783 public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, String add,
784 String change, String remove, String swap)
785 {
Pierre De Rop32b68c82016-01-11 21:52:47 +0000786 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, add, change, remove, swap);
787 }
788
789 /**
790 * Creates a new aspect. The aspect will be applied to any service that
791 * matches the specified interface and filter. For each matching service
792 * an aspect will be created based on the aspect implementation class.
793 * The aspect will be registered with the same interface and properties
794 * as the original service, plus any extra properties you supply here.
795 * It will also inherit all dependencies, and if you declare the original
796 * service as a member it will be injected.
797 *
798 * <h3>Usage Example</h3>
799 *
800 * <blockquote><pre>
801 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
802 * .setImplementation(ExistingServiceAspect.class)
803 * );
804 * </pre></blockquote>
805 *
806 * @param serviceInterface the service interface to apply the aspect to
807 * @param serviceFilter the filter condition to use with the service interface
808 * @param ranking the level used to organize the aspect chain ordering
809 * @param callbackInstance the instance to invoke the callbacks on, or null if the callbacks have to be invoked on the aspect itself
810 * @param add name of the callback method to invoke on add
811 * @param change name of the callback method to invoke on change
812 * @param remove name of the callback method to invoke on remove
813 * @param swap name of the callback method to invoke on swap
814 * @return a service that acts as a factory for generating aspects
815 */
816 public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, Object callbackInstance,
817 String add, String change, String remove, String swap)
818 {
819 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, callbackInstance, add, change, remove, swap);
Pierre De Rop3a00a212015-03-01 09:27:46 +0000820 }
821
822 /**
823 * Removes all components and their dependencies.
824 */
825 public void clear() {
826 for (Component component : m_components.keySet()) {
827 remove(component);
828 }
829 m_components.clear();
830 }
831
832 /**
833 * Creates a new configuration property metadata.
834 *
835 * @return the configuration property metadata.
836 */
837 public PropertyMetaData createPropertyMetaData() {
838 return new PropertyMetaDataImpl();
839 }
840
841 private BundleContext createContext(BundleContext context) {
842 if (m_serviceRegistryCache != null) {
843 return m_serviceRegistryCache.createBundleContextInterceptor(context);
844 }
845 else {
846 return context;
847 }
848 }
849}