Modified the bundle tracker to be even simpler, so that I wouldn't have
to deal with various concurrency issues.


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@556701 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/BundleTracker.java b/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/BundleTracker.java
index 13a6982..f180fbd 100644
--- a/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/BundleTracker.java
+++ b/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/BundleTracker.java
@@ -26,33 +26,34 @@
 import org.osgi.framework.SynchronousBundleListener;
 
 /**
- * This is a simple class that only tracks active bundles. It must be given
- * a bundle context upon creation, which it uses to listen for bundle events.
- * It may also be given a bundle tracker customizer object which it will
- * notify about changes in the list of active bundles. The bundle tracker
- * must be opened to track objects and closed when it is no longer needed.
+ * This is a very simple bundle tracker utility class that tracks active
+ * bundles. The tracker must be given a bundle context upon creation,
+ * which it uses to listen for bundle events. The bundle tracker must be
+ * opened to track objects and closed when it is no longer needed. This
+ * class is abstract, which means in order to use it you must create a
+ * subclass of it. Subclasses must implement the <tt>addedBundle()</tt>
+ * and <tt>removedBundle()</tt> methods, which can be used to perform some
+ * custom action upon the activation or deactivation of bundles. Since this
+ * tracker is quite simple, its concurrency control approach is also
+ * simplistic. This means that subclasses should take great care to ensure
+ * that their <tt>addedBundle()</tt> and <tt>removedBundle()</tt> methods
+ * are very simple and do not do anything to change the state of any bundles.
 **/
-public class BundleTracker implements BundleTrackerCustomizer
+public abstract class BundleTracker
 {
-    private Set m_bundleSet = new HashSet();
-    private BundleContext m_context;
-    private BundleTrackerCustomizer m_customizer;
-    private SynchronousBundleListener m_listener;
-    private boolean m_open;
+    final Set m_bundleSet = new HashSet();
+    final BundleContext m_context;
+    final SynchronousBundleListener m_listener;
+    boolean m_open;
 
     /**
      * Constructs a bundle tracker object that will use the specified
-     * bundle context for listening to bundle events and will notify the
-     * specified bundle tracker customizer about changes in the set of
-     * active bundles.
+     * bundle context.
      * @param context The bundle context to use to track bundles.
-     * @param customizer The bundle tracker customerizer to inform about
-     *        changes in the active set of bundles.
     **/
-    public BundleTracker(BundleContext context, BundleTrackerCustomizer customizer)
+    public BundleTracker(BundleContext context)
     {
         m_context = context;
-        m_customizer = (customizer == null) ? this : customizer;
         m_listener = new SynchronousBundleListener() {
             public void bundleChanged(BundleEvent evt)
             {
@@ -68,7 +69,7 @@
                         if (!m_bundleSet.contains(evt.getBundle()))
                         {
                             m_bundleSet.add(evt.getBundle());
-                            m_customizer.addedBundle(evt.getBundle());
+                            addedBundle(evt.getBundle());
                         }
                     }
                     else if (evt.getType() == BundleEvent.STOPPED)
@@ -76,7 +77,7 @@
                         if (m_bundleSet.contains(evt.getBundle()))
                         {
                             m_bundleSet.remove(evt.getBundle());
-                            m_customizer.removedBundle(evt.getBundle());
+                            removedBundle(evt.getBundle());
                         }
                     }
                 }
@@ -110,7 +111,7 @@
                 if (bundles[i].getState() == Bundle.ACTIVE)
                 {
                     m_bundleSet.add(bundles[i]);
-                    m_customizer.addedBundle(bundles[i]);
+                    addedBundle(bundles[i]);
                 }
             }
         }
@@ -127,34 +128,32 @@
 
             m_context.removeBundleListener(m_listener);
 
-            Bundle[] bundles = getBundles();
+            Bundle[] bundles = (Bundle[]) m_bundleSet.toArray(new Bundle[m_bundleSet.size()]);
             for (int i = 0; i < bundles.length; i++)
             {
                 if (m_bundleSet.remove(bundles[i]))
                 {
-                    m_customizer.removedBundle(bundles[i]);
+                    removedBundle(bundles[i]);
                 }
             }
         }
     }
 
     /**
-     * A default implementation of the bundle tracker customizer that
-     * does nothing.
+     * Subclasses must implement this method; it can be used to perform
+     * actions upon the activation of a bundle. Subclasses should keep
+     * this method implementation as simple as possible and should not
+     * cause the change in any bundle state to avoid concurrency issues.
      * @param bundle The bundle being added to the active set.
     **/
-    public void addedBundle(Bundle bundle)
-    {
-        // Do nothing by default.
-    }
+    protected abstract void addedBundle(Bundle bundle);
 
     /**
-     * A default implementation of the bundle tracker customizer that
-     * does nothing.
+     * Subclasses must implement this method; it can be used to perform
+     * actions upon the deactivation of a bundle. Subclasses should keep
+     * this method implementation as simple as possible and should not
+     * cause the change in any bundle state to avoid concurrency issues.
      * @param bundle The bundle being removed from the active set.
     **/
-    public void removedBundle(Bundle bundle)
-    {
-        // Do nothing by default.
-    }
+    protected abstract void removedBundle(Bundle bundle);
 }
\ No newline at end of file
diff --git a/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/BundleTrackerCustomizer.java b/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/BundleTrackerCustomizer.java
deleted file mode 100644
index d0cbc18..0000000
--- a/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/BundleTrackerCustomizer.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.felix.example.extenderbased.host;
-
-import org.osgi.framework.Bundle;
-
-/**
- * This interface class can be used to customize the bundle tracker
- * handling of bundle notifications when adding/removing bundles
- * to/from the active set of bundles.
-**/
-public interface BundleTrackerCustomizer
-{
-    /**
-     * Called when an inactive bundle becomes active.
-     * @param bundle The activated bundle.
-    **/
-    public void addedBundle(Bundle bundle);
-
-    /**
-     * Called when an active bundle becomes inactive.
-     * @param bundle The inactivated bundle.
-    **/
-    public void removedBundle(Bundle bundle);
-}
\ No newline at end of file
diff --git a/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/ShapeTracker.java b/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/ShapeTracker.java
index 873e7db..09d8f44 100644
--- a/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/ShapeTracker.java
+++ b/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/ShapeTracker.java
@@ -27,11 +27,10 @@
 /**
  * Extends the <tt>BundleTracker</tt> to create a tracker for
  * <tt>SimpleShape</tt> extensions. The tracker is responsible for
- * listener for the arrival/departure of <tt>SimpleShape</tt>
- * extensions and informing the application about the availability
- * of shapes. This tracker forces all notifications to be processed
- * on the Swing event thread to avoid synchronization and redraw
- * issues.
+ * listening for <tt>SimpleShape</tt> extensions and informing the
+ * application about the availability of shapes. This tracker forces
+ * all notifications to be processed on the Swing event thread to
+ * avoid synchronization and redraw issues.
 **/
 public class ShapeTracker extends BundleTracker
 {
@@ -51,7 +50,7 @@
     **/
     public ShapeTracker(BundleContext context, DrawingFrame frame)
     {
-        super(context, null);
+        super(context);
         m_frame = frame;
     }
 
@@ -60,7 +59,7 @@
      * the application object about the added extensions.
      * @param bundle The activated bundle.
     **/
-    public void addedBundle(Bundle bundle)
+    protected void addedBundle(Bundle bundle)
     {
         processBundleOnEventThread(ADDED, bundle);
     }
@@ -70,7 +69,7 @@
      * the application object about removed extensions.
      * @param bundle The inactivated bundle.
     **/
-    public void removedBundle(Bundle bundle)
+    protected void removedBundle(Bundle bundle)
     {
         processBundleOnEventThread(REMOVED, bundle);
     }