blob: 07b90bbadded9c694309c931d7338f090c9ffd00 [file] [log] [blame]
Marcel Offermanse14b3422009-11-25 23:04:32 +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 Rope4d80b92009-12-04 22:48:32 +000019package org.apache.felix.dm.impl.dependencies;
Marcel Offermanse14b3422009-11-25 23:04:32 +000020
Marcel Offermans26081d32010-07-12 12:43:42 +000021import java.lang.reflect.InvocationTargetException;
Marcel Offermansd665eaf2010-02-16 15:56:35 +000022import java.lang.reflect.Proxy;
Marcel Offermanscae61362009-12-01 08:37:10 +000023import java.util.ArrayList;
Marcel Offermanse14b3422009-11-25 23:04:32 +000024import java.util.Dictionary;
Marcel Offermanscae61362009-12-01 08:37:10 +000025import java.util.List;
Marcel Offermanse14b3422009-11-25 23:04:32 +000026
Marcel Offermans8b93efa2010-07-02 18:27:21 +000027import org.apache.felix.dm.BundleDependency;
28import org.apache.felix.dm.Dependency;
Marcel Offermans3d921212010-08-09 13:37:02 +000029import org.apache.felix.dm.DependencyService;
Marcel Offermans8b93efa2010-07-02 18:27:21 +000030import org.apache.felix.dm.ServiceComponentDependency;
Marcel Offermansd665eaf2010-02-16 15:56:35 +000031import org.apache.felix.dm.impl.DefaultNullObject;
Marcel Offermans26081d32010-07-12 12:43:42 +000032import org.apache.felix.dm.impl.InvocationUtil;
Pierre De Rope4d80b92009-12-04 22:48:32 +000033import org.apache.felix.dm.impl.Logger;
34import org.apache.felix.dm.impl.tracker.BundleTracker;
35import org.apache.felix.dm.impl.tracker.BundleTrackerCustomizer;
Marcel Offermanse14b3422009-11-25 23:04:32 +000036import org.osgi.framework.Bundle;
37import org.osgi.framework.BundleContext;
38import org.osgi.framework.BundleEvent;
39import org.osgi.framework.Filter;
40import org.osgi.framework.InvalidSyntaxException;
Marcel Offermans26081d32010-07-12 12:43:42 +000041import org.osgi.service.log.LogService;
Marcel Offermanse14b3422009-11-25 23:04:32 +000042
Marcel Offermans61a81142010-04-02 15:16:50 +000043public class BundleDependencyImpl extends DependencyBase implements BundleDependency, BundleTrackerCustomizer, ServiceComponentDependency {
Marcel Offermanse14b3422009-11-25 23:04:32 +000044 private final BundleContext m_context;
Marcel Offermanse14b3422009-11-25 23:04:32 +000045 private boolean m_isStarted;
46 private BundleTracker m_tracker;
Marcel Offermansd66c5ce2009-11-26 09:58:44 +000047 private int m_stateMask = Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE;
Marcel Offermanscae61362009-12-01 08:37:10 +000048 private List m_services = new ArrayList();
Marcel Offermansb196d722009-11-26 17:12:12 +000049 private boolean m_isAvailable;
Marcel Offermanse14b3422009-11-25 23:04:32 +000050 private Object m_callbackInstance;
51 private String m_callbackAdded;
52 private String m_callbackChanged;
53 private String m_callbackRemoved;
54 private boolean m_autoConfig;
55 private Bundle m_bundleInstance;
56 private Filter m_filter;
57 private long m_bundleId = -1;
Marcel Offermansd665eaf2010-02-16 15:56:35 +000058 private String m_autoConfigInstance;
59 private Object m_nullObject;
60 private boolean m_autoConfigInvoked;
Marcel Offermans26081d32010-07-12 12:43:42 +000061 private boolean m_propagate;
62 private Object m_propagateCallbackInstance;
63 private String m_propagateCallbackMethod;
Marcel Offermansd665eaf2010-02-16 15:56:35 +000064
Pierre De Rope4d80b92009-12-04 22:48:32 +000065 public BundleDependencyImpl(BundleContext context, Logger logger) {
Marcel Offermansb196d722009-11-26 17:12:12 +000066 super(logger);
Marcel Offermanse14b3422009-11-25 23:04:32 +000067 m_context = context;
Marcel Offermanse14b3422009-11-25 23:04:32 +000068 m_autoConfig = true;
69 }
Marcel Offermansb1959f42010-07-01 12:23:51 +000070
71 public BundleDependencyImpl(BundleDependencyImpl prototype) {
72 super(prototype);
73 m_context = prototype.m_context;
74 m_autoConfig = prototype.m_autoConfig;
75 m_stateMask = prototype.m_stateMask;
76 m_nullObject = prototype.m_nullObject;
77 m_bundleInstance = prototype.m_bundleInstance;
78 m_filter = prototype.m_filter;
79 m_bundleId = prototype.m_bundleId;
80 m_propagate = prototype.m_propagate;
81 m_callbackInstance = prototype.m_callbackInstance;
82 m_callbackAdded = prototype.m_callbackAdded;
83 m_callbackChanged = prototype.m_callbackChanged;
84 m_callbackRemoved = prototype.m_callbackRemoved;
85 m_autoConfigInstance = prototype.m_autoConfigInstance;
86 }
87
88 public Dependency createCopy() {
89 return new BundleDependencyImpl(this);
90 }
Marcel Offermanse14b3422009-11-25 23:04:32 +000091
Marcel Offermans61a81142010-04-02 15:16:50 +000092 public BundleDependency setInstanceBound(boolean isInstanceBound) {
93 setIsInstanceBound(isInstanceBound);
94 return this;
95 }
96
Marcel Offermansb196d722009-11-26 17:12:12 +000097 public synchronized boolean isAvailable() {
98 return m_isAvailable;
99 }
100
Marcel Offermansb196d722009-11-26 17:12:12 +0000101 public void start(DependencyService service) {
Marcel Offermanscae61362009-12-01 08:37:10 +0000102 boolean needsStarting = false;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000103 synchronized (this) {
Marcel Offermanscae61362009-12-01 08:37:10 +0000104 m_services.add(service);
105 if (!m_isStarted) {
106 m_tracker = new BundleTracker(m_context, m_stateMask, this);
107 m_isStarted = true;
108 needsStarting = true;
109 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000110 }
Marcel Offermanscae61362009-12-01 08:37:10 +0000111 if (needsStarting) {
112 m_tracker.open();
113 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000114 }
115
116 public void stop(DependencyService service) {
Marcel Offermanscae61362009-12-01 08:37:10 +0000117 boolean needsStopping = false;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000118 synchronized (this) {
Marcel Offermanscae61362009-12-01 08:37:10 +0000119 if (m_services.size() == 1 && m_services.contains(service)) {
120 m_isStarted = false;
121 needsStopping = true;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000122 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000123 }
Marcel Offermanscae61362009-12-01 08:37:10 +0000124 if (needsStopping) {
125 m_tracker.close();
126 m_tracker = null;
127 m_services.remove(service);
128 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000129 }
130
131 public String getName() {
Marcel Offermanscae61362009-12-01 08:37:10 +0000132 StringBuilder sb = new StringBuilder();
Marcel Offermansb1959f42010-07-01 12:23:51 +0000133 if ((m_stateMask & Bundle.ACTIVE) != 0) {
134 sb.append("active ");
Marcel Offermans001db052009-12-08 08:58:40 +0000135 }
Marcel Offermansb1959f42010-07-01 12:23:51 +0000136 if ((m_stateMask & Bundle.INSTALLED) != 0) {
137 sb.append("installed ");
138 }
139 if ((m_stateMask & Bundle.RESOLVED) != 0) {
140 sb.append("resolved ");
141 }
Marcel Offermanscae61362009-12-01 08:37:10 +0000142 if (m_filter != null) {
Marcel Offermanscae61362009-12-01 08:37:10 +0000143 sb.append(m_filter.toString());
144 }
Marcel Offermansb1959f42010-07-01 12:23:51 +0000145 if (m_bundleId != -1) {
146 sb.append("bundle.id=" + m_bundleId);
147 }
Marcel Offermanscae61362009-12-01 08:37:10 +0000148 return sb.toString();
Marcel Offermanse14b3422009-11-25 23:04:32 +0000149 }
150
151 public int getState() {
Marcel Offermansb1959f42010-07-01 12:23:51 +0000152 return (isAvailable() ? 1 : 0) + (isRequired() ? 2 : 0);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000153 }
154
155 public String getType() {
Marcel Offermanscae61362009-12-01 08:37:10 +0000156 return "bundle";
Marcel Offermanse14b3422009-11-25 23:04:32 +0000157 }
158
159 public Object addingBundle(Bundle bundle, BundleEvent event) {
Marcel Offermanse14b3422009-11-25 23:04:32 +0000160 // if we don't like a bundle, we could reject it here by returning null
Marcel Offermans001db052009-12-08 08:58:40 +0000161 long bundleId = bundle.getBundleId();
162 if (m_bundleId >= 0 && m_bundleId != bundleId) {
Marcel Offermanse14b3422009-11-25 23:04:32 +0000163 return null;
164 }
165 Filter filter = m_filter;
166 if (filter != null) {
167 Dictionary headers = bundle.getHeaders();
168 if (!m_filter.match(headers)) {
169 return null;
170 }
171 }
172 return bundle;
173 }
174
175 public void addedBundle(Bundle bundle, BundleEvent event, Object object) {
Marcel Offermanscae61362009-12-01 08:37:10 +0000176 boolean makeAvailable = makeAvailable();
177 Object[] services = m_services.toArray();
178 for (int i = 0; i < services.length; i++) {
179 DependencyService ds = (DependencyService) services[i];
180 if (makeAvailable) {
181 ds.dependencyAvailable(this);
182 if (!isRequired()) {
183 invokeAdded(ds, bundle);
184 }
185 }
186 else {
187 ds.dependencyChanged(this);
188 invokeAdded(ds, bundle);
189 }
190 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000191 }
192
193 public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
Marcel Offermanscae61362009-12-01 08:37:10 +0000194 Object[] services = m_services.toArray();
195 for (int i = 0; i < services.length; i++) {
196 DependencyService ds = (DependencyService) services[i];
197 ds.dependencyChanged(this);
198 if (ds.isRegistered()) {
199 invokeChanged(ds, bundle);
200 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000201 }
202 }
203
204 public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
Marcel Offermanscae61362009-12-01 08:37:10 +0000205 boolean makeUnavailable = makeUnavailable();
206 Object[] services = m_services.toArray();
207 for (int i = 0; i < services.length; i++) {
208 DependencyService ds = (DependencyService) services[i];
209 if (makeUnavailable) {
210 ds.dependencyUnavailable(this);
211 if (!isRequired()) {
212 invokeRemoved(ds, bundle);
213 }
Marcel Offermans9f3c5f42009-11-26 11:17:36 +0000214 }
Marcel Offermanscae61362009-12-01 08:37:10 +0000215 else {
216 ds.dependencyChanged(this);
217 invokeRemoved(ds, bundle);
218 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000219 }
220 }
221
222 private synchronized boolean makeAvailable() {
Marcel Offermansb196d722009-11-26 17:12:12 +0000223 if (!isAvailable()) {
Marcel Offermanse14b3422009-11-25 23:04:32 +0000224 m_isAvailable = true;
225 return true;
226 }
227 return false;
228 }
229
230 private synchronized boolean makeUnavailable() {
Marcel Offermansb196d722009-11-26 17:12:12 +0000231 if ((isAvailable()) && (m_tracker.getTrackingCount() == 0)) {
Marcel Offermanse14b3422009-11-25 23:04:32 +0000232 m_isAvailable = false;
233 return true;
234 }
235 return false;
236 }
237
Marcel Offermanscae61362009-12-01 08:37:10 +0000238 public void invokeAdded(DependencyService dependencyService, Bundle service) {
Marcel Offermansea89b862010-06-24 13:14:43 +0000239 invoke(dependencyService, service, m_callbackAdded);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000240 }
241
Marcel Offermanscae61362009-12-01 08:37:10 +0000242 public void invokeChanged(DependencyService dependencyService, Bundle service) {
Marcel Offermansea89b862010-06-24 13:14:43 +0000243 invoke(dependencyService, service, m_callbackChanged);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000244 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000245
Marcel Offermanscae61362009-12-01 08:37:10 +0000246 public void invokeRemoved(DependencyService dependencyService, Bundle service) {
Marcel Offermansea89b862010-06-24 13:14:43 +0000247 invoke(dependencyService, service, m_callbackRemoved);
248 }
249
250 public void invoke(DependencyService dependencyService, Bundle service, String name) {
251 if (name != null) {
252 dependencyService.invokeCallbackMethod(getCallbackInstances(dependencyService), name,
Marcel Offermansb196d722009-11-26 17:12:12 +0000253 new Class[][] {{Bundle.class}, {Object.class}, {}},
254 new Object[][] {{service}, {service}, {}}
255 );
Marcel Offermanse14b3422009-11-25 23:04:32 +0000256 }
257 }
Marcel Offermanscae61362009-12-01 08:37:10 +0000258
259 private synchronized Object[] getCallbackInstances(DependencyService dependencyService) {
Marcel Offermanse14b3422009-11-25 23:04:32 +0000260 if (m_callbackInstance == null) {
Marcel Offermanscae61362009-12-01 08:37:10 +0000261 return dependencyService.getCompositionInstances();
Marcel Offermanse14b3422009-11-25 23:04:32 +0000262 }
Marcel Offermanscae61362009-12-01 08:37:10 +0000263 else {
264 return new Object[] { m_callbackInstance };
265 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000266 }
Marcel Offermanscae61362009-12-01 08:37:10 +0000267
Marcel Offermanse14b3422009-11-25 23:04:32 +0000268 /**
269 * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
270 * dependency is added or removed. When you specify callbacks, the auto configuration
271 * feature is automatically turned off, because we're assuming you don't need it in this
272 * case.
273 *
274 * @param added the method to call when a service was added
275 * @param removed the method to call when a service was removed
276 * @return this service dependency
277 */
278 public synchronized BundleDependency setCallbacks(String added, String removed) {
279 return setCallbacks(null, added, null, removed);
280 }
281
282 /**
283 * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
284 * dependency is added, changed or removed. When you specify callbacks, the auto
285 * configuration feature is automatically turned off, because we're assuming you don't
286 * need it in this case.
287 *
288 * @param added the method to call when a service was added
289 * @param changed the method to call when a service was changed
290 * @param removed the method to call when a service was removed
291 * @return this service dependency
292 */
293 public synchronized BundleDependency setCallbacks(String added, String changed, String removed) {
294 return setCallbacks(null, added, changed, removed);
295 }
296
297 /**
298 * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
299 * dependency is added or removed. They are called on the instance you provide. When you
300 * specify callbacks, the auto configuration feature is automatically turned off, because
301 * we're assuming you don't need it in this case.
302 *
303 * @param instance the instance to call the callbacks on
304 * @param added the method to call when a service was added
305 * @param removed the method to call when a service was removed
306 * @return this service dependency
307 */
308 public synchronized BundleDependency setCallbacks(Object instance, String added, String removed) {
309 return setCallbacks(instance, added, null, removed);
310 }
311
312 /**
313 * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
314 * dependency is added, changed or removed. They are called on the instance you provide. When you
315 * specify callbacks, the auto configuration feature is automatically turned off, because
316 * we're assuming you don't need it in this case.
317 *
318 * @param instance the instance to call the callbacks on
319 * @param added the method to call when a service was added
320 * @param changed the method to call when a service was changed
321 * @param removed the method to call when a service was removed
322 * @return this service dependency
323 */
324 public synchronized BundleDependency setCallbacks(Object instance, String added, String changed, String removed) {
325 ensureNotActive();
326 // if at least one valid callback is specified, we turn off auto configuration
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000327 if ((added != null || removed != null || changed != null) && ! m_autoConfigInvoked) {
Marcel Offermanse14b3422009-11-25 23:04:32 +0000328 setAutoConfig(false);
329 }
330 m_callbackInstance = instance;
331 m_callbackAdded = added;
332 m_callbackChanged = changed;
333 m_callbackRemoved = removed;
334 return this;
335 }
336
337 private void ensureNotActive() {
338 if (m_tracker != null) {
339 throw new IllegalStateException("Cannot modify state while active.");
340 }
341 }
342 public synchronized BundleDependency setAutoConfig(boolean autoConfig) {
343 ensureNotActive();
344 m_autoConfig = autoConfig;
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000345 m_autoConfigInvoked = true;
346 return this;
347 }
348
349 public synchronized BundleDependency setAutoConfig(String instanceName) {
350 ensureNotActive();
351 m_autoConfig = (instanceName != null);
352 m_autoConfigInstance = instanceName;
353 m_autoConfigInvoked = true;
Marcel Offermanse14b3422009-11-25 23:04:32 +0000354 return this;
355 }
356
357 public synchronized BundleDependency setRequired(boolean required) {
358 ensureNotActive();
Marcel Offermansb196d722009-11-26 17:12:12 +0000359 setIsRequired(required);
Marcel Offermanse14b3422009-11-25 23:04:32 +0000360 return this;
361 }
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000362
Marcel Offermanse14b3422009-11-25 23:04:32 +0000363 public BundleDependency setBundle(Bundle bundle) {
364 m_bundleId = bundle.getBundleId();
365 return this;
366 }
367
368 public BundleDependency setFilter(String filter) throws IllegalArgumentException {
369 if (filter != null) {
370 try {
371 m_filter = m_context.createFilter(filter);
372 }
373 catch (InvalidSyntaxException e) {
374 throw new IllegalArgumentException(e.getMessage());
375 }
376 }
377 return this;
378 }
379
380 public BundleDependency setStateMask(int mask) {
381 m_stateMask = mask;
382 return this;
383 }
384
385 public synchronized boolean isAutoConfig() {
386 return m_autoConfig;
387 }
388
389 public Bundle getBundle() {
390 Bundle[] bundles = m_tracker.getBundles();
391 if (bundles != null && bundles.length > 0) {
392 return bundles[0];
393 }
394 return null;
395 }
Marcel Offermans001db052009-12-08 08:58:40 +0000396
397 public Object getAutoConfigInstance() {
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000398 return lookupBundle();
Marcel Offermans001db052009-12-08 08:58:40 +0000399 }
400
Marcel Offermansad760672010-03-03 15:30:01 +0000401 public Bundle lookupBundle() {
402 Bundle service = null;
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000403 if (m_isStarted) {
404 service = getBundle();
405 }
406 else {
407 Bundle[] bundles = m_context.getBundles();
408 for (int i = 0; i < bundles.length; i++) {
409 if ((bundles[i].getState() & m_stateMask) > 0) {
Marcel Offermans9ace4f42010-02-16 16:25:38 +0000410 Filter filter = m_filter;
411 if (filter == null) {
412 service = bundles[i];
413 break;
414 }
415 else if (filter.match(bundles[i].getHeaders())) {
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000416 service = bundles[i];
417 break;
418 }
419 }
420 }
421 }
422 if (service == null && isAutoConfig()) {
423 // TODO does it make sense to add support for custom bundle impls?
424// service = getDefaultImplementation();
425 if (service == null) {
426 service = getNullObject();
427 }
428 }
429 return service;
430 }
431
Marcel Offermansad760672010-03-03 15:30:01 +0000432 private Bundle getNullObject() {
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000433 if (m_nullObject == null) {
434 try {
435 m_nullObject = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { Bundle.class }, new DefaultNullObject());
436 }
437 catch (Exception e) {
438 m_logger.log(Logger.LOG_ERROR, "Could not create null object for Bundle.", e);
439 }
440 }
Marcel Offermansad760672010-03-03 15:30:01 +0000441 return (Bundle) m_nullObject;
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000442 }
443
Marcel Offermans001db052009-12-08 08:58:40 +0000444 public String getAutoConfigName() {
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000445 return m_autoConfigInstance;
Marcel Offermans001db052009-12-08 08:58:40 +0000446 }
447
448 public Class getAutoConfigType() {
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000449 return Bundle.class;
Marcel Offermans001db052009-12-08 08:58:40 +0000450 }
451
452 public void invokeAdded(DependencyService service) {
453 // we remember these for future reference, needed for required service callbacks
Marcel Offermansad760672010-03-03 15:30:01 +0000454 m_bundleInstance = lookupBundle();
Marcel Offermans001db052009-12-08 08:58:40 +0000455 invokeAdded(service, m_bundleInstance);
456 }
457
458 public void invokeRemoved(DependencyService service) {
459 invokeRemoved(service, m_bundleInstance);
460 m_bundleInstance = null;
461 }
Marcel Offermans26081d32010-07-12 12:43:42 +0000462
463 public BundleDependency setPropagate(boolean propagate) {
464 ensureNotActive();
465 m_propagate = propagate;
466 return this;
467 }
468
469 public BundleDependency setPropagate(Object instance, String method) {
470 setPropagate(instance != null && method != null);
471 m_propagateCallbackInstance = instance;
472 m_propagateCallbackMethod = method;
473 return this;
474 }
475
Marcel Offermans117aa2f2009-12-10 09:48:17 +0000476 public Dictionary getProperties() {
Marcel Offermans26081d32010-07-12 12:43:42 +0000477 Bundle bundle = lookupBundle();
478 if (bundle != null) {
479 if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
480 try {
481 return (Dictionary) InvocationUtil.invokeCallbackMethod(m_propagateCallbackInstance, m_propagateCallbackMethod, new Class[][] {{ Bundle.class }}, new Object[][] {{ bundle }});
482 }
483 catch (InvocationTargetException e) {
484 m_logger.log(LogService.LOG_WARNING, "Exception while invoking callback method", e.getCause());
485 }
486 catch (Exception e) {
487 m_logger.log(LogService.LOG_WARNING, "Exception while trying to invoke callback method", e);
488 }
489 throw new IllegalStateException("Could not invoke callback");
490 }
491 else {
492 return bundle.getHeaders();
493 }
494 }
495 else {
496 throw new IllegalStateException("cannot find bundle");
497 }
Marcel Offermans117aa2f2009-12-10 09:48:17 +0000498 }
499
500 public boolean isPropagated() {
Marcel Offermansd665eaf2010-02-16 15:56:35 +0000501 return m_propagate;
Marcel Offermans117aa2f2009-12-10 09:48:17 +0000502 }
Marcel Offermanse14b3422009-11-25 23:04:32 +0000503}