blob: 8a761800bc9986e5c8ebc1224b808f42b789cb1e [file] [log] [blame]
Marcel Offermansa962bc92009-11-21 17:59:33 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Pierre De Ropae4a5db2009-12-04 22:08:05 +000019package org.apache.felix.dm;
Marcel Offermansa962bc92009-11-21 17:59:33 +000020
Marcel Offermans5be5f142011-04-26 10:47:12 +000021import java.lang.ref.WeakReference;
Marcel Offermansa962bc92009-11-21 17:59:33 +000022import java.util.ArrayList;
23import java.util.Collections;
Marcel Offermans5be5f142011-04-26 10:47:12 +000024import java.util.HashSet;
25import java.util.Iterator;
Marcel Offermansa962bc92009-11-21 17:59:33 +000026import java.util.List;
Marcel Offermans5be5f142011-04-26 10:47:12 +000027import java.util.Set;
Marcel Offermansa962bc92009-11-21 17:59:33 +000028
Pierre De Rop34231582010-05-23 20:05:16 +000029import org.apache.felix.dm.impl.AdapterServiceImpl;
Pierre De Rop19476fe2010-05-23 08:13:58 +000030import org.apache.felix.dm.impl.AspectServiceImpl;
Pierre De Rop13dd63d2010-05-23 21:58:28 +000031import org.apache.felix.dm.impl.BundleAdapterServiceImpl;
Marcel Offermansfaaed472010-09-08 10:07:32 +000032import org.apache.felix.dm.impl.ComponentImpl;
Pierre De Rop3e100372010-05-24 12:43:44 +000033import org.apache.felix.dm.impl.FactoryConfigurationAdapterServiceImpl;
Pierre De Ropae4a5db2009-12-04 22:08:05 +000034import org.apache.felix.dm.impl.Logger;
Pierre De Rop445ddec2010-05-23 21:05:27 +000035import org.apache.felix.dm.impl.ResourceAdapterServiceImpl;
Pierre De Ropae4a5db2009-12-04 22:08:05 +000036import org.apache.felix.dm.impl.dependencies.BundleDependencyImpl;
37import org.apache.felix.dm.impl.dependencies.ConfigurationDependencyImpl;
38import org.apache.felix.dm.impl.dependencies.ResourceDependencyImpl;
39import org.apache.felix.dm.impl.dependencies.ServiceDependencyImpl;
40import org.apache.felix.dm.impl.dependencies.TemporalServiceDependencyImpl;
Marcel Offermans90ba4fa2011-04-27 07:57:44 +000041import org.apache.felix.dm.impl.index.AspectFilterIndex;
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +000042import org.apache.felix.dm.impl.index.AdapterFilterIndex;
Marcel Offermans90ba4fa2011-04-27 07:57:44 +000043import org.apache.felix.dm.impl.index.ServiceRegistryCache;
Xander Uiterlinden48f267b2013-06-03 12:13:09 +000044import org.apache.felix.dm.impl.index.multiproperty.MultiPropertyFilterIndex;
Pierre De Ropa0204f52010-03-06 22:23:57 +000045import org.apache.felix.dm.impl.metatype.PropertyMetaDataImpl;
Marcel Offermansa7dadd52011-06-22 12:10:01 +000046import org.osgi.framework.Bundle;
Marcel Offermansb8405a52009-12-22 19:01:31 +000047import org.osgi.framework.BundleContext;
Marcel Offermansa7dadd52011-06-22 12:10:01 +000048import org.osgi.framework.BundleException;
Marcel Offermans227dd712011-04-19 07:14:22 +000049import org.osgi.framework.FrameworkUtil;
Marcel Offermansa962bc92009-11-21 17:59:33 +000050
51/**
Marcel Offermansfaaed472010-09-08 10:07:32 +000052 * The dependency manager manages all components and their dependencies. Using
53 * this API you can declare all components and their dependencies. Under normal
Marcel Offermans4fd903f2009-12-29 09:18:05 +000054 * circumstances, you get passed an instance of this class through the
55 * <code>DependencyActivatorBase</code> subclass you use as your
56 * <code>BundleActivator</code>, but it is also possible to create your
57 * own instance.
Marcel Offermansa962bc92009-11-21 17:59:33 +000058 *
59 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
60 */
61public class DependencyManager {
Marcel Offermansad760672010-03-03 15:30:01 +000062 public static final String ASPECT = "org.apache.felix.dependencymanager.aspect";
Marcel Offermans540daac2011-06-22 07:25:33 +000063 public static final String SERVICEREGISTRY_CACHE_INDICES = "org.apache.felix.dependencymanager.filterindex";
Marcel Offermanse0906072011-05-17 11:09:05 +000064 public static final String METHOD_CACHE_SIZE = "org.apache.felix.dependencymanager.methodcache";
Marcel Offermansa962bc92009-11-21 17:59:33 +000065 private final BundleContext m_context;
66 private final Logger m_logger;
Marcel Offermans5be5f142011-04-26 10:47:12 +000067 private List m_components = Collections.synchronizedList(new ArrayList());
Marcel Offermansa962bc92009-11-21 17:59:33 +000068
69 /**
Marcel Offermans4fd903f2009-12-29 09:18:05 +000070 * Creates a new dependency manager. You need to supply the
71 * <code>BundleContext</code> to be used by the dependency
72 * manager to register services and communicate with the
73 * framework.
Marcel Offermansa962bc92009-11-21 17:59:33 +000074 *
75 * @param context the bundle context
Marcel Offermansa962bc92009-11-21 17:59:33 +000076 */
Pierre De Ropae4a5db2009-12-04 22:08:05 +000077 public DependencyManager(BundleContext context) {
78 this(context, new Logger(context));
79 }
80
Marcel Offermans4fd903f2009-12-29 09:18:05 +000081 DependencyManager(BundleContext context, Logger logger) {
Marcel Offermans227dd712011-04-19 07:14:22 +000082 m_context = createContext(context);
Marcel Offermansa962bc92009-11-21 17:59:33 +000083 m_logger = logger;
Marcel Offermans5be5f142011-04-26 10:47:12 +000084 synchronized (m_dependencyManagers) {
85 m_dependencyManagers.add(new WeakReference(this));
86 }
Marcel Offermansa962bc92009-11-21 17:59:33 +000087 }
Pierre De Ropae4a5db2009-12-04 22:08:05 +000088
Marcel Offermans227dd712011-04-19 07:14:22 +000089 // service registry cache
90 private static ServiceRegistryCache m_serviceRegistryCache;
Marcel Offermans5be5f142011-04-26 10:47:12 +000091 private static final Set /* WeakReference<DependencyManager> */ m_dependencyManagers = new HashSet();
Marcel Offermans227dd712011-04-19 07:14:22 +000092 static {
93 String index = System.getProperty(SERVICEREGISTRY_CACHE_INDICES);
Marcel Offermans227dd712011-04-19 07:14:22 +000094 if (index != null) {
Marcel Offermansa7dadd52011-06-22 12:10:01 +000095 Bundle bundle = FrameworkUtil.getBundle(DependencyManager.class);
96 try {
97 if (bundle.getState() != Bundle.ACTIVE) {
98 bundle.start();
Marcel Offermansfd7deb02011-04-20 11:26:09 +000099 }
Marcel Offermansa7dadd52011-06-22 12:10:01 +0000100 BundleContext bundleContext = bundle.getBundleContext();
101
102 m_serviceRegistryCache = new ServiceRegistryCache(bundleContext);
103 m_serviceRegistryCache.open(); // TODO close it somewhere
104 String[] props = index.split(";");
105 for (int i = 0; i < props.length; i++) {
106 if (props[i].equals("*aspect*")) {
107 m_serviceRegistryCache.addFilterIndex(new AspectFilterIndex());
Marcel Offermanscba269a2013-01-18 11:00:56 +0000108 }
109 else if (props[i].equals("*adapter*")) {
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +0000110 m_serviceRegistryCache.addFilterIndex(new AdapterFilterIndex());
Marcel Offermansa7dadd52011-06-22 12:10:01 +0000111 }
112 else {
Xander Uiterlinden48f267b2013-06-03 12:13:09 +0000113 m_serviceRegistryCache.addFilterIndex(new MultiPropertyFilterIndex(props[i]));
Marcel Offermansa7dadd52011-06-22 12:10:01 +0000114 }
Marcel Offermansfd7deb02011-04-20 11:26:09 +0000115 }
Marcel Offermans227dd712011-04-19 07:14:22 +0000116 }
Marcel Offermansa7dadd52011-06-22 12:10:01 +0000117 catch (BundleException e) {
118 // if we cannot start ourselves, we cannot use the indices
119 // TODO we might want to warn people about this
120 }
Marcel Offermans227dd712011-04-19 07:14:22 +0000121 }
Marcel Offermans5be5f142011-04-26 10:47:12 +0000122 }
123
124 public static List getDependencyManagers() {
125 List /* DependencyManager */ result = new ArrayList();
126 synchronized (m_dependencyManagers) {
127 Iterator iterator = m_dependencyManagers.iterator();
128 while (iterator.hasNext()) {
129 WeakReference reference = (WeakReference) iterator.next();
130 DependencyManager manager = (DependencyManager) reference.get();
131 if (manager != null) {
Marcel Offermansc7fbf782011-05-18 14:34:33 +0000132 try {
133 manager.getBundleContext().getBundle();
134 result.add(manager);
135 continue;
136 }
137 catch (IllegalStateException e) {
138 }
Marcel Offermans5be5f142011-04-26 10:47:12 +0000139 }
Marcel Offermansc7fbf782011-05-18 14:34:33 +0000140 iterator.remove();
Marcel Offermans5be5f142011-04-26 10:47:12 +0000141 }
Marcel Offermans227dd712011-04-19 07:14:22 +0000142 }
Marcel Offermans5be5f142011-04-26 10:47:12 +0000143 return result;
Marcel Offermans227dd712011-04-19 07:14:22 +0000144 }
145
146 private BundleContext createContext(BundleContext context) {
147 if (m_serviceRegistryCache != null) {
Marcel Offermans227dd712011-04-19 07:14:22 +0000148 return m_serviceRegistryCache.createBundleContextInterceptor(context);
149 }
150 else {
151 return context;
152 }
153 }
Marcel Offermans5be5f142011-04-26 10:47:12 +0000154
155 public BundleContext getBundleContext() {
156 return m_context;
157 }
Marcel Offermans227dd712011-04-19 07:14:22 +0000158
Marcel Offermansa962bc92009-11-21 17:59:33 +0000159 /**
160 * Adds a new service to the dependency manager. After the service was added
161 * it will be started immediately.
162 *
163 * @param service the service to add
164 */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000165 public void add(Component service) {
Marcel Offermans5be5f142011-04-26 10:47:12 +0000166 m_components.add(service);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000167 service.start();
168 }
169
170 /**
171 * Removes a service from the dependency manager. Before the service is removed
172 * it is stopped first.
173 *
174 * @param service the service to remove
175 */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000176 public void remove(Component service) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000177 service.stop();
Marcel Offermans5be5f142011-04-26 10:47:12 +0000178 m_components.remove(service);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000179 }
180
181 /**
182 * Creates a new service.
183 *
184 * @return the new service
185 */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000186 public Component createComponent() {
187 return new ComponentImpl(m_context, this, m_logger);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000188 }
189
190 /**
191 * Creates a new service dependency.
192 *
193 * @return the service dependency
194 */
195 public ServiceDependency createServiceDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000196 return new ServiceDependencyImpl(m_context, m_logger);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000197 }
198
Marcel Offermans74363c32009-11-23 19:56:08 +0000199 /**
200 * Creates a new temporal service dependency.
201 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000202 * @return a new temporal service dependency
Marcel Offermans74363c32009-11-23 19:56:08 +0000203 */
204 public TemporalServiceDependency createTemporalServiceDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000205 return new TemporalServiceDependencyImpl(m_context, m_logger);
Marcel Offermans74363c32009-11-23 19:56:08 +0000206 }
Marcel Offermans2925f172009-12-02 13:03:39 +0000207
208 /**
209 * Creates a new configuration dependency.
210 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000211 * @return the configuration dependency
Marcel Offermans2925f172009-12-02 13:03:39 +0000212 */
Marcel Offermansa962bc92009-11-21 17:59:33 +0000213 public ConfigurationDependency createConfigurationDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000214 return new ConfigurationDependencyImpl(m_context, m_logger);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000215 }
216
Marcel Offermans2925f172009-12-02 13:03:39 +0000217 /**
Marcel Offermansfaaed472010-09-08 10:07:32 +0000218 * Creates a new configuration property metadata.
219 *
220 * @return the configuration property metadata.
Pierre De Ropa0204f52010-03-06 22:23:57 +0000221 */
222 public PropertyMetaData createPropertyMetaData() {
223 return new PropertyMetaDataImpl();
224 }
225
226 /**
Marcel Offermans2925f172009-12-02 13:03:39 +0000227 * Creates a new bundle dependency.
228 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000229 * @return a new BundleDependency instance.
Marcel Offermans2925f172009-12-02 13:03:39 +0000230 */
Marcel Offermansd66c5ce2009-11-26 09:58:44 +0000231 public BundleDependency createBundleDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000232 return new BundleDependencyImpl(m_context, m_logger);
Marcel Offermansd66c5ce2009-11-26 09:58:44 +0000233 }
Marcel Offermans2925f172009-12-02 13:03:39 +0000234
235 /**
236 * Creates a new resource dependency.
237 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000238 * @return the resource dependency
Marcel Offermans2925f172009-12-02 13:03:39 +0000239 */
240 public ResourceDependency createResourceDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000241 return new ResourceDependencyImpl(m_context, m_logger);
Marcel Offermans2925f172009-12-02 13:03:39 +0000242 }
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000243
Marcel Offermans2925f172009-12-02 13:03:39 +0000244 /**
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000245 * Creates a new aspect. The aspect will be applied to any service that
246 * matches the specified interface and filter. For each matching service
247 * an aspect will be created based on the aspect implementation class.
248 * The aspect will be registered with the same interface and properties
249 * as 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.
Marcel Offermans2925f172009-12-02 13:03:39 +0000252 *
Pierre De Rop19476fe2010-05-23 08:13:58 +0000253 * <h3>Usage Example</h3>
254 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000255 * <blockquote><pre>
Marcel Offermansa8818d52011-03-09 10:03:35 +0000256 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "m_service")
257 * .setImplementation(ExistingServiceAspect.class)
258 * );
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000259 * </pre></blockquote>
Pierre De Rop19476fe2010-05-23 08:13:58 +0000260 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000261 * @param serviceInterface the service interface to apply the aspect to
262 * @param serviceFilter the filter condition to use with the service interface
Pierre De Rop19476fe2010-05-23 08:13:58 +0000263 * @param ranking the level used to organize the aspect chain ordering
Marcel Offermansa8818d52011-03-09 10:03:35 +0000264 * @param autoConfig the aspect implementation field name where to inject original service.
Marcel Offermansfaaed472010-09-08 10:07:32 +0000265 * If null, any field matching the original service will be injected.
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000266 * @return a service that acts as a factory for generating aspects
Marcel Offermans2925f172009-12-02 13:03:39 +0000267 */
Marcel Offermansa8818d52011-03-09 10:03:35 +0000268 public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String autoConfig) {
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +0000269 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, autoConfig, null, null, null, null);
Marcel Offermansa8818d52011-03-09 10:03:35 +0000270 }
271 /**
272 * Creates a new aspect. The aspect will be applied to any service that
273 * matches the specified interface and filter. For each matching service
274 * an aspect will be created based on the aspect implementation class.
275 * The aspect will be registered with the same interface and properties
276 * as the original service, plus any extra properties you supply here.
277 * It will also inherit all dependencies, and if you declare the original
278 * service as a member it will be injected.
279 *
280 * <h3>Usage Example</h3>
281 *
282 * <blockquote><pre>
283 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10)
284 * .setImplementation(ExistingServiceAspect.class)
285 * );
286 * </pre></blockquote>
287 *
288 * @param serviceInterface the service interface to apply the aspect to
289 * @param serviceFilter the filter condition to use with the service interface
290 * @param ranking the level used to organize the aspect chain ordering
291 * @return a service that acts as a factory for generating aspects
292 */
293 public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking) {
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +0000294 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, null, null, null);
Marcel Offermansa8818d52011-03-09 10:03:35 +0000295 }
296 /**
297 * Creates a new aspect. The aspect will be applied to any service that
298 * matches the specified interface and filter. For each matching service
299 * an aspect will be created based on the aspect implementation class.
300 * The aspect will be registered with the same interface and properties
301 * as the original service, plus any extra properties you supply here.
302 * It will also inherit all dependencies, and if you declare the original
303 * service as a member it will be injected.
304 *
305 * <h3>Usage Example</h3>
306 *
307 * <blockquote><pre>
308 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
309 * .setImplementation(ExistingServiceAspect.class)
310 * );
311 * </pre></blockquote>
312 *
313 * @param serviceInterface the service interface to apply the aspect to
314 * @param serviceFilter the filter condition to use with the service interface
315 * @param ranking the level used to organize the aspect chain ordering
316 * @param add name of the callback method to invoke on add
317 * @param change name of the callback method to invoke on change
318 * @param remove name of the callback method to invoke on remove
319 * @return a service that acts as a factory for generating aspects
320 */
321 public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String add, String change, String remove) {
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +0000322 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, add, change, remove, null);
323 }
324
325 /**
326 * Creates a new aspect. The aspect will be applied to any service that
327 * matches the specified interface and filter. For each matching service
328 * an aspect will be created based on the aspect implementation class.
329 * The aspect will be registered with the same interface and properties
330 * as 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.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
338 * .setImplementation(ExistingServiceAspect.class)
339 * );
340 * </pre></blockquote>
341 *
342 * @param serviceInterface the service interface to apply the aspect to
343 * @param serviceFilter the filter condition to use with the service interface
344 * @param ranking the level used to organize the aspect chain ordering
345 * @param add name of the callback method to invoke on add
346 * @param change name of the callback method to invoke on change
347 * @param remove name of the callback method to invoke on remove
348 * @param swap name of the callback method to invoke on swap
349 * @return a service that acts as a factory for generating aspects
350 */
351 public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String add, String change, String remove, String swap) {
352 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, add, change, remove, swap);
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000353 }
Marcel Offermanse9c13d92010-07-01 14:01:02 +0000354
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000355 /**
356 * Creates a new adapter. The adapter will be applied to any service that
357 * matches the specified interface and filter. For each matching service
358 * an adapter will be created based on the adapter implementation class.
359 * The adapter will be registered with the specified interface and existing properties
360 * from the original service plus any extra properties you supply here.
361 * It will also inherit all dependencies, and if you declare the original
362 * service as a member it will be injected.
363 *
Pierre De Rop34231582010-05-23 20:05:16 +0000364 * <h3>Usage Example</h3>
365 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000366 * <blockquote><pre>
Marcel Offermansa8818d52011-03-09 10:03:35 +0000367 * manager.createAdapterService(AdapteeService.class, "(foo=bar)")
368 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
369 * .setImplementation(AdapterImpl.class);
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000370 * </pre></blockquote>
Marcel Offermansa8818d52011-03-09 10:03:35 +0000371 *
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000372 * @param serviceInterface the service interface to apply the adapter to
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000373 * @param serviceFilter the filter condition to use with the service interface
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000374 * @return a service that acts as a factory for generating adapters
375 */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000376 public Component createAdapterService(Class serviceInterface, String serviceFilter) {
Marcel Offermansa8818d52011-03-09 10:03:35 +0000377 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, null, null);
378 }
379 /**
380 * Creates a new adapter. The adapter will be applied to any service that
381 * matches the specified interface and filter. For each matching service
382 * an adapter will be created based on the adapter implementation class.
383 * The adapter will be registered with the specified interface and existing properties
384 * from the original service plus any extra properties you supply here.
385 * It will also inherit all dependencies, and if you declare the original
386 * service as a member it will be injected.
387 *
388 * <h3>Usage Example</h3>
389 *
390 * <blockquote><pre>
391 * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "m_service")
392 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
393 * .setImplementation(AdapterImpl.class);
394 * </pre></blockquote>
395 *
396 * @param serviceInterface the service interface to apply the adapter to
397 * @param serviceFilter the filter condition to use with the service interface
398 * @param autoConfig the name of the member to inject the service into
399 * @return a service that acts as a factory for generating adapters
400 */
401 public Component createAdapterService(Class serviceInterface, String serviceFilter, String autoConfig) {
402 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, autoConfig, null, null, null);
403 }
404 /**
405 * Creates a new adapter. The adapter will be applied to any service that
406 * matches the specified interface and filter. For each matching service
407 * an adapter will be created based on the adapter implementation class.
408 * The adapter will be registered with the specified interface and existing properties
409 * from the original service plus any extra properties you supply here.
410 * It will also inherit all dependencies, and if you declare the original
411 * service as a member it will be injected.
412 *
413 * <h3>Usage Example</h3>
414 *
415 * <blockquote><pre>
416 * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove")
417 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
418 * .setImplementation(AdapterImpl.class);
419 * </pre></blockquote>
420 *
421 * @param serviceInterface the service interface to apply the adapter to
422 * @param serviceFilter the filter condition to use with the service interface
423 * @param add name of the callback method to invoke on add
424 * @param change name of the callback method to invoke on change
425 * @param remove name of the callback method to invoke on remove
Marcel Offermans4aa032c2012-01-02 19:18:22 +0000426 * @param swap name of the callback method to invoke on swap
Marcel Offermansa8818d52011-03-09 10:03:35 +0000427 * @return a service that acts as a factory for generating adapters
428 */
Marcel Offermans4aa032c2012-01-02 19:18:22 +0000429 public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove, String swap) {
430 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove, swap);
431 }
432
Marcel Offermanscba269a2013-01-18 11:00:56 +0000433 /** @see DependencyManager#createAdapterService(Class, String, String, String, String, String) */
Marcel Offermansa8818d52011-03-09 10:03:35 +0000434 public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove) {
435 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove);
Marcel Offermans61a81142010-04-02 15:16:50 +0000436 }
Pierre De Rop34231582010-05-23 20:05:16 +0000437
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000438 /**
439 * Creates a new resource adapter. The adapter will be applied to any resource that
440 * matches the specified filter condition. For each matching resource
441 * an adapter will be created based on the adapter implementation class.
442 * The adapter will be registered with the specified interface and existing properties
443 * from the original resource plus any extra properties you supply here.
444 * It will also inherit all dependencies, and if you declare the original
445 * service as a member it will be injected.
446 *
Pierre De Rop445ddec2010-05-23 21:05:27 +0000447 * <h3>Usage Example</h3>
448 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000449 * <blockquote><pre>
Pierre De Rop445ddec2010-05-23 21:05:27 +0000450 * manager.createResourceAdapterService("(&(path=/test)(repository=TestRepository))", true)
451 * // The interface to use when registering adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000452 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
Pierre De Rop445ddec2010-05-23 21:05:27 +0000453 * // the implementation of the adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000454 * .setImplementation(AdapterServiceImpl.class);
455 * </pre></blockquote>
Pierre De Rop445ddec2010-05-23 21:05:27 +0000456 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000457 * @param resourceFilter the filter condition to use with the resource
Marcel Offermansd26f2bd2012-01-02 14:53:17 +0000458 * @param resourcePropertiesFilter the filter condition on the resource properties to use with the resource
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000459 * @param propagate <code>true</code> if properties from the resource should be propagated to the service
Marcel Offermanscba269a2013-01-18 11:00:56 +0000460 * @param callbackInstance instance to invoke the callback on
461 * @param callbackChanged the name of the callback method
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000462 * @return a service that acts as a factory for generating resource adapters
463 * @see Resource
464 */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000465 public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance, String callbackChanged) {
Marcel Offermansd26f2bd2012-01-02 14:53:17 +0000466 return new ResourceAdapterServiceImpl(this, resourceFilter, propagate, callbackInstance, null, callbackChanged);
467 }
468
Marcel Offermanscba269a2013-01-18 11:00:56 +0000469 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
Marcel Offermansd26f2bd2012-01-02 14:53:17 +0000470 public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance, String callbackSet, String callbackChanged) {
471 return new ResourceAdapterServiceImpl(this, resourceFilter, propagate, callbackInstance, callbackSet, callbackChanged);
Marcel Offermans61a81142010-04-02 15:16:50 +0000472 }
Pierre De Rop445ddec2010-05-23 21:05:27 +0000473
Marcel Offermanscba269a2013-01-18 11:00:56 +0000474 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000475 public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackChanged) {
Marcel Offermansd26f2bd2012-01-02 14:53:17 +0000476 return new ResourceAdapterServiceImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, null, callbackChanged);
477 }
478
Marcel Offermanscba269a2013-01-18 11:00:56 +0000479 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
Marcel Offermansd26f2bd2012-01-02 14:53:17 +0000480 public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackSet, String callbackChanged) {
481 return new ResourceAdapterServiceImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, callbackSet, callbackChanged);
Marcel Offermans26081d32010-07-12 12:43:42 +0000482 }
483
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000484 /**
485 * Creates a new bundle adapter. The adapter will be applied to any bundle that
486 * matches the specified bundle state mask and filter condition. For each matching
487 * bundle an adapter will be created based on the adapter implementation class.
488 * The adapter will be registered with the specified interface
489 *
490 * TODO and existing properties from the original resource plus any extra properties you supply here.
491 * It will also inherit all dependencies, and if you declare the original
492 * service as a member it will be injected.
493 *
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000494 * <h3>Usage Example</h3>
495 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000496 * <blockquote><pre>
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000497 * manager.createBundleAdapterService(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE,
498 * "(Bundle-SymbolicName=org.apache.felix.dependencymanager)",
499 * true)
500 * // The interface to use when registering adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000501 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000502 * // the implementation of the adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000503 * .setImplementation(AdapterServiceImpl.class);
504 * </pre></blockquote>
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000505 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000506 * @param bundleStateMask the bundle state mask to apply
507 * @param bundleFilter the filter to apply to the bundle manifest
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000508 * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000509 * @return a service that acts as a factory for generating bundle adapters
510 */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000511 public Component createBundleAdapterService(int bundleStateMask, String bundleFilter, boolean propagate) {
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000512 return new BundleAdapterServiceImpl(this, bundleStateMask, bundleFilter, propagate);
Marcel Offermans61a81142010-04-02 15:16:50 +0000513 }
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000514
Marcel Offermansa962bc92009-11-21 17:59:33 +0000515 /**
Pierre De Ropef94c882010-04-17 18:23:35 +0000516 * Creates a new Managed Service Factory Configuration Adapter. For each new Config Admin factory configuration matching
517 * the factoryPid, an adapter will be created based on the adapter implementation class.
518 * The adapter will be registered with the specified interface, and with the specified adapter service properties.
519 * Depending on the <code>propagate</code> parameter, every public factory configuration properties
520 * (which don't start with ".") will be propagated along with the adapter service properties.
521 * It will also inherit all dependencies.
522 *
Pierre De Rop3e100372010-05-24 12:43:44 +0000523 * <h3>Usage Example</h3>
524 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000525 * <blockquote><pre>
Pierre De Rop3e100372010-05-24 12:43:44 +0000526 * manager.createFactoryConfigurationAdapterService("MyFactoryPid", "update", true)
527 * // The interface to use when registering adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000528 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
Pierre De Rop3e100372010-05-24 12:43:44 +0000529 * // the implementation of the adapter
530 * .setImplementation(AdapterServiceImpl.class);
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000531 * </pre></blockquote>
532 *
Pierre De Ropef94c882010-04-17 18:23:35 +0000533 * @param factoryPid the pid matching the factory configuration
534 * @param update the adapter method name that will be notified when the factory configuration is created/updated.
Pierre De Ropef94c882010-04-17 18:23:35 +0000535 * @param propagate true if public factory configuration should be propagated to the adapter service properties
536 * @return a service that acts as a factory for generating the managed service factory configuration adapter
537 */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000538 public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate) {
Pierre De Rop3e100372010-05-24 12:43:44 +0000539 return new FactoryConfigurationAdapterServiceImpl(this, factoryPid, update, propagate);
Pierre De Ropef94c882010-04-17 18:23:35 +0000540 }
541
542 /**
Pierre De Rop3e100372010-05-24 12:43:44 +0000543 * Creates a new Managed Service Factory Configuration Adapter with meta type support. For each new Config Admin
544 * factory configuration matching the factoryPid, an adapter will be created based on the adapter implementation
545 * class. The adapter will be registered with the specified interface, and with the specified adapter service
546 * properties. Depending on the <code>propagate</code> parameter, every public factory configuration properties
Pierre De Ropef94c882010-04-17 18:23:35 +0000547 * (which don't start with ".") will be propagated along with the adapter service properties.
548 * It will also inherit all dependencies.
549 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000550 * <h3>Usage Example</h3>
551 *
552 * <blockquote><pre>
553 * PropertyMetaData[] propertiesMetaData = new PropertyMetaData[] {
554 * manager.createPropertyMetaData()
555 * .setCardinality(Integer.MAX_VALUE)
556 * .setType(String.class)
557 * .setHeading("English words")
558 * .setDescription("Declare here some valid english words")
559 * .setDefaults(new String[] {"hello", "world"})
560 * .setId("words")
561 * };
562 *
563 * manager.add(createFactoryConfigurationAdapterService("FactoryPid",
564 * "updated",
565 * true, // propagate CM settings
566 * "EnglishDictionary",
567 * "English dictionary configuration properties",
568 * null,
569 * propertiesMetaData)
570 * .setImplementation(Adapter.class));
571 * </pre></blockquote>
572 *
Pierre De Ropef94c882010-04-17 18:23:35 +0000573 * @param factoryPid the pid matching the factory configuration
574 * @param update the adapter method name that will be notified when the factory configuration is created/updated.
Pierre De Ropef94c882010-04-17 18:23:35 +0000575 * @param propagate true if public factory configuration should be propagated to the adapter service properties
Pierre De Rop3e100372010-05-24 12:43:44 +0000576 * @param heading The label used to display the tab name (or section) where the properties are displayed.
577 * Example: "Printer Service"
578 * @param desc A human readable description of the factory PID this configuration is associated with.
579 * Example: "Configuration for the PrinterService bundle"
Pierre De Rop9a8ebfd2010-04-25 22:25:34 +0000580 * @param localization Points to the basename of the Properties file that can localize the Meta Type informations.
581 * The default localization base name for the properties is OSGI-INF/l10n/bundle, but can
Pierre De Rop3e100372010-05-24 12:43:44 +0000582 * be overridden by the manifest Bundle-Localization header (see core specification, in section Localization
583 * on page 68). You can specify a specific localization basename file using this parameter
584 * (e.g. <code>"person"</code> will match person_du_NL.properties in the root bundle directory).
Pierre De Rop9a8ebfd2010-04-25 22:25:34 +0000585 * @param propertiesMetaData Array of MetaData regarding configuration properties
586 * @return a service that acts as a factory for generating the managed service factory configuration adapter
587 */
Marcel Offermanscba269a2013-01-18 11:00:56 +0000588 public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate, String heading, String desc, String localization, PropertyMetaData[] propertiesMetaData) {
589 return new FactoryConfigurationAdapterServiceImpl(this, factoryPid, update, propagate, m_context, m_logger, heading, desc, localization, propertiesMetaData);
Pierre De Rop9a8ebfd2010-04-25 22:25:34 +0000590 }
591
592 /**
Marcel Offermansa962bc92009-11-21 17:59:33 +0000593 * Returns a list of services.
594 *
595 * @return a list of services
596 */
Marcel Offermans5be5f142011-04-26 10:47:12 +0000597 public List getComponents() {
598 return Collections.unmodifiableList(m_components);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000599 }
Marcel Offermans07095832011-11-16 06:28:10 +0000600
601 /**
602 * Removes all components and their dependencies.
603 */
604 public void clear() {
Marcel Offermans8222d982013-01-15 10:11:39 +0000605 Component[] components;
606 synchronized (m_components) {
607 components = (Component[]) m_components.toArray(new Component[m_components.size()]);
608 }
609 for (int i = components.length - 1; i >= 0; i--) {
610 Component component = (Component) components[i];
611 remove(component);
Marcel Offermans07095832011-11-16 06:28:10 +0000612 // remove any state listeners that are still registered
Marcel Offermans8222d982013-01-15 10:11:39 +0000613 if (component instanceof ComponentImpl) {
614 ComponentImpl si = (ComponentImpl) component;
Marcel Offermans07095832011-11-16 06:28:10 +0000615 si.removeStateListeners();
616 }
617 }
618 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000619}