Skip to content

Commit

Permalink
ARIES-342: Stop memory leak with CompositeBundles
Browse files Browse the repository at this point in the history
git-svn-id: https://svn.apache.org/repos/asf/incubator/aries/trunk/util@958509 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
Valentin Mahrwald committed Jun 28, 2010
1 parent 757d7e0 commit aa6eb0d
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 3 deletions.
Expand Up @@ -99,7 +99,7 @@ public void modifiedBundle(Bundle b, BundleEvent event, Object object)
public void removedBundle(Bundle b, BundleEvent event, Object object)
{
if (b instanceof CompositeBundle) {
// We should have already picked up the stopping event on the CBA itself
customizedProcessBundle(this, b, event);
} else {
if (customizer != null) {
customizer.removedBundle(b, event, object);
Expand All @@ -123,7 +123,7 @@ protected void customizedProcessBundle(BundleTrackerCustomizer btc, Bundle b, Bu
openTracker(btc, cb, bundleScope, mask);
}
} else {
if (event.getType() == BundleEvent.STOPPING) {
if (event.getType() == BundleEvent.STOPPED) {
// if CompositeBundle is being stopped, let's remove the bundle
// tracker(s) associated with the composite bundle
BundleContext compositeBundleContext = ((CompositeBundle) b).getCompositeFramework()
Expand Down
Expand Up @@ -47,7 +47,7 @@ public final class RecursiveBundleTracker {
*
* @param context - The <code>BundleContext</code> against which the tracking is done.
* @param stateMask - The bit mask of the ORing of the bundle states to be tracked. The
* mask must contain the flags <code>Bundle.STARTING | Bundle.ACTIVE | Bundle.STOPPING</code>
* mask must contain the flags <code>Bundle.INSTALLED | Bundle.STARTING | Bundle.ACTIVE | Bundle.STOPPING</code>
* as a minimum.
* @throws IllegalArgumentException - If the provided bit mask does not contain required
* flags
Expand Down
@@ -0,0 +1,94 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.aries.util;

import org.apache.aries.unittest.mocks.MethodCall;
import org.apache.aries.unittest.mocks.Skeleton;
import org.apache.aries.util.tracker.BundleTrackerFactory;
import org.apache.aries.util.tracker.InternalRecursiveBundleTracker;
import org.apache.aries.util.tracker.RecursiveBundleTracker;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;
import org.osgi.service.framework.CompositeBundle;
import org.osgi.service.framework.CompositeBundleFactory;
import org.osgi.util.tracker.BundleTrackerCustomizer;

import static org.junit.Assert.*;

public class RecursiveBundleTrackerTest {
BundleContext context;

@Before
public void setup() {
context = Skeleton.newMock(BundleContext.class);
Skeleton.getSkeleton(context).setReturnValue(
new MethodCall(BundleContext.class, "getServiceReference", "org.osgi.service.framework.CompositeBundleFactory"),
Skeleton.newMock(ServiceReference.class));
}

@After
public void closeTrackes() {
BundleTrackerFactory.unregisterAndCloseBundleTracker("test");
}

@Test
public void testCompositeLifeCycle() {
BundleTrackerCustomizer customizer = Skeleton.newMock(BundleTrackerCustomizer.class);

InternalRecursiveBundleTracker sut = new InternalRecursiveBundleTracker(context,
Bundle.INSTALLED | Bundle.STARTING | Bundle.ACTIVE | Bundle.STOPPING, customizer);

sut.open();

CompositeBundle cb = Skeleton.newMock(CompositeBundle.class);
Skeleton cbSkel = Skeleton.getSkeleton(cb);
cbSkel.setReturnValue(new MethodCall(CompositeBundle.class, "getSymbolicName"), "test.composite");
cbSkel.setReturnValue(new MethodCall(CompositeBundle.class, "getVersion"), new Version("1.0.0"));

assertTrue(BundleTrackerFactory.getAllBundleTracker().isEmpty());

sut.addingBundle(cb, new BundleEvent(BundleEvent.INSTALLED, cb));
assertEquals(1, BundleTrackerFactory.getAllBundleTracker().size());
assertEquals(1, BundleTrackerFactory.getBundleTrackerList("test.composite_1.0.0").size());

sut.removedBundle(cb, new BundleEvent(BundleEvent.STOPPED, cb), cb);
assertTrue(BundleTrackerFactory.getAllBundleTracker().isEmpty());
}

@Test(expected=IllegalArgumentException.class)
public void testMissingStopping() {
new RecursiveBundleTracker(null, Bundle.INSTALLED | Bundle.RESOLVED | Bundle.STARTING | Bundle.ACTIVE, null);
}

@Test(expected=IllegalArgumentException.class)
public void testMissingStarting() {
new RecursiveBundleTracker(null, Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE | Bundle.STOPPING, null);
}

@Test(expected=IllegalArgumentException.class)
public void testMissingInstalled() {
new RecursiveBundleTracker(null, Bundle.RESOLVED | Bundle.STARTING | Bundle.ACTIVE | Bundle.STOPPING, null);
}
}

0 comments on commit aa6eb0d

Please sign in to comment.