blob: 0a59f1bb0f2316aa8e06e23d762c7114e6441e2f [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
21import java.util.ArrayList;
22import java.util.Collections;
23import java.util.List;
24
Pierre De Ropae4a5db2009-12-04 22:08:05 +000025import org.apache.felix.dm.dependencies.BundleDependency;
26import org.apache.felix.dm.dependencies.ConfigurationDependency;
Pierre De Ropa0204f52010-03-06 22:23:57 +000027import org.apache.felix.dm.dependencies.PropertyMetaData;
Pierre De Ropae4a5db2009-12-04 22:08:05 +000028import org.apache.felix.dm.dependencies.ResourceDependency;
29import org.apache.felix.dm.dependencies.ServiceDependency;
30import org.apache.felix.dm.dependencies.TemporalServiceDependency;
Pierre De Rop34231582010-05-23 20:05:16 +000031import org.apache.felix.dm.impl.AdapterServiceImpl;
Pierre De Rop19476fe2010-05-23 08:13:58 +000032import org.apache.felix.dm.impl.AspectServiceImpl;
Pierre De Rop13dd63d2010-05-23 21:58:28 +000033import org.apache.felix.dm.impl.BundleAdapterServiceImpl;
Pierre De Rop3e100372010-05-24 12:43:44 +000034import org.apache.felix.dm.impl.FactoryConfigurationAdapterServiceImpl;
Pierre De Ropae4a5db2009-12-04 22:08:05 +000035import org.apache.felix.dm.impl.Logger;
Pierre De Rop445ddec2010-05-23 21:05:27 +000036import org.apache.felix.dm.impl.ResourceAdapterServiceImpl;
Pierre De Ropae4a5db2009-12-04 22:08:05 +000037import org.apache.felix.dm.impl.ServiceImpl;
38import org.apache.felix.dm.impl.dependencies.BundleDependencyImpl;
39import org.apache.felix.dm.impl.dependencies.ConfigurationDependencyImpl;
40import org.apache.felix.dm.impl.dependencies.ResourceDependencyImpl;
41import org.apache.felix.dm.impl.dependencies.ServiceDependencyImpl;
42import org.apache.felix.dm.impl.dependencies.TemporalServiceDependencyImpl;
Pierre De Ropa0204f52010-03-06 22:23:57 +000043import org.apache.felix.dm.impl.metatype.PropertyMetaDataImpl;
Pierre De Ropae4a5db2009-12-04 22:08:05 +000044import org.apache.felix.dm.service.Service;
Marcel Offermansb8405a52009-12-22 19:01:31 +000045import org.osgi.framework.BundleContext;
Marcel Offermansa962bc92009-11-21 17:59:33 +000046
47/**
Marcel Offermans4fd903f2009-12-29 09:18:05 +000048 * The dependency manager manages all services and their dependencies. Using
49 * this API you can declare all services and their dependencies. Under normal
50 * circumstances, you get passed an instance of this class through the
51 * <code>DependencyActivatorBase</code> subclass you use as your
52 * <code>BundleActivator</code>, but it is also possible to create your
53 * own instance.
Marcel Offermansa962bc92009-11-21 17:59:33 +000054 *
55 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
56 */
57public class DependencyManager {
Marcel Offermansad760672010-03-03 15:30:01 +000058 public static final String ASPECT = "org.apache.felix.dependencymanager.aspect";
Marcel Offermansa962bc92009-11-21 17:59:33 +000059 private final BundleContext m_context;
60 private final Logger m_logger;
61 private List m_services = Collections.synchronizedList(new ArrayList());
62
63 /**
Marcel Offermans4fd903f2009-12-29 09:18:05 +000064 * Creates a new dependency manager. You need to supply the
65 * <code>BundleContext</code> to be used by the dependency
66 * manager to register services and communicate with the
67 * framework.
Marcel Offermansa962bc92009-11-21 17:59:33 +000068 *
69 * @param context the bundle context
Marcel Offermansa962bc92009-11-21 17:59:33 +000070 */
Pierre De Ropae4a5db2009-12-04 22:08:05 +000071 public DependencyManager(BundleContext context) {
72 this(context, new Logger(context));
73 }
74
Marcel Offermans4fd903f2009-12-29 09:18:05 +000075 DependencyManager(BundleContext context, Logger logger) {
Marcel Offermansa962bc92009-11-21 17:59:33 +000076 m_context = context;
77 m_logger = logger;
78 }
Pierre De Ropae4a5db2009-12-04 22:08:05 +000079
Marcel Offermansa962bc92009-11-21 17:59:33 +000080 /**
81 * Adds a new service to the dependency manager. After the service was added
82 * it will be started immediately.
83 *
84 * @param service the service to add
85 */
86 public void add(Service service) {
87 m_services.add(service);
88 service.start();
89 }
90
91 /**
92 * Removes a service from the dependency manager. Before the service is removed
93 * it is stopped first.
94 *
95 * @param service the service to remove
96 */
97 public void remove(Service service) {
98 service.stop();
99 m_services.remove(service);
100 }
101
102 /**
103 * Creates a new service.
104 *
105 * @return the new service
106 */
107 public Service createService() {
108 return new ServiceImpl(m_context, this, m_logger);
109 }
110
111 /**
112 * Creates a new service dependency.
113 *
114 * @return the service dependency
115 */
116 public ServiceDependency createServiceDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000117 return new ServiceDependencyImpl(m_context, m_logger);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000118 }
119
Marcel Offermans74363c32009-11-23 19:56:08 +0000120 /**
121 * Creates a new temporal service dependency.
122 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000123 * @return a new temporal service dependency
Marcel Offermans74363c32009-11-23 19:56:08 +0000124 */
125 public TemporalServiceDependency createTemporalServiceDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000126 return new TemporalServiceDependencyImpl(m_context, m_logger);
Marcel Offermans74363c32009-11-23 19:56:08 +0000127 }
Marcel Offermans2925f172009-12-02 13:03:39 +0000128
129 /**
130 * Creates a new configuration dependency.
131 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000132 * @return the configuration dependency
Marcel Offermans2925f172009-12-02 13:03:39 +0000133 */
Marcel Offermansa962bc92009-11-21 17:59:33 +0000134 public ConfigurationDependency createConfigurationDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000135 return new ConfigurationDependencyImpl(m_context, m_logger);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000136 }
137
Marcel Offermans2925f172009-12-02 13:03:39 +0000138 /**
Pierre De Ropa0204f52010-03-06 22:23:57 +0000139 * Creates a new configuration property MetaData.
140 * @return a new Configuration property MetaData.
141 */
142 public PropertyMetaData createPropertyMetaData() {
143 return new PropertyMetaDataImpl();
144 }
145
146 /**
Marcel Offermans2925f172009-12-02 13:03:39 +0000147 * Creates a new bundle dependency.
148 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000149 * @return a new BundleDependency instance.
Marcel Offermans2925f172009-12-02 13:03:39 +0000150 */
Marcel Offermansd66c5ce2009-11-26 09:58:44 +0000151 public BundleDependency createBundleDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000152 return new BundleDependencyImpl(m_context, m_logger);
Marcel Offermansd66c5ce2009-11-26 09:58:44 +0000153 }
Marcel Offermans2925f172009-12-02 13:03:39 +0000154
155 /**
156 * Creates a new resource dependency.
157 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000158 * @return the resource dependency
Marcel Offermans2925f172009-12-02 13:03:39 +0000159 */
160 public ResourceDependency createResourceDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000161 return new ResourceDependencyImpl(m_context, m_logger);
Marcel Offermans2925f172009-12-02 13:03:39 +0000162 }
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000163
Marcel Offermans2925f172009-12-02 13:03:39 +0000164 /**
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000165 * Creates a new aspect. The aspect will be applied to any service that
166 * matches the specified interface and filter. For each matching service
167 * an aspect will be created based on the aspect implementation class.
168 * The aspect will be registered with the same interface and properties
169 * as the original service, plus any extra properties you supply here.
170 * It will also inherit all dependencies, and if you declare the original
171 * service as a member it will be injected.
Marcel Offermans2925f172009-12-02 13:03:39 +0000172 *
Pierre De Rop19476fe2010-05-23 08:13:58 +0000173 * <h3>Usage Example</h3>
174 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000175 * <blockquote><pre>
Pierre De Rop19476fe2010-05-23 08:13:58 +0000176 * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "m_aspect")
177 * .setImplementation(ExistingServiceAspect.class)
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000178 * .setServiceProperties(new Hashtable() {{ put("additional", "properties"); }});
179 * </pre></blockquote>
Pierre De Rop19476fe2010-05-23 08:13:58 +0000180 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000181 * @param serviceInterface the service interface to apply the aspect to
182 * @param serviceFilter the filter condition to use with the service interface
Pierre De Rop19476fe2010-05-23 08:13:58 +0000183 * @param ranking the level used to organize the aspect chain ordering
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000184 * @param attributeName the aspect implementation field name where to inject original service.
Pierre De Rop19476fe2010-05-23 08:13:58 +0000185 * If null, any field matching the original service will be injected.
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000186 * @return a service that acts as a factory for generating aspects
Marcel Offermans2925f172009-12-02 13:03:39 +0000187 */
Pierre De Rop19476fe2010-05-23 08:13:58 +0000188 public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, String attributeName) {
189 return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, attributeName);
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000190 }
Marcel Offermanse9c13d92010-07-01 14:01:02 +0000191
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000192 /**
193 * Creates a new adapter. The adapter will be applied to any service that
194 * matches the specified interface and filter. For each matching service
195 * an adapter will be created based on the adapter implementation class.
196 * The adapter will be registered with the specified interface and existing properties
197 * from the original service plus any extra properties you supply here.
198 * It will also inherit all dependencies, and if you declare the original
199 * service as a member it will be injected.
200 *
Pierre De Rop34231582010-05-23 20:05:16 +0000201 * <h3>Usage Example</h3>
202 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000203 * <blockquote><pre>
Pierre De Rop34231582010-05-23 20:05:16 +0000204 * manager.createAdapterService(AdapteeService.class, "(foo=bar)")
Pierre De Rop445ddec2010-05-23 21:05:27 +0000205 * // The interface to use when registering adapter
Pierre De Rop34231582010-05-23 20:05:16 +0000206 * .setInterface(AdapterService.class, new Hashtable() {{ put("additional", "properties"); }})
207 * // the implementation of the adapter
208 * .setImplementation(AdapterImpl.class);
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000209 * </pre></blockquote>
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000210 * @param serviceInterface the service interface to apply the adapter to
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000211 * @param serviceFilter the filter condition to use with the service interface
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000212 * @return a service that acts as a factory for generating adapters
213 */
Pierre De Rop34231582010-05-23 20:05:16 +0000214 public Service createAdapterService(Class serviceInterface, String serviceFilter) {
215 return new AdapterServiceImpl(this, serviceInterface, serviceFilter);
Marcel Offermans61a81142010-04-02 15:16:50 +0000216 }
Pierre De Rop34231582010-05-23 20:05:16 +0000217
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000218 /**
219 * Creates a new resource adapter. The adapter will be applied to any resource that
220 * matches the specified filter condition. For each matching resource
221 * an adapter will be created based on the adapter implementation class.
222 * The adapter will be registered with the specified interface and existing properties
223 * from the original resource plus any extra properties you supply here.
224 * It will also inherit all dependencies, and if you declare the original
225 * service as a member it will be injected.
226 *
Pierre De Rop445ddec2010-05-23 21:05:27 +0000227 * <h3>Usage Example</h3>
228 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000229 * <blockquote><pre>
Pierre De Rop445ddec2010-05-23 21:05:27 +0000230 * manager.createResourceAdapterService("(&(path=/test)(repository=TestRepository))", true)
231 * // The interface to use when registering adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000232 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
Pierre De Rop445ddec2010-05-23 21:05:27 +0000233 * // the implementation of the adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000234 * .setImplementation(AdapterServiceImpl.class);
235 * </pre></blockquote>
Pierre De Rop445ddec2010-05-23 21:05:27 +0000236 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000237 * @param resourceFilter the filter condition to use with the resource
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000238 * @param propagate <code>true</code> if properties from the resource should be propagated to the service
Marcel Offermanse9c13d92010-07-01 14:01:02 +0000239 * @param callbackInstance
240 * @param callbackChanged
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000241 * @return a service that acts as a factory for generating resource adapters
242 * @see Resource
243 */
Marcel Offermanse9c13d92010-07-01 14:01:02 +0000244 public Service createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance, String callbackChanged) {
245 return new ResourceAdapterServiceImpl(this, resourceFilter, propagate, callbackInstance, callbackChanged);
Marcel Offermans61a81142010-04-02 15:16:50 +0000246 }
Pierre De Rop445ddec2010-05-23 21:05:27 +0000247
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000248 /**
249 * Creates a new bundle adapter. The adapter will be applied to any bundle that
250 * matches the specified bundle state mask and filter condition. For each matching
251 * bundle an adapter will be created based on the adapter implementation class.
252 * The adapter will be registered with the specified interface
253 *
254 * TODO and existing properties from the original resource plus any extra properties you supply here.
255 * It will also inherit all dependencies, and if you declare the original
256 * service as a member it will be injected.
257 *
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000258 * <h3>Usage Example</h3>
259 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000260 * <blockquote><pre>
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000261 * manager.createBundleAdapterService(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE,
262 * "(Bundle-SymbolicName=org.apache.felix.dependencymanager)",
263 * true)
264 * // The interface to use when registering adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000265 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000266 * // the implementation of the adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000267 * .setImplementation(AdapterServiceImpl.class);
268 * </pre></blockquote>
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000269 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000270 * @param bundleStateMask the bundle state mask to apply
271 * @param bundleFilter the filter to apply to the bundle manifest
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000272 * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000273 * @return a service that acts as a factory for generating bundle adapters
274 */
Pierre De Rop13dd63d2010-05-23 21:58:28 +0000275 public Service createBundleAdapterService(int bundleStateMask, String bundleFilter, boolean propagate) {
276 return new BundleAdapterServiceImpl(this, bundleStateMask, bundleFilter, propagate);
Marcel Offermans61a81142010-04-02 15:16:50 +0000277 }
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000278
Marcel Offermansa962bc92009-11-21 17:59:33 +0000279 /**
Pierre De Ropef94c882010-04-17 18:23:35 +0000280 * Creates a new Managed Service Factory Configuration Adapter. For each new Config Admin factory configuration matching
281 * the factoryPid, an adapter will be created based on the adapter implementation class.
282 * The adapter will be registered with the specified interface, and with the specified adapter service properties.
283 * Depending on the <code>propagate</code> parameter, every public factory configuration properties
284 * (which don't start with ".") will be propagated along with the adapter service properties.
285 * It will also inherit all dependencies.
286 *
Pierre De Rop3e100372010-05-24 12:43:44 +0000287 * <h3>Usage Example</h3>
288 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000289 * <blockquote><pre>
Pierre De Rop3e100372010-05-24 12:43:44 +0000290 * manager.createFactoryConfigurationAdapterService("MyFactoryPid", "update", true)
291 * // The interface to use when registering adapter
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000292 * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
Pierre De Rop3e100372010-05-24 12:43:44 +0000293 * // the implementation of the adapter
294 * .setImplementation(AdapterServiceImpl.class);
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000295 * </pre></blockquote>
296 *
Pierre De Ropef94c882010-04-17 18:23:35 +0000297 * @param factoryPid the pid matching the factory configuration
298 * @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 +0000299 * @param propagate true if public factory configuration should be propagated to the adapter service properties
300 * @return a service that acts as a factory for generating the managed service factory configuration adapter
301 */
Pierre De Rop3e100372010-05-24 12:43:44 +0000302 public Service createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate) {
303 return new FactoryConfigurationAdapterServiceImpl(this, factoryPid, update, propagate);
Pierre De Ropef94c882010-04-17 18:23:35 +0000304 }
305
306 /**
Pierre De Rop3e100372010-05-24 12:43:44 +0000307 * Creates a new Managed Service Factory Configuration Adapter with meta type support. For each new Config Admin
308 * factory configuration matching the factoryPid, an adapter will be created based on the adapter implementation
309 * class. The adapter will be registered with the specified interface, and with the specified adapter service
310 * properties. Depending on the <code>propagate</code> parameter, every public factory configuration properties
Pierre De Ropef94c882010-04-17 18:23:35 +0000311 * (which don't start with ".") will be propagated along with the adapter service properties.
312 * It will also inherit all dependencies.
313 *
Pierre De Ropc3dfbb72010-05-24 13:16:35 +0000314 * <h3>Usage Example</h3>
315 *
316 * <blockquote><pre>
317 * PropertyMetaData[] propertiesMetaData = new PropertyMetaData[] {
318 * manager.createPropertyMetaData()
319 * .setCardinality(Integer.MAX_VALUE)
320 * .setType(String.class)
321 * .setHeading("English words")
322 * .setDescription("Declare here some valid english words")
323 * .setDefaults(new String[] {"hello", "world"})
324 * .setId("words")
325 * };
326 *
327 * manager.add(createFactoryConfigurationAdapterService("FactoryPid",
328 * "updated",
329 * true, // propagate CM settings
330 * "EnglishDictionary",
331 * "English dictionary configuration properties",
332 * null,
333 * propertiesMetaData)
334 * .setImplementation(Adapter.class));
335 * </pre></blockquote>
336 *
Pierre De Ropef94c882010-04-17 18:23:35 +0000337 * @param factoryPid the pid matching the factory configuration
338 * @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 +0000339 * @param propagate true if public factory configuration should be propagated to the adapter service properties
Pierre De Rop3e100372010-05-24 12:43:44 +0000340 * @param heading The label used to display the tab name (or section) where the properties are displayed.
341 * Example: "Printer Service"
342 * @param desc A human readable description of the factory PID this configuration is associated with.
343 * Example: "Configuration for the PrinterService bundle"
Pierre De Rop9a8ebfd2010-04-25 22:25:34 +0000344 * @param localization Points to the basename of the Properties file that can localize the Meta Type informations.
345 * The default localization base name for the properties is OSGI-INF/l10n/bundle, but can
Pierre De Rop3e100372010-05-24 12:43:44 +0000346 * be overridden by the manifest Bundle-Localization header (see core specification, in section Localization
347 * on page 68). You can specify a specific localization basename file using this parameter
348 * (e.g. <code>"person"</code> will match person_du_NL.properties in the root bundle directory).
Pierre De Rop9a8ebfd2010-04-25 22:25:34 +0000349 * @param propertiesMetaData Array of MetaData regarding configuration properties
350 * @return a service that acts as a factory for generating the managed service factory configuration adapter
351 */
Pierre De Rop3e100372010-05-24 12:43:44 +0000352 public Service createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate,
353 String heading, String desc, String localization,
354 PropertyMetaData[] propertiesMetaData)
Pierre De Rop9a8ebfd2010-04-25 22:25:34 +0000355 {
Pierre De Rop3e100372010-05-24 12:43:44 +0000356 return new FactoryConfigurationAdapterServiceImpl(this, factoryPid, update, propagate, m_context, m_logger,
357 heading, desc, localization, propertiesMetaData);
Pierre De Rop9a8ebfd2010-04-25 22:25:34 +0000358 }
359
360 /**
Marcel Offermansa962bc92009-11-21 17:59:33 +0000361 * Returns a list of services.
362 *
363 * @return a list of services
364 */
365 public List getServices() {
366 return Collections.unmodifiableList(m_services);
367 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000368}