blob: 981c13fa75f2e503ea575a0d0f5237b39956ed36 [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;
Pierre De Ropa0204f52010-03-06 22:23:57 +000028import org.apache.felix.dm.dependencies.PropertyMetaData;
Pierre De Ropae4a5db2009-12-04 22:08:05 +000029import org.apache.felix.dm.dependencies.ResourceDependency;
30import org.apache.felix.dm.dependencies.ServiceDependency;
31import org.apache.felix.dm.dependencies.TemporalServiceDependency;
Marcel Offermans001db052009-12-08 08:58:40 +000032import org.apache.felix.dm.impl.AdapterImpl;
Pierre De Ropae4a5db2009-12-04 22:08:05 +000033import org.apache.felix.dm.impl.AspectImpl;
Marcel Offermans001db052009-12-08 08:58:40 +000034import org.apache.felix.dm.impl.BundleAdapterImpl;
Pierre De Ropae4a5db2009-12-04 22:08:05 +000035import org.apache.felix.dm.impl.Logger;
Marcel Offermans001db052009-12-08 08:58:40 +000036import org.apache.felix.dm.impl.ResourceAdapterImpl;
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;
Marcel Offermans4fd903f2009-12-29 09:18:05 +000044import org.apache.felix.dm.resources.Resource;
Pierre De Ropae4a5db2009-12-04 22:08:05 +000045import org.apache.felix.dm.service.Service;
Marcel Offermansb8405a52009-12-22 19:01:31 +000046import org.osgi.framework.BundleContext;
Marcel Offermansa962bc92009-11-21 17:59:33 +000047
48/**
Marcel Offermans4fd903f2009-12-29 09:18:05 +000049 * The dependency manager manages all services and their dependencies. Using
50 * this API you can declare all services and their dependencies. Under normal
51 * circumstances, you get passed an instance of this class through the
52 * <code>DependencyActivatorBase</code> subclass you use as your
53 * <code>BundleActivator</code>, but it is also possible to create your
54 * own instance.
Marcel Offermansa962bc92009-11-21 17:59:33 +000055 *
56 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
57 */
58public class DependencyManager {
Marcel Offermansad760672010-03-03 15:30:01 +000059 public static final String ASPECT = "org.apache.felix.dependencymanager.aspect";
Marcel Offermansa962bc92009-11-21 17:59:33 +000060 private final BundleContext m_context;
61 private final Logger m_logger;
62 private List m_services = Collections.synchronizedList(new ArrayList());
63
64 /**
Marcel Offermans4fd903f2009-12-29 09:18:05 +000065 * Creates a new dependency manager. You need to supply the
66 * <code>BundleContext</code> to be used by the dependency
67 * manager to register services and communicate with the
68 * framework.
Marcel Offermansa962bc92009-11-21 17:59:33 +000069 *
70 * @param context the bundle context
Marcel Offermansa962bc92009-11-21 17:59:33 +000071 */
Pierre De Ropae4a5db2009-12-04 22:08:05 +000072 public DependencyManager(BundleContext context) {
73 this(context, new Logger(context));
74 }
75
Marcel Offermans4fd903f2009-12-29 09:18:05 +000076 DependencyManager(BundleContext context, Logger logger) {
Marcel Offermansa962bc92009-11-21 17:59:33 +000077 m_context = context;
78 m_logger = logger;
79 }
Pierre De Ropae4a5db2009-12-04 22:08:05 +000080
Marcel Offermansa962bc92009-11-21 17:59:33 +000081 /**
82 * Adds a new service to the dependency manager. After the service was added
83 * it will be started immediately.
84 *
85 * @param service the service to add
86 */
87 public void add(Service service) {
88 m_services.add(service);
89 service.start();
90 }
91
92 /**
93 * Removes a service from the dependency manager. Before the service is removed
94 * it is stopped first.
95 *
96 * @param service the service to remove
97 */
98 public void remove(Service service) {
99 service.stop();
100 m_services.remove(service);
101 }
102
103 /**
104 * Creates a new service.
105 *
106 * @return the new service
107 */
108 public Service createService() {
109 return new ServiceImpl(m_context, this, m_logger);
110 }
111
112 /**
113 * Creates a new service dependency.
114 *
115 * @return the service dependency
116 */
117 public ServiceDependency createServiceDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000118 return new ServiceDependencyImpl(m_context, m_logger);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000119 }
120
Marcel Offermans74363c32009-11-23 19:56:08 +0000121 /**
122 * Creates a new temporal service dependency.
123 *
124 * @param timeout the max number of milliseconds to wait for a service availability.
125 * @return the service dependency
126 */
127 public TemporalServiceDependency createTemporalServiceDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000128 return new TemporalServiceDependencyImpl(m_context, m_logger);
Marcel Offermans74363c32009-11-23 19:56:08 +0000129 }
Marcel Offermans2925f172009-12-02 13:03:39 +0000130
131 /**
132 * Creates a new configuration dependency.
133 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000134 * @return the configuration dependency
Marcel Offermans2925f172009-12-02 13:03:39 +0000135 */
Marcel Offermansa962bc92009-11-21 17:59:33 +0000136 public ConfigurationDependency createConfigurationDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000137 return new ConfigurationDependencyImpl(m_context, m_logger);
Marcel Offermansa962bc92009-11-21 17:59:33 +0000138 }
139
Marcel Offermans2925f172009-12-02 13:03:39 +0000140 /**
Pierre De Ropa0204f52010-03-06 22:23:57 +0000141 * Creates a new configuration property MetaData.
142 * @return a new Configuration property MetaData.
143 */
144 public PropertyMetaData createPropertyMetaData() {
145 return new PropertyMetaDataImpl();
146 }
147
148 /**
Marcel Offermans2925f172009-12-02 13:03:39 +0000149 * Creates a new bundle dependency.
150 *
151 * @return
152 */
Marcel Offermansd66c5ce2009-11-26 09:58:44 +0000153 public BundleDependency createBundleDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000154 return new BundleDependencyImpl(m_context, m_logger);
Marcel Offermansd66c5ce2009-11-26 09:58:44 +0000155 }
Marcel Offermans2925f172009-12-02 13:03:39 +0000156
157 /**
158 * Creates a new resource dependency.
159 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000160 * @return the resource dependency
Marcel Offermans2925f172009-12-02 13:03:39 +0000161 */
162 public ResourceDependency createResourceDependency() {
Pierre De Ropae4a5db2009-12-04 22:08:05 +0000163 return new ResourceDependencyImpl(m_context, m_logger);
Marcel Offermans2925f172009-12-02 13:03:39 +0000164 }
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000165
Marcel Offermans2925f172009-12-02 13:03:39 +0000166 /**
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000167 * Creates a new aspect. The aspect will be applied to any service that
168 * matches the specified interface and filter. For each matching service
169 * an aspect will be created based on the aspect implementation class.
170 * The aspect will be registered with the same interface and properties
171 * as the original service, plus any extra properties you supply here.
172 * It will also inherit all dependencies, and if you declare the original
173 * service as a member it will be injected.
Marcel Offermans2925f172009-12-02 13:03:39 +0000174 *
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000175 * @param serviceInterface the service interface to apply the aspect to
176 * @param serviceFilter the filter condition to use with the service interface
177 * @param aspectImplementation the implementation of the aspect
178 * @param aspectProperties additional properties to use with the aspect service registration
179 * @return a service that acts as a factory for generating aspects
Marcel Offermans2925f172009-12-02 13:03:39 +0000180 */
Marcel Offermansad760672010-03-03 15:30:01 +0000181 public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, Object aspectImplementation, Dictionary aspectProperties) {
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000182 return createService()
Marcel Offermansad760672010-03-03 15:30:01 +0000183 .setImplementation(new AspectImpl(serviceInterface, serviceFilter, ranking, aspectImplementation, aspectProperties))
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000184 .add(createServiceDependency()
Marcel Offermansad760672010-03-03 15:30:01 +0000185 .setService(serviceInterface, createAspectFilter(serviceFilter))
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000186 .setAutoConfig(false)
187 .setCallbacks("added", "removed")
188 );
189 }
Marcel Offermansad760672010-03-03 15:30:01 +0000190 public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, Object factory, String factoryCreateMethod, Dictionary aspectProperties) {
191 return createService()
192 .setImplementation(new AspectImpl(serviceInterface, serviceFilter, ranking, factory, factoryCreateMethod, aspectProperties))
193 .add(createServiceDependency()
194 .setService(serviceInterface, createAspectFilter(serviceFilter))
195 .setAutoConfig(false)
196 .setCallbacks("added", "removed")
197 );
198 }
199 private String createAspectFilter(String filter) {
200 // we only want to match services which are not themselves aspects
201 if (filter == null || filter.length() == 0) {
202 return "(!(" + ASPECT + "=*))";
203 }
204 else {
205 return "(&(!(" + ASPECT + "=*))" + filter + ")";
206 }
207 }
Marcel Offermans001db052009-12-08 08:58:40 +0000208
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000209 /**
210 * Creates a new adapter. The adapter will be applied to any service that
211 * matches the specified interface and filter. For each matching service
212 * an adapter will be created based on the adapter implementation class.
213 * The adapter will be registered with the specified interface and existing properties
214 * from the original service plus any extra properties you supply here.
215 * It will also inherit all dependencies, and if you declare the original
216 * service as a member it will be injected.
217 *
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000218 * @param serviceInterface the service interface to apply the adapter to
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000219 * @param serviceFilter the filter condition to use with the service interface
220 * @param adapterInterface the interface to use when registering adapters
221 * @param adapterImplementation the implementation of the adapter
222 * @param adapterProperties additional properties to use with the adapter service registration
223 * @return a service that acts as a factory for generating adapters
224 */
225 public Service createAdapterService(Class serviceInterface, String serviceFilter, Class adapterInterface, Object adapterImplementation, Dictionary adapterProperties) {
Marcel Offermans001db052009-12-08 08:58:40 +0000226 return createService()
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000227 .setImplementation(new AdapterImpl(serviceInterface, serviceFilter, adapterImplementation, adapterInterface.getName(), adapterProperties))
Marcel Offermans001db052009-12-08 08:58:40 +0000228 .add(createServiceDependency()
Marcel Offermans3e1998c2009-12-16 20:47:25 +0000229 .setService(serviceInterface)
Marcel Offermans001db052009-12-08 08:58:40 +0000230 .setAutoConfig(false)
231 .setCallbacks("added", "removed")
Marcel Offermans626260c2009-12-22 17:06:46 +0000232 );
Marcel Offermans001db052009-12-08 08:58:40 +0000233 }
234
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000235 /**
236 * Creates a new resource adapter. The adapter will be applied to any resource that
237 * matches the specified filter condition. For each matching resource
238 * an adapter will be created based on the adapter implementation class.
239 * The adapter will be registered with the specified interface and existing properties
240 * from the original resource plus any extra properties you supply here.
241 * It will also inherit all dependencies, and if you declare the original
242 * service as a member it will be injected.
243 *
244 * @param resourceFilter the filter condition to use with the resource
245 * @param adapterInterface the interface to use when registering adapters
246 * @param adapterProperties additional properties to use with the adapter service registration
247 * @param adapterImplementation the implementation of the adapter
248 * @param propagate <code>true</code> if properties from the resource should be propagated to the service
249 * @return a service that acts as a factory for generating resource adapters
250 * @see Resource
251 */
252 public Service createResourceAdapterService(String resourceFilter, Class adapterInterface, Dictionary adapterProperties, Object adapterImplementation, boolean propagate) {
Marcel Offermans001db052009-12-08 08:58:40 +0000253 return createService()
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000254 .setImplementation(new ResourceAdapterImpl(resourceFilter, adapterImplementation, adapterInterface.getName(), adapterProperties, propagate))
Marcel Offermans001db052009-12-08 08:58:40 +0000255 .add(createResourceDependency()
256 .setFilter(resourceFilter)
257 .setAutoConfig(false)
258 .setCallbacks("added", "removed")
Marcel Offermans626260c2009-12-22 17:06:46 +0000259 );
Marcel Offermans001db052009-12-08 08:58:40 +0000260 }
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000261
262 /**
263 * Creates a new bundle adapter. The adapter will be applied to any bundle that
264 * matches the specified bundle state mask and filter condition. For each matching
265 * bundle an adapter will be created based on the adapter implementation class.
266 * The adapter will be registered with the specified interface
267 *
268 * TODO and existing properties from the original resource plus any extra properties you supply here.
269 * It will also inherit all dependencies, and if you declare the original
270 * service as a member it will be injected.
271 *
272 * @param bundleStateMask the bundle state mask to apply
273 * @param bundleFilter the filter to apply to the bundle manifest
274 * @param adapterImplementation the implementation of the adapter
275 * @param adapterInterface the interface to use when registering adapters
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000276 * @param adapterProperties additional properties to use with the service registration
277 * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000278 * @return a service that acts as a factory for generating bundle adapters
279 */
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000280 public Service createBundleAdapterService(int bundleStateMask, String bundleFilter, Object adapterImplementation, String adapterInterface, Dictionary adapterProperties, boolean propagate) {
Marcel Offermans001db052009-12-08 08:58:40 +0000281 return createService()
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000282 .setImplementation(new BundleAdapterImpl(bundleStateMask, bundleFilter, adapterImplementation, adapterInterface, adapterProperties, propagate))
Marcel Offermans001db052009-12-08 08:58:40 +0000283 .add(createBundleDependency()
Marcel Offermans4fd903f2009-12-29 09:18:05 +0000284 .setFilter(bundleFilter)
285 .setStateMask(bundleStateMask)
Marcel Offermans001db052009-12-08 08:58:40 +0000286 .setCallbacks("added", "removed")
Marcel Offermans626260c2009-12-22 17:06:46 +0000287 );
Marcel Offermans001db052009-12-08 08:58:40 +0000288 }
Marcel Offermans80eeafe2009-12-01 22:12:26 +0000289
Marcel Offermansa962bc92009-11-21 17:59:33 +0000290 /**
291 * Returns a list of services.
292 *
293 * @return a list of services
294 */
295 public List getServices() {
296 return Collections.unmodifiableList(m_services);
297 }
Marcel Offermansa962bc92009-11-21 17:59:33 +0000298}