blob: 7a148fe4a8c84e93ecbc04d378fd4e05f5fd072a [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;
42import org.apache.felix.dm.impl.index.MultiPropertyExactFilter;
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +000043import org.apache.felix.dm.impl.index.AdapterFilterIndex;
Marcel Offermans90ba4fa2011-04-27 07:57:44 +000044import org.apache.felix.dm.impl.index.ServiceRegistryCache;
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 {
113 String[] propList = props[i].split(",");
114 m_serviceRegistryCache.addFilterIndex(new MultiPropertyExactFilter(propList));
115 }
Marcel Offermansfd7deb02011-04-20 11:26:09 +0000116 }
Marcel Offermans227dd712011-04-19 07:14:22 +0000117 }
Marcel Offermansa7dadd52011-06-22 12:10:01 +0000118 catch (BundleException e) {
119 // if we cannot start ourselves, we cannot use the indices
120 // TODO we might want to warn people about this
121 }
Marcel Offermans227dd712011-04-19 07:14:22 +0000122 }
Marcel Offermans5be5f142011-04-26 10:47:12 +0000123 }
124
125 public static List getDependencyManagers() {
126 List /* DependencyManager */ result = new ArrayList();
127 synchronized (m_dependencyManagers) {
128 Iterator iterator = m_dependencyManagers.iterator();
129 while (iterator.hasNext()) {
130 WeakReference reference = (WeakReference) iterator.next();
131 DependencyManager manager = (DependencyManager) reference.get();
132 if (manager != null) {
Marcel Offermansc7fbf782011-05-18 14:34:33 +0000133 try {
134 manager.getBundleContext().getBundle();
135 result.add(manager);
136 continue;
137 }
138 catch (IllegalStateException e) {
139 }
Marcel Offermans5be5f142011-04-26 10:47:12 +0000140 }
Marcel Offermansc7fbf782011-05-18 14:34:33 +0000141 iterator.remove();
Marcel Offermans5be5f142011-04-26 10:47:12 +0000142 }
Marcel Offermans227dd712011-04-19 07:14:22 +0000143 }
Marcel Offermans5be5f142011-04-26 10:47:12 +0000144 return result;
Marcel Offermans227dd712011-04-19 07:14:22 +0000145 }
146
147 private BundleContext createContext(BundleContext context) {
148 if (m_serviceRegistryCache != null) {
149// System.out.println("DM: Enabling bundle context interceptor for bundle #" + context.getBundle().getBundleId());
150 return m_serviceRegistryCache.createBundleContextInterceptor(context);
151 }
152 else {
153 return context;
154 }
155 }
Marcel Offermans5be5f142011-04-26 10:47:12 +0000156
157 public BundleContext getBundleContext() {
158 return m_context;
159 }
Marcel Offermans227dd712011-04-19 07:14:22 +0000160
Marcel Offermansa962bc92009-11-21 17:59:33 +0000161 /**
162 * Adds a new service to the dependency manager. After the service was added
163 * it will be started immediately.
164 *
165 * @param service the service to add
166 */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000167 public void add(Component service) {
Marcel Offermans5be5f142011-04-26 10:47:12 +0000168 m_components.add(service);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000169 service.start();
170 }
171
172 /**
173 * Removes a service from the dependency manager. Before the service is removed
174 * it is stopped first.
175 *
176 * @param service the service to remove
177 */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000178 public void remove(Component service) {
Marcel Offermansa962bc92009-11-21 17:59:33 +0000179 service.stop();
Marcel Offermans5be5f142011-04-26 10:47:12 +0000180 m_components.remove(service);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000181 }
182
183 /**
184 * Creates a new service.
185 *
186 * @return the new service
187 */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000188 public Component createComponent() {
189 return new ComponentImpl(m_context, this, m_logger);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000190 }
191
192 /**
193 * Creates a new service dependency.
194 *
195 * @return the service dependency
196 */
197 public ServiceDependency createServiceDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000198 return new ServiceDependencyImpl(m_context, m_logger);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000199 }
200
Marcel Offermans74363c32009-11-23 19:56:08 +0000201 /**
202 * Creates a new temporal service dependency.
203 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000204 * @return a new temporal service dependency
Marcel Offermans74363c32009-11-23 19:56:08 +0000205 */
206 public TemporalServiceDependency createTemporalServiceDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000207 return new TemporalServiceDependencyImpl(m_context, m_logger);
Marcel Offermans74363c32009-11-23 19:56:08 +0000208 }
Marcel Offermans2925f172009-12-02 13:03:39 +0000209
210 /**
211 * Creates a new configuration dependency.
212 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000213 * @return the configuration dependency
Marcel Offermans2925f172009-12-02 13:03:39 +0000214 */
Marcel Offermansa962bc92009-11-21 17:59:33 +0000215 public ConfigurationDependency createConfigurationDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000216 return new ConfigurationDependencyImpl(m_context, m_logger);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000217 }
218
Marcel Offermans2925f172009-12-02 13:03:39 +0000219 /**
Marcel Offermansfaaed472010-09-08 10:07:32 +0000220 * Creates a new configuration property metadata.
221 *
222 * @return the configuration property metadata.
Pierre De Ropa0204f52010-03-06 22:23:57 +0000223 */
224 public PropertyMetaData createPropertyMetaData() {
225 return new PropertyMetaDataImpl();
226 }
227
228 /**
Marcel Offermans2925f172009-12-02 13:03:39 +0000229 * Creates a new bundle dependency.
230 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000231 * @return a new BundleDependency instance.
Marcel Offermans2925f172009-12-02 13:03:39 +0000232 */
Marcel Offermansd66c5ce2009-11-26 09:58:44 +0000233 public BundleDependency createBundleDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000234 return new BundleDependencyImpl(m_context, m_logger);
Marcel Offermansd66c5ce2009-11-26 09:58:44 +0000235 }
Marcel Offermans2925f172009-12-02 13:03:39 +0000236
237 /**
238 * Creates a new resource dependency.
239 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000240 * @return the resource dependency
Marcel Offermans2925f172009-12-02 13:03:39 +0000241 */
242 public ResourceDependency createResourceDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000243 return new ResourceDependencyImpl(m_context, m_logger);
Marcel Offermans2925f172009-12-02 13:03:39 +0000244 }
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000245
Marcel Offermans2925f172009-12-02 13:03:39 +0000246 /**
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000247 * Creates a new aspect. The aspect will be applied to any service that
248 * matches the specified interface and filter. For each matching service
249 * an aspect will be created based on the aspect implementation class.
250 * The aspect will be registered with the same interface and properties
251 * as the original service, plus any extra properties you supply here.
252 * It will also inherit all dependencies, and if you declare the original
253 * service as a member it will be injected.
Marcel Offermans2925f172009-12-02 13:03:39 +0000254 *
Pierre De Rop19476fe2010-05-23 08:13:58 +0000255 * <h3>Usage Example</h3>
256 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000257 * <blockquote><pre>
Marcel Offermansa8818d52011-03-09 10:03:35 +0000258 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "m_service")
259 * .setImplementation(ExistingServiceAspect.class)
260 * );
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000261 * </pre></blockquote>
Pierre De Rop19476fe2010-05-23 08:13:58 +0000262 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000263 * @param serviceInterface the service interface to apply the aspect to
264 * @param serviceFilter the filter condition to use with the service interface
Pierre De Rop19476fe2010-05-23 08:13:58 +0000265 * @param ranking the level used to organize the aspect chain ordering
Marcel Offermansa8818d52011-03-09 10:03:35 +0000266 * @param autoConfig the aspect implementation field name where to inject original service.
Marcel Offermansfaaed472010-09-08 10:07:32 +0000267 * If null, any field matching the original service will be injected.
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000268 * @return a service that acts as a factory for generating aspects
Marcel Offermans2925f172009-12-02 13:03:39 +0000269 */
Marcel Offermansa8818d52011-03-09 10:03:35 +0000270 public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String autoConfig) {
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +0000271 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, autoConfig, null, null, null, null);
Marcel Offermansa8818d52011-03-09 10:03:35 +0000272 }
273 /**
274 * Creates a new aspect. The aspect will be applied to any service that
275 * matches the specified interface and filter. For each matching service
276 * an aspect will be created based on the aspect implementation class.
277 * The aspect will be registered with the same interface and properties
278 * as the original service, plus any extra properties you supply here.
279 * It will also inherit all dependencies, and if you declare the original
280 * service as a member it will be injected.
281 *
282 * <h3>Usage Example</h3>
283 *
284 * <blockquote><pre>
285 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10)
286 * .setImplementation(ExistingServiceAspect.class)
287 * );
288 * </pre></blockquote>
289 *
290 * @param serviceInterface the service interface to apply the aspect to
291 * @param serviceFilter the filter condition to use with the service interface
292 * @param ranking the level used to organize the aspect chain ordering
293 * @return a service that acts as a factory for generating aspects
294 */
295 public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking) {
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +0000296 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, null, null, null);
Marcel Offermansa8818d52011-03-09 10:03:35 +0000297 }
298 /**
299 * Creates a new aspect. The aspect will be applied to any service that
300 * matches the specified interface and filter. For each matching service
301 * an aspect will be created based on the aspect implementation class.
302 * The aspect will be registered with the same interface and properties
303 * as the original service, plus any extra properties you supply here.
304 * It will also inherit all dependencies, and if you declare the original
305 * service as a member it will be injected.
306 *
307 * <h3>Usage Example</h3>
308 *
309 * <blockquote><pre>
310 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
311 * .setImplementation(ExistingServiceAspect.class)
312 * );
313 * </pre></blockquote>
314 *
315 * @param serviceInterface the service interface to apply the aspect to
316 * @param serviceFilter the filter condition to use with the service interface
317 * @param ranking the level used to organize the aspect chain ordering
318 * @param add name of the callback method to invoke on add
319 * @param change name of the callback method to invoke on change
320 * @param remove name of the callback method to invoke on remove
321 * @return a service that acts as a factory for generating aspects
322 */
323 public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String add, String change, String remove) {
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +0000324 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, add, change, remove, null);
325 }
326
327 /**
328 * Creates a new aspect. The aspect will be applied to any service that
329 * matches the specified interface and filter. For each matching service
330 * an aspect will be created based on the aspect implementation class.
331 * The aspect will be registered with the same interface and properties
332 * as the original service, plus any extra properties you supply here.
333 * It will also inherit all dependencies, and if you declare the original
334 * service as a member it will be injected.
335 *
336 * <h3>Usage Example</h3>
337 *
338 * <blockquote><pre>
339 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
340 * .setImplementation(ExistingServiceAspect.class)
341 * );
342 * </pre></blockquote>
343 *
344 * @param serviceInterface the service interface to apply the aspect to
345 * @param serviceFilter the filter condition to use with the service interface
346 * @param ranking the level used to organize the aspect chain ordering
347 * @param add name of the callback method to invoke on add
348 * @param change name of the callback method to invoke on change
349 * @param remove name of the callback method to invoke on remove
350 * @param swap name of the callback method to invoke on swap
351 * @return a service that acts as a factory for generating aspects
352 */
353 public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String add, String change, String remove, String swap) {
354 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, add, change, remove, swap);
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000355 }
Marcel Offermanse9c13d92010-07-01 14:01:02 +0000356
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000357 /**
358 * Creates a new adapter. The adapter will be applied to any service that
359 * matches the specified interface and filter. For each matching service
360 * an adapter will be created based on the adapter implementation class.
361 * The adapter will be registered with the specified interface and existing properties
362 * from the original service plus any extra properties you supply here.
363 * It will also inherit all dependencies, and if you declare the original
364 * service as a member it will be injected.
365 *
Pierre De Rop34231582010-05-23 20:05:16 +0000366 * <h3>Usage Example</h3>
367 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000368 * <blockquote><pre>
Marcel Offermansa8818d52011-03-09 10:03:35 +0000369 * manager.createAdapterService(AdapteeService.class, "(foo=bar)")
370 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
371 * .setImplementation(AdapterImpl.class);
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000372 * </pre></blockquote>
Marcel Offermansa8818d52011-03-09 10:03:35 +0000373 *
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000374 * @param serviceInterface the service interface to apply the adapter to
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000375 * @param serviceFilter the filter condition to use with the service interface
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000376 * @return a service that acts as a factory for generating adapters
377 */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000378 public Component createAdapterService(Class serviceInterface, String serviceFilter) {
Marcel Offermansa8818d52011-03-09 10:03:35 +0000379 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, null, null);
380 }
381 /**
382 * Creates a new adapter. The adapter will be applied to any service that
383 * matches the specified interface and filter. For each matching service
384 * an adapter will be created based on the adapter implementation class.
385 * The adapter will be registered with the specified interface and existing properties
386 * from the original service plus any extra properties you supply here.
387 * It will also inherit all dependencies, and if you declare the original
388 * service as a member it will be injected.
389 *
390 * <h3>Usage Example</h3>
391 *
392 * <blockquote><pre>
393 * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "m_service")
394 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
395 * .setImplementation(AdapterImpl.class);
396 * </pre></blockquote>
397 *
398 * @param serviceInterface the service interface to apply the adapter to
399 * @param serviceFilter the filter condition to use with the service interface
400 * @param autoConfig the name of the member to inject the service into
401 * @return a service that acts as a factory for generating adapters
402 */
403 public Component createAdapterService(Class serviceInterface, String serviceFilter, String autoConfig) {
404 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, autoConfig, null, null, null);
405 }
406 /**
407 * Creates a new adapter. The adapter will be applied to any service that
408 * matches the specified interface and filter. For each matching service
409 * an adapter will be created based on the adapter implementation class.
410 * The adapter will be registered with the specified interface and existing properties
411 * from the original service plus any extra properties you supply here.
412 * It will also inherit all dependencies, and if you declare the original
413 * service as a member it will be injected.
414 *
415 * <h3>Usage Example</h3>
416 *
417 * <blockquote><pre>
418 * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove")
419 * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
420 * .setImplementation(AdapterImpl.class);
421 * </pre></blockquote>
422 *
423 * @param serviceInterface the service interface to apply the adapter to
424 * @param serviceFilter the filter condition to use with the service interface
425 * @param add name of the callback method to invoke on add
426 * @param change name of the callback method to invoke on change
427 * @param remove name of the callback method to invoke on remove
Marcel Offermans4aa032c2012-01-02 19:18:22 +0000428 * @param swap name of the callback method to invoke on swap
Marcel Offermansa8818d52011-03-09 10:03:35 +0000429 * @return a service that acts as a factory for generating adapters
430 */
Marcel Offermans4aa032c2012-01-02 19:18:22 +0000431 public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove, String swap) {
432 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove, swap);
433 }
434
Marcel Offermanscba269a2013-01-18 11:00:56 +0000435 /** @see DependencyManager#createAdapterService(Class, String, String, String, String, String) */
Marcel Offermansa8818d52011-03-09 10:03:35 +0000436 public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove) {
437 return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove);
Marcel Offermans61a81142010-04-02 15:16:50 +0000438 }
Pierre De Rop34231582010-05-23 20:05:16 +0000439
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000440 /**
441 * Creates a new resource adapter. The adapter will be applied to any resource that
442 * matches the specified filter condition. For each matching resource
443 * an adapter will be created based on the adapter implementation class.
444 * The adapter will be registered with the specified interface and existing properties
445 * from the original resource plus any extra properties you supply here.
446 * It will also inherit all dependencies, and if you declare the original
447 * service as a member it will be injected.
448 *
Pierre De Rop445ddec2010-05-23 21:05:27 +0000449 * <h3>Usage Example</h3>
450 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000451 * <blockquote><pre>
Pierre De Rop445ddec2010-05-23 21:05:27 +0000452 * manager.createResourceAdapterService("(&(path=/test)(repository=TestRepository))", true)
453 * // The interface to use when registering adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000454 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
Pierre De Rop445ddec2010-05-23 21:05:27 +0000455 * // the implementation of the adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000456 * .setImplementation(AdapterServiceImpl.class);
457 * </pre></blockquote>
Pierre De Rop445ddec2010-05-23 21:05:27 +0000458 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000459 * @param resourceFilter the filter condition to use with the resource
Marcel Offermansd26f2bd2012-01-02 14:53:17 +0000460 * @param resourcePropertiesFilter the filter condition on the resource properties to use with the resource
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000461 * @param propagate <code>true</code> if properties from the resource should be propagated to the service
Marcel Offermanscba269a2013-01-18 11:00:56 +0000462 * @param callbackInstance instance to invoke the callback on
463 * @param callbackChanged the name of the callback method
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000464 * @return a service that acts as a factory for generating resource adapters
465 * @see Resource
466 */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000467 public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance, String callbackChanged) {
Marcel Offermansd26f2bd2012-01-02 14:53:17 +0000468 return new ResourceAdapterServiceImpl(this, resourceFilter, propagate, callbackInstance, null, callbackChanged);
469 }
470
Marcel Offermanscba269a2013-01-18 11:00:56 +0000471 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
Marcel Offermansd26f2bd2012-01-02 14:53:17 +0000472 public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance, String callbackSet, String callbackChanged) {
473 return new ResourceAdapterServiceImpl(this, resourceFilter, propagate, callbackInstance, callbackSet, callbackChanged);
Marcel Offermans61a81142010-04-02 15:16:50 +0000474 }
Pierre De Rop445ddec2010-05-23 21:05:27 +0000475
Marcel Offermanscba269a2013-01-18 11:00:56 +0000476 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000477 public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackChanged) {
Marcel Offermansd26f2bd2012-01-02 14:53:17 +0000478 return new ResourceAdapterServiceImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, null, callbackChanged);
479 }
480
Marcel Offermanscba269a2013-01-18 11:00:56 +0000481 /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
Marcel Offermansd26f2bd2012-01-02 14:53:17 +0000482 public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackSet, String callbackChanged) {
483 return new ResourceAdapterServiceImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, callbackSet, callbackChanged);
Marcel Offermans26081d32010-07-12 12:43:42 +0000484 }
485
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000486 /**
487 * Creates a new bundle adapter. The adapter will be applied to any bundle that
488 * matches the specified bundle state mask and filter condition. For each matching
489 * bundle an adapter will be created based on the adapter implementation class.
490 * The adapter will be registered with the specified interface
491 *
492 * TODO and existing properties from the original resource plus any extra properties you supply here.
493 * It will also inherit all dependencies, and if you declare the original
494 * service as a member it will be injected.
495 *
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000496 * <h3>Usage Example</h3>
497 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000498 * <blockquote><pre>
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000499 * manager.createBundleAdapterService(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE,
500 * "(Bundle-SymbolicName=org.apache.felix.dependencymanager)",
501 * true)
502 * // The interface to use when registering adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000503 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000504 * // the implementation of the adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000505 * .setImplementation(AdapterServiceImpl.class);
506 * </pre></blockquote>
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000507 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000508 * @param bundleStateMask the bundle state mask to apply
509 * @param bundleFilter the filter to apply to the bundle manifest
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000510 * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000511 * @return a service that acts as a factory for generating bundle adapters
512 */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000513 public Component createBundleAdapterService(int bundleStateMask, String bundleFilter, boolean propagate) {
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000514 return new BundleAdapterServiceImpl(this, bundleStateMask, bundleFilter, propagate);
Marcel Offermans61a81142010-04-02 15:16:50 +0000515 }
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000516
Marcel Offermansa962bc92009-11-21 17:59:33 +0000517 /**
Pierre De Ropef94c882010-04-17 18:23:35 +0000518 * Creates a new Managed Service Factory Configuration Adapter. For each new Config Admin factory configuration matching
519 * the factoryPid, an adapter will be created based on the adapter implementation class.
520 * The adapter will be registered with the specified interface, and with the specified adapter service properties.
521 * Depending on the <code>propagate</code> parameter, every public factory configuration properties
522 * (which don't start with ".") will be propagated along with the adapter service properties.
523 * It will also inherit all dependencies.
524 *
Pierre De Rop3e100372010-05-24 12:43:44 +0000525 * <h3>Usage Example</h3>
526 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000527 * <blockquote><pre>
Pierre De Rop3e100372010-05-24 12:43:44 +0000528 * manager.createFactoryConfigurationAdapterService("MyFactoryPid", "update", true)
529 * // The interface to use when registering adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000530 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
Pierre De Rop3e100372010-05-24 12:43:44 +0000531 * // the implementation of the adapter
532 * .setImplementation(AdapterServiceImpl.class);
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000533 * </pre></blockquote>
534 *
Pierre De Ropef94c882010-04-17 18:23:35 +0000535 * @param factoryPid the pid matching the factory configuration
536 * @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 +0000537 * @param propagate true if public factory configuration should be propagated to the adapter service properties
538 * @return a service that acts as a factory for generating the managed service factory configuration adapter
539 */
Marcel Offermansfaaed472010-09-08 10:07:32 +0000540 public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate) {
Pierre De Rop3e100372010-05-24 12:43:44 +0000541 return new FactoryConfigurationAdapterServiceImpl(this, factoryPid, update, propagate);
Pierre De Ropef94c882010-04-17 18:23:35 +0000542 }
543
544 /**
Pierre De Rop3e100372010-05-24 12:43:44 +0000545 * Creates a new Managed Service Factory Configuration Adapter with meta type support. For each new Config Admin
546 * factory configuration matching the factoryPid, an adapter will be created based on the adapter implementation
547 * class. The adapter will be registered with the specified interface, and with the specified adapter service
548 * properties. Depending on the <code>propagate</code> parameter, every public factory configuration properties
Pierre De Ropef94c882010-04-17 18:23:35 +0000549 * (which don't start with ".") will be propagated along with the adapter service properties.
550 * It will also inherit all dependencies.
551 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000552 * <h3>Usage Example</h3>
553 *
554 * <blockquote><pre>
555 * PropertyMetaData[] propertiesMetaData = new PropertyMetaData[] {
556 * manager.createPropertyMetaData()
557 * .setCardinality(Integer.MAX_VALUE)
558 * .setType(String.class)
559 * .setHeading("English words")
560 * .setDescription("Declare here some valid english words")
561 * .setDefaults(new String[] {"hello", "world"})
562 * .setId("words")
563 * };
564 *
565 * manager.add(createFactoryConfigurationAdapterService("FactoryPid",
566 * "updated",
567 * true, // propagate CM settings
568 * "EnglishDictionary",
569 * "English dictionary configuration properties",
570 * null,
571 * propertiesMetaData)
572 * .setImplementation(Adapter.class));
573 * </pre></blockquote>
574 *
Pierre De Ropef94c882010-04-17 18:23:35 +0000575 * @param factoryPid the pid matching the factory configuration
576 * @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 +0000577 * @param propagate true if public factory configuration should be propagated to the adapter service properties
Pierre De Rop3e100372010-05-24 12:43:44 +0000578 * @param heading The label used to display the tab name (or section) where the properties are displayed.
579 * Example: "Printer Service"
580 * @param desc A human readable description of the factory PID this configuration is associated with.
581 * Example: "Configuration for the PrinterService bundle"
Pierre De Rop9a8ebfd2010-04-25 22:25:34 +0000582 * @param localization Points to the basename of the Properties file that can localize the Meta Type informations.
583 * The default localization base name for the properties is OSGI-INF/l10n/bundle, but can
Pierre De Rop3e100372010-05-24 12:43:44 +0000584 * be overridden by the manifest Bundle-Localization header (see core specification, in section Localization
585 * on page 68). You can specify a specific localization basename file using this parameter
586 * (e.g. <code>"person"</code> will match person_du_NL.properties in the root bundle directory).
Pierre De Rop9a8ebfd2010-04-25 22:25:34 +0000587 * @param propertiesMetaData Array of MetaData regarding configuration properties
588 * @return a service that acts as a factory for generating the managed service factory configuration adapter
589 */
Marcel Offermanscba269a2013-01-18 11:00:56 +0000590 public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate, String heading, String desc, String localization, PropertyMetaData[] propertiesMetaData) {
591 return new FactoryConfigurationAdapterServiceImpl(this, factoryPid, update, propagate, m_context, m_logger, heading, desc, localization, propertiesMetaData);
Pierre De Rop9a8ebfd2010-04-25 22:25:34 +0000592 }
593
594 /**
Marcel Offermansa962bc92009-11-21 17:59:33 +0000595 * Returns a list of services.
596 *
597 * @return a list of services
598 */
Marcel Offermans5be5f142011-04-26 10:47:12 +0000599 public List getComponents() {
600 return Collections.unmodifiableList(m_components);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000601 }
Marcel Offermans07095832011-11-16 06:28:10 +0000602
603 /**
604 * Removes all components and their dependencies.
605 */
606 public void clear() {
Marcel Offermans8222d982013-01-15 10:11:39 +0000607 Component[] components;
608 synchronized (m_components) {
609 components = (Component[]) m_components.toArray(new Component[m_components.size()]);
610 }
611 for (int i = components.length - 1; i >= 0; i--) {
612 Component component = (Component) components[i];
613 remove(component);
Marcel Offermans07095832011-11-16 06:28:10 +0000614 // remove any state listeners that are still registered
Marcel Offermans8222d982013-01-15 10:11:39 +0000615 if (component instanceof ComponentImpl) {
616 ComponentImpl si = (ComponentImpl) component;
Marcel Offermans07095832011-11-16 06:28:10 +0000617 si.removeStateListeners();
618 }
619 }
620 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000621}