blob: 65b97b798f01347384ce764374d97057b3804ffc [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;
Marcel Offermans80eeafe2009-12-01 22:12:26 +000023import java.util.Dictionary;
Marcel Offermansa962bc92009-11-21 17:59:33 +000024import java.util.List;
25
Pierre De Ropae4a5db2009-12-04 22:08:05 +000026import org.apache.felix.dm.dependencies.BundleDependency;
27import org.apache.felix.dm.dependencies.ConfigurationDependency;
28import org.apache.felix.dm.dependencies.ResourceDependency;
29import org.apache.felix.dm.dependencies.ServiceDependency;
30import org.apache.felix.dm.dependencies.TemporalServiceDependency;
Marcel Offermans001db052009-12-08 08:58:40 +000031import org.apache.felix.dm.impl.AdapterImpl;
Pierre De Ropae4a5db2009-12-04 22:08:05 +000032import org.apache.felix.dm.impl.AspectImpl;
Marcel Offermans001db052009-12-08 08:58:40 +000033import org.apache.felix.dm.impl.BundleAdapterImpl;
Pierre De Ropae4a5db2009-12-04 22:08:05 +000034import org.apache.felix.dm.impl.Logger;
Marcel Offermans001db052009-12-08 08:58:40 +000035import org.apache.felix.dm.impl.ResourceAdapterImpl;
Pierre De Ropae4a5db2009-12-04 22:08:05 +000036import org.apache.felix.dm.impl.ServiceImpl;
37import org.apache.felix.dm.impl.dependencies.BundleDependencyImpl;
38import org.apache.felix.dm.impl.dependencies.ConfigurationDependencyImpl;
39import org.apache.felix.dm.impl.dependencies.ResourceDependencyImpl;
40import org.apache.felix.dm.impl.dependencies.ServiceDependencyImpl;
41import org.apache.felix.dm.impl.dependencies.TemporalServiceDependencyImpl;
Marcel Offermans4fd903f2009-12-29 09:18:05 +000042import org.apache.felix.dm.resources.Resource;
Pierre De Ropae4a5db2009-12-04 22:08:05 +000043import org.apache.felix.dm.service.Service;
Marcel Offermansb8405a52009-12-22 19:01:31 +000044import org.osgi.framework.BundleContext;
Marcel Offermansa962bc92009-11-21 17:59:33 +000045
46/**
Marcel Offermans4fd903f2009-12-29 09:18:05 +000047 * The dependency manager manages all services and their dependencies. Using
48 * this API you can declare all services and their dependencies. Under normal
49 * circumstances, you get passed an instance of this class through the
50 * <code>DependencyActivatorBase</code> subclass you use as your
51 * <code>BundleActivator</code>, but it is also possible to create your
52 * own instance.
Marcel Offermansa962bc92009-11-21 17:59:33 +000053 *
54 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
55 */
56public class DependencyManager {
Marcel Offermansad760672010-03-03 15:30:01 +000057 public static final String ASPECT = "org.apache.felix.dependencymanager.aspect";
Marcel Offermansa962bc92009-11-21 17:59:33 +000058 private final BundleContext m_context;
59 private final Logger m_logger;
60 private List m_services = Collections.synchronizedList(new ArrayList());
61
62 /**
Marcel Offermans4fd903f2009-12-29 09:18:05 +000063 * Creates a new dependency manager. You need to supply the
64 * <code>BundleContext</code> to be used by the dependency
65 * manager to register services and communicate with the
66 * framework.
Marcel Offermansa962bc92009-11-21 17:59:33 +000067 *
68 * @param context the bundle context
Marcel Offermansa962bc92009-11-21 17:59:33 +000069 */
Pierre De Ropae4a5db2009-12-04 22:08:05 +000070 public DependencyManager(BundleContext context) {
71 this(context, new Logger(context));
72 }
73
Marcel Offermans4fd903f2009-12-29 09:18:05 +000074 DependencyManager(BundleContext context, Logger logger) {
Marcel Offermansa962bc92009-11-21 17:59:33 +000075 m_context = context;
76 m_logger = logger;
77 }
Pierre De Ropae4a5db2009-12-04 22:08:05 +000078
Marcel Offermansa962bc92009-11-21 17:59:33 +000079 /**
80 * Adds a new service to the dependency manager. After the service was added
81 * it will be started immediately.
82 *
83 * @param service the service to add
84 */
85 public void add(Service service) {
86 m_services.add(service);
87 service.start();
88 }
89
90 /**
91 * Removes a service from the dependency manager. Before the service is removed
92 * it is stopped first.
93 *
94 * @param service the service to remove
95 */
96 public void remove(Service service) {
97 service.stop();
98 m_services.remove(service);
99 }
100
101 /**
102 * Creates a new service.
103 *
104 * @return the new service
105 */
106 public Service createService() {
107 return new ServiceImpl(m_context, this, m_logger);
108 }
109
110 /**
111 * Creates a new service dependency.
112 *
113 * @return the service dependency
114 */
115 public ServiceDependency createServiceDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000116 return new ServiceDependencyImpl(m_context, m_logger);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000117 }
118
Marcel Offermans74363c32009-11-23 19:56:08 +0000119 /**
120 * Creates a new temporal service dependency.
121 *
122 * @param timeout the max number of milliseconds to wait for a service availability.
123 * @return the service dependency
124 */
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 /**
139 * Creates a new bundle dependency.
140 *
141 * @return
142 */
Marcel Offermansd66c5ce2009-11-26 09:58:44 +0000143 public BundleDependency createBundleDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000144 return new BundleDependencyImpl(m_context, m_logger);
Marcel Offermansd66c5ce2009-11-26 09:58:44 +0000145 }
Marcel Offermans2925f172009-12-02 13:03:39 +0000146
147 /**
148 * Creates a new resource dependency.
149 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000150 * @return the resource dependency
Marcel Offermans2925f172009-12-02 13:03:39 +0000151 */
152 public ResourceDependency createResourceDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000153 return new ResourceDependencyImpl(m_context, m_logger);
Marcel Offermans2925f172009-12-02 13:03:39 +0000154 }
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000155
Marcel Offermans2925f172009-12-02 13:03:39 +0000156 /**
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000157 * Creates a new aspect. The aspect will be applied to any service that
158 * matches the specified interface and filter. For each matching service
159 * an aspect will be created based on the aspect implementation class.
160 * The aspect will be registered with the same interface and properties
161 * as the original service, plus any extra properties you supply here.
162 * It will also inherit all dependencies, and if you declare the original
163 * service as a member it will be injected.
Marcel Offermans2925f172009-12-02 13:03:39 +0000164 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000165 * @param serviceInterface the service interface to apply the aspect to
166 * @param serviceFilter the filter condition to use with the service interface
167 * @param aspectImplementation the implementation of the aspect
168 * @param aspectProperties additional properties to use with the aspect service registration
169 * @return a service that acts as a factory for generating aspects
Marcel Offermans2925f172009-12-02 13:03:39 +0000170 */
Marcel Offermansad760672010-03-03 15:30:01 +0000171 public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, Object aspectImplementation, Dictionary aspectProperties) {
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000172 return createService()
Marcel Offermansad760672010-03-03 15:30:01 +0000173 .setImplementation(new AspectImpl(serviceInterface, serviceFilter, ranking, aspectImplementation, aspectProperties))
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000174 .add(createServiceDependency()
Marcel Offermansad760672010-03-03 15:30:01 +0000175 .setService(serviceInterface, createAspectFilter(serviceFilter))
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000176 .setAutoConfig(false)
177 .setCallbacks("added", "removed")
178 );
179 }
Marcel Offermansad760672010-03-03 15:30:01 +0000180 public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, Object factory, String factoryCreateMethod, Dictionary aspectProperties) {
181 return createService()
182 .setImplementation(new AspectImpl(serviceInterface, serviceFilter, ranking, factory, factoryCreateMethod, aspectProperties))
183 .add(createServiceDependency()
184 .setService(serviceInterface, createAspectFilter(serviceFilter))
185 .setAutoConfig(false)
186 .setCallbacks("added", "removed")
187 );
188 }
189 private String createAspectFilter(String filter) {
190 // we only want to match services which are not themselves aspects
191 if (filter == null || filter.length() == 0) {
192 return "(!(" + ASPECT + "=*))";
193 }
194 else {
195 return "(&(!(" + ASPECT + "=*))" + filter + ")";
196 }
197 }
Marcel Offermans001db052009-12-08 08:58:40 +0000198
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000199 /**
200 * Creates a new adapter. The adapter will be applied to any service that
201 * matches the specified interface and filter. For each matching service
202 * an adapter will be created based on the adapter implementation class.
203 * The adapter will be registered with the specified interface and existing properties
204 * from the original service plus any extra properties you supply here.
205 * It will also inherit all dependencies, and if you declare the original
206 * service as a member it will be injected.
207 *
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000208 * @param serviceInterface the service interface to apply the adapter to
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000209 * @param serviceFilter the filter condition to use with the service interface
210 * @param adapterInterface the interface to use when registering adapters
211 * @param adapterImplementation the implementation of the adapter
212 * @param adapterProperties additional properties to use with the adapter service registration
213 * @return a service that acts as a factory for generating adapters
214 */
215 public Service createAdapterService(Class serviceInterface, String serviceFilter, Class adapterInterface, Object adapterImplementation, Dictionary adapterProperties) {
Marcel Offermans001db052009-12-08 08:58:40 +0000216 return createService()
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000217 .setImplementation(new AdapterImpl(serviceInterface, serviceFilter, adapterImplementation, adapterInterface.getName(), adapterProperties))
Marcel Offermans001db052009-12-08 08:58:40 +0000218 .add(createServiceDependency()
Marcel Offermans3e1998c2009-12-16 20:47:25 +0000219 .setService(serviceInterface)
Marcel Offermans001db052009-12-08 08:58:40 +0000220 .setAutoConfig(false)
221 .setCallbacks("added", "removed")
Marcel Offermans626260c2009-12-22 17:06:46 +0000222 );
Marcel Offermans001db052009-12-08 08:58:40 +0000223 }
224
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000225 /**
226 * Creates a new resource adapter. The adapter will be applied to any resource that
227 * matches the specified filter condition. For each matching resource
228 * an adapter will be created based on the adapter implementation class.
229 * The adapter will be registered with the specified interface and existing properties
230 * from the original resource plus any extra properties you supply here.
231 * It will also inherit all dependencies, and if you declare the original
232 * service as a member it will be injected.
233 *
234 * @param resourceFilter the filter condition to use with the resource
235 * @param adapterInterface the interface to use when registering adapters
236 * @param adapterProperties additional properties to use with the adapter service registration
237 * @param adapterImplementation the implementation of the adapter
238 * @param propagate <code>true</code> if properties from the resource should be propagated to the service
239 * @return a service that acts as a factory for generating resource adapters
240 * @see Resource
241 */
242 public Service createResourceAdapterService(String resourceFilter, Class adapterInterface, Dictionary adapterProperties, Object adapterImplementation, boolean propagate) {
Marcel Offermans001db052009-12-08 08:58:40 +0000243 return createService()
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000244 .setImplementation(new ResourceAdapterImpl(resourceFilter, adapterImplementation, adapterInterface.getName(), adapterProperties, propagate))
Marcel Offermans001db052009-12-08 08:58:40 +0000245 .add(createResourceDependency()
246 .setFilter(resourceFilter)
247 .setAutoConfig(false)
248 .setCallbacks("added", "removed")
Marcel Offermans626260c2009-12-22 17:06:46 +0000249 );
Marcel Offermans001db052009-12-08 08:58:40 +0000250 }
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000251
252 /**
253 * Creates a new bundle adapter. The adapter will be applied to any bundle that
254 * matches the specified bundle state mask and filter condition. For each matching
255 * bundle an adapter will be created based on the adapter implementation class.
256 * The adapter will be registered with the specified interface
257 *
258 * TODO and existing properties from the original resource plus any extra properties you supply here.
259 * It will also inherit all dependencies, and if you declare the original
260 * service as a member it will be injected.
261 *
262 * @param bundleStateMask the bundle state mask to apply
263 * @param bundleFilter the filter to apply to the bundle manifest
264 * @param adapterImplementation the implementation of the adapter
265 * @param adapterInterface the interface to use when registering adapters
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000266 * @param adapterProperties additional properties to use with the service registration
267 * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000268 * @return a service that acts as a factory for generating bundle adapters
269 */
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000270 public Service createBundleAdapterService(int bundleStateMask, String bundleFilter, Object adapterImplementation, String adapterInterface, Dictionary adapterProperties, boolean propagate) {
Marcel Offermans001db052009-12-08 08:58:40 +0000271 return createService()
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000272 .setImplementation(new BundleAdapterImpl(bundleStateMask, bundleFilter, adapterImplementation, adapterInterface, adapterProperties, propagate))
Marcel Offermans001db052009-12-08 08:58:40 +0000273 .add(createBundleDependency()
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000274 .setFilter(bundleFilter)
275 .setStateMask(bundleStateMask)
Marcel Offermans001db052009-12-08 08:58:40 +0000276 .setCallbacks("added", "removed")
Marcel Offermans626260c2009-12-22 17:06:46 +0000277 );
Marcel Offermans001db052009-12-08 08:58:40 +0000278 }
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000279
Marcel Offermansa962bc92009-11-21 17:59:33 +0000280 /**
281 * Returns a list of services.
282 *
283 * @return a list of services
284 */
285 public List getServices() {
286 return Collections.unmodifiableList(m_services);
287 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000288}