You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2009/07/24 19:06:44 UTC
svn commit: r797561 [7/9] - in /felix/trunk: org.osgi.compendium/
org.osgi.compendium/src/main/java/info/dmtree/
org.osgi.compendium/src/main/java/info/dmtree/notification/
org.osgi.compendium/src/main/java/info/dmtree/notification/spi/
org.osgi.compen...
Modified: felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/State.java
URL: http://svn.apache.org/viewvc/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/State.java?rev=797561&r1=797560&r2=797561&view=diff
==============================================================================
--- felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/State.java (original)
+++ felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/State.java Fri Jul 24 17:06:37 2009
@@ -1,7 +1,5 @@
/*
- * $Header: /cvshome/build/org.osgi.util.measurement/src/org/osgi/util/measurement/State.java,v 1.8 2006/06/16 16:31:34 hargrave Exp $
- *
- * Copyright (c) OSGi Alliance (2002, 2006). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 2008). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,12 +25,13 @@
* <p>
* A <code>State</code> object is immutable so that it may be easily shared.
*
- * @version $Revision: 1.8 $
+ * @Immutable
+ * @version $Revision: 5715 $
*/
public class State {
- final int value;
- final long time;
- final String name;
+ private final int value;
+ private final long time;
+ private final String name;
/**
* Create a new <code>State</code> object.
@@ -108,9 +107,9 @@
* @return A hash code value for this object.
*/
public int hashCode() {
- int hash = value;
+ int hash = 31 * 17 + value;
if (name != null) {
- hash ^= name.hashCode();
+ hash = 31 * hash + name.hashCode();
}
return hash;
}
Modified: felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/Unit.java
URL: http://svn.apache.org/viewvc/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/Unit.java?rev=797561&r1=797560&r2=797561&view=diff
==============================================================================
--- felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/Unit.java (original)
+++ felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/Unit.java Fri Jul 24 17:06:37 2009
@@ -1,7 +1,5 @@
/*
- * $Header: /cvshome/build/org.osgi.util.measurement/src/org/osgi/util/measurement/Unit.java,v 1.15 2006/06/16 16:31:34 hargrave Exp $
- *
- * Copyright (c) OSGi Alliance (2002, 2006). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 2008). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,7 +28,8 @@
* +63. Any operation which produces an exponent outside of this range will
* result in a <code>Unit</code> object with undefined exponents.
*
- * @version $Revision: 1.15 $
+ * @Immutable
+ * @version $Revision: 5715 $
*/
/*
* This local class maintains the information about units. It can calculate new
@@ -279,9 +278,11 @@
private final static Unit[] allUnits = new Unit[] {m, s, kg, K, A, mol,
cd, rad, m_s, m_s2, m2, m3, Hz, N, Pa, J, W, C, V, F, Ohm, S, Wb,
T, lx, Gy, kat, unity };
+
+ /* @GuardedBy("this") */
private static Hashtable base;
- private String name;
- private long type;
+ private final String name;
+ private final long type;
/**
* Creates a new <code>Unit</code> instance.
@@ -290,6 +291,9 @@
* @param type the type of the <code>Unit</code>
*/
private Unit(String name, long type) {
+ if (name == null) {
+ name = computeName(type);
+ }
this.name = name;
this.type = type;
//System.out.println( name + " " + Long.toHexString( type ) );
@@ -338,7 +342,7 @@
* @return This object's hash code.
*/
public int hashCode() {
- return (int) ((type >>> 32) ^ type);
+ return 31 * 17 + (int) (type ^ (type >>> 32));
}
/**
@@ -435,16 +439,12 @@
*
* @return the <code>Unit</code>
*/
- static Unit find(long type) {
+ static synchronized Unit find(long type) {
if (base == null) {
- synchronized (Unit.class) {
- if (base == null) {
- int size = allUnits.length;
- base = new Hashtable(size << 1);
- for (int i = 0; i < size; i++) {
- base.put(allUnits[i], allUnits[i]);
- }
- }
+ int size = allUnits.length;
+ base = new Hashtable(size << 1);
+ for (int i = 0; i < size; i++) {
+ base.put(allUnits[i], allUnits[i]);
}
}
Unit unit = new Unit(null, type);
@@ -462,43 +462,39 @@
* @return A <code>String</code> object representing the <code>Unit</code>
*/
public String toString() {
- if (name == null) {
- int m = (int) (((type >> m_SHIFT) & MASK) - ZERO);
- int s = (int) (((type >> s_SHIFT) & MASK) - ZERO);
- int kg = (int) (((type >> kg_SHIFT) & MASK) - ZERO);
- int K = (int) (((type >> K_SHIFT) & MASK) - ZERO);
- int A = (int) (((type >> A_SHIFT) & MASK) - ZERO);
- int mol = (int) (((type >> mol_SHIFT) & MASK) - ZERO);
- int cd = (int) (((type >> cd_SHIFT) & MASK) - ZERO);
- int rad = (int) (((type >> rad_SHIFT) & MASK) - ZERO);
- StringBuffer numerator = new StringBuffer();
- StringBuffer denominator = new StringBuffer();
- addSIname(m, "m", numerator, denominator);
- addSIname(s, "s", numerator, denominator);
- addSIname(kg, "kg", numerator, denominator);
- addSIname(K, "K", numerator, denominator);
- addSIname(A, "A", numerator, denominator);
- addSIname(mol, "mol", numerator, denominator);
- addSIname(cd, "cd", numerator, denominator);
- addSIname(rad, "rad", numerator, denominator);
- if (denominator.length() > 0) {
- if (numerator.length() == 0) {
- numerator.append("1");
- }
- numerator.append("/");
- numerator.append((Object) denominator); /*
- * we use (Object) to
- * avoid using new 1.4
- * method
- * append(StringBuffer)
- */
- }
- name = numerator.toString();
- }
return name;
}
- private void addSIname(int si, String name, StringBuffer numerator,
+ private static String computeName(long type) {
+ int m = (int) (((type >> m_SHIFT) & MASK) - ZERO);
+ int s = (int) (((type >> s_SHIFT) & MASK) - ZERO);
+ int kg = (int) (((type >> kg_SHIFT) & MASK) - ZERO);
+ int K = (int) (((type >> K_SHIFT) & MASK) - ZERO);
+ int A = (int) (((type >> A_SHIFT) & MASK) - ZERO);
+ int mol = (int) (((type >> mol_SHIFT) & MASK) - ZERO);
+ int cd = (int) (((type >> cd_SHIFT) & MASK) - ZERO);
+ int rad = (int) (((type >> rad_SHIFT) & MASK) - ZERO);
+ StringBuffer numerator = new StringBuffer();
+ StringBuffer denominator = new StringBuffer();
+ addSIname(m, "m", numerator, denominator);
+ addSIname(s, "s", numerator, denominator);
+ addSIname(kg, "kg", numerator, denominator);
+ addSIname(K, "K", numerator, denominator);
+ addSIname(A, "A", numerator, denominator);
+ addSIname(mol, "mol", numerator, denominator);
+ addSIname(cd, "cd", numerator, denominator);
+ addSIname(rad, "rad", numerator, denominator);
+ if (denominator.length() > 0) {
+ if (numerator.length() == 0) {
+ numerator.append("1");
+ }
+ numerator.append("/");
+ numerator.append(denominator.toString());
+ }
+ return numerator.toString();
+ }
+
+ private static void addSIname(int si, String name, StringBuffer numerator,
StringBuffer denominator) {
if (si != 0) {
StringBuffer sb = (si > 0) ? numerator : denominator;
Added: felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/package.html
URL: http://svn.apache.org/viewvc/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/package.html?rev=797561&view=auto
==============================================================================
--- felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/package.html (added)
+++ felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/package.html Fri Jul 24 17:06:37 2009
@@ -0,0 +1,10 @@
+<!-- $Revision: 6204 $ -->
+<BODY>
+<p>Measurement Package Version 1.0.
+<p>Bundles wishing to use this package must list the package
+in the Import-Package header of the bundle's manifest.
+For example:
+<pre>
+Import-Package: org.osgi.util.measurement; version="[1.0,2.0)"
+</pre>
+</BODY>
Added: felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/packageinfo?rev=797561&view=auto
==============================================================================
--- felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/packageinfo (added)
+++ felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/packageinfo Fri Jul 24 17:06:37 2009
@@ -0,0 +1 @@
+version 1.0.1
\ No newline at end of file
Modified: felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/mobile/UserPromptCondition.java
URL: http://svn.apache.org/viewvc/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/mobile/UserPromptCondition.java?rev=797561&r1=797560&r2=797561&view=diff
==============================================================================
--- felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/mobile/UserPromptCondition.java (original)
+++ felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/mobile/UserPromptCondition.java Fri Jul 24 17:06:37 2009
@@ -1,7 +1,5 @@
/*
- * $Header: /cvshome/build/org.osgi.util.mobile/src/org/osgi/util/mobile/UserPromptCondition.java,v 1.26 2006/07/10 08:18:30 pnagy Exp $
- *
- * Copyright (c) OSGi Alliance (2004, 2006). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2004, 2008). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Added: felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/mobile/package.html
URL: http://svn.apache.org/viewvc/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/mobile/package.html?rev=797561&view=auto
==============================================================================
--- felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/mobile/package.html (added)
+++ felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/mobile/package.html Fri Jul 24 17:06:37 2009
@@ -0,0 +1,10 @@
+<!-- $Revision: 6204 $ -->
+<BODY>
+<p>Mobile Conditions Package Version 1.0.
+<p>Bundles wishing to use this package must list the package
+in the Import-Package header of the bundle's manifest.
+For example:
+<pre>
+Import-Package: org.osgi.util.mobile; version="[1.0,2.0)"
+</pre>
+</BODY>
Added: felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/mobile/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/mobile/packageinfo?rev=797561&view=auto
==============================================================================
--- felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/mobile/packageinfo (added)
+++ felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/mobile/packageinfo Fri Jul 24 17:06:37 2009
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file
Modified: felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/Position.java
URL: http://svn.apache.org/viewvc/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/Position.java?rev=797561&r1=797560&r2=797561&view=diff
==============================================================================
--- felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/Position.java (original)
+++ felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/Position.java Fri Jul 24 17:06:37 2009
@@ -1,7 +1,5 @@
/*
- * $Header: /cvshome/build/org.osgi.util.position/src/org/osgi/util/position/Position.java,v 1.9 2006/07/12 21:21:35 hargrave Exp $
- *
- * Copyright (c) OSGi Alliance (2002, 2006). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 2009). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,16 +33,19 @@
* hashCode() because it is not clear how missing values should be handled. It
* is up to the user of a position to determine how best to compare two position
* objects. A <code>Position</code> object is immutable.
+ *
+ * @Immutable
+ * @version $Revision: 6860 $
*/
public class Position {
- private Measurement altitude;
- private Measurement longitude;
- private Measurement latitude;
- private Measurement speed;
- private Measurement track;
+ private final Measurement altitude;
+ private final Measurement longitude;
+ private final Measurement latitude;
+ private final Measurement speed;
+ private final Measurement track;
/**
- * Contructs a <code>Position</code> object with the given values.
+ * Constructs a <code>Position</code> object with the given values.
*
* @param lat a <code>Measurement</code> object specifying the latitude in
* radians, or null
@@ -63,33 +64,87 @@
if (!Unit.rad.equals(lat.getUnit())) {
throw new IllegalArgumentException("Invalid Latitude");
}
- this.latitude = lat;
}
if (lon != null) {
if (!Unit.rad.equals(lon.getUnit())) {
throw new IllegalArgumentException("Invalid Longitude");
}
- this.longitude = lon;
}
- normalizeLatLon();
if (alt != null) {
if (!Unit.m.equals(alt.getUnit())) {
throw new IllegalArgumentException("Invalid Altitude");
}
- this.altitude = alt;
}
if (speed != null) {
if (!Unit.m_s.equals(speed.getUnit())) {
throw new IllegalArgumentException("Invalid Speed");
}
- this.speed = speed;
}
if (track != null) {
if (!Unit.rad.equals(track.getUnit())) {
throw new IllegalArgumentException("Invalid Track");
}
- this.track = normalizeTrack(track);
}
+
+ /*
+ * Verify the longitude and latitude parameters so they fit the normal
+ * coordinate system. A latitude is between -90 (south) and +90 (north).
+ * A longitude is between -180 (Western hemisphere) and +180 (eastern
+ * hemisphere). This method first normalizes the latitude and longitude
+ * between +/- 180. If the |latitude| > 90, then the longitude is added
+ * 180 and the latitude is normalized to fit +/-90. (Example are with
+ * degrees though radians are used) <br> No normalization takes place
+ * when either lon or lat is null.
+ */
+ normalizeLatLon: {
+ if (lat == null || lon == null) {
+ break normalizeLatLon;
+ }
+ double dlat = lat.getValue();
+ double dlon = lon.getValue();
+ if (dlon >= -LON_RANGE && dlon < LON_RANGE && dlat >= -LAT_RANGE
+ && dlat <= LAT_RANGE) {
+ break normalizeLatLon;
+ }
+ dlon = normalize(dlon, LON_RANGE);
+ dlat = normalize(dlat, LAT_RANGE * 2.0D); // First over 180 degree
+ // Check if we have to move to other side of the earth
+ if (dlat > LAT_RANGE || dlat < -LAT_RANGE) {
+ dlon = normalize(dlon - LON_RANGE, LON_RANGE);
+ dlat = normalize((LAT_RANGE * 2.0D) - dlat, LAT_RANGE);
+ }
+ lon = new Measurement(dlon, lon.getError(), lon.getUnit(), lon
+ .getTime());
+ lat = new Measurement(dlat, lat.getError(), lat.getUnit(), lat
+ .getTime());
+ }
+
+ /*
+ * Normalize track to be a value such that: 0 <= value < +2PI. This
+ * corresponds to 0 deg to +360 deg. 0 is North, 0.5PI is East, PI is
+ * South, 1.5PI is West
+ */
+ normalizeTrack: {
+ if (track == null) {
+ break normalizeTrack;
+ }
+ double dtrack = track.getValue();
+ if ((0.0D <= dtrack) && (dtrack < TRACK_RANGE)) {
+ break normalizeTrack; /* value is already normalized */
+ }
+ dtrack %= TRACK_RANGE;
+ if (dtrack < 0.0D) {
+ dtrack += TRACK_RANGE;
+ }
+ track = new Measurement(dtrack, track.getError(), track.getUnit(),
+ track.getTime());
+ }
+
+ this.latitude = lat;
+ this.longitude = lon;
+ this.altitude = alt;
+ this.speed = speed;
+ this.track = track;
}
/**
@@ -153,37 +208,6 @@
private static final double LAT_RANGE = Math.PI / 2.0D;
/**
- * Verify the longitude and latitude parameters so they fit the normal
- * coordinate system. A latitude is between -90 (south) and +90 (north). A A
- * longitude is between -180 (Western hemisphere) and +180 (eastern
- * hemisphere). This method first normalizes the latitude and longitude
- * between +/- 180. If the |latitude| > 90, then the longitude is added 180
- * and the latitude is normalized to fit +/-90. (Example are with degrees
- * though radians are used) <br>
- * No normalization takes place when either lon or lat is null.
- */
- private void normalizeLatLon() {
- if (longitude == null || latitude == null)
- return;
- double dlon = longitude.getValue();
- double dlat = latitude.getValue();
- if (dlon >= -LON_RANGE && dlon < LON_RANGE && dlat >= -LAT_RANGE
- && dlat <= LAT_RANGE)
- return;
- dlon = normalize(dlon, LON_RANGE);
- dlat = normalize(dlat, LAT_RANGE * 2.0D); // First over 180 degree
- // Check if we have to move to other side of the earth
- if (dlat > LAT_RANGE || dlat < -LAT_RANGE) {
- dlon = normalize(dlon - LON_RANGE, LON_RANGE);
- dlat = normalize((LAT_RANGE * 2.0D) - dlat, LAT_RANGE);
- }
- longitude = new Measurement(dlon, longitude.getError(), longitude
- .getUnit(), longitude.getTime());
- latitude = new Measurement(dlat, latitude.getError(), latitude
- .getUnit(), latitude.getTime());
- }
-
- /**
* This function normalizes the a value according to a range. This is not
* simple modulo (as I thought when I started), but requires some special
* handling. For positive numbers we subtract 2*range from the number so
@@ -201,7 +225,7 @@
* @param value The value that needs adjusting
* @param range -range = < value < range
*/
- private double normalize(double value, double range) {
+ private static double normalize(double value, double range) {
double twiceRange = 2.0D * range;
while (value >= range) {
value -= twiceRange;
@@ -213,25 +237,4 @@
}
private static final double TRACK_RANGE = Math.PI * 2.0D;
-
- /**
- * Normalize track to be a value such that: 0 <= value < +2PI. This
- * corresponds to 0 deg to +360 deg. 0 is North 0.5*PI is East PI is South
- * 1.5*PI is West
- *
- * @param track Value to be normalized
- * @return Normalized value
- */
- private Measurement normalizeTrack(Measurement track) {
- double value = track.getValue();
- if ((0.0D <= value) && (value < TRACK_RANGE)) {
- return track; /* value is already normalized */
- }
- value %= TRACK_RANGE;
- if (value < 0.0D) {
- value += TRACK_RANGE;
- }
- return new Measurement(value, track.getError(), track.getUnit(), track
- .getTime());
- }
}
Added: felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/package.html
URL: http://svn.apache.org/viewvc/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/package.html?rev=797561&view=auto
==============================================================================
--- felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/package.html (added)
+++ felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/package.html Fri Jul 24 17:06:37 2009
@@ -0,0 +1,10 @@
+<!-- $Revision: 6204 $ -->
+<BODY>
+<p>Position Package Version 1.0.
+<p>Bundles wishing to use this package must list the package
+in the Import-Package header of the bundle's manifest.
+For example:
+<pre>
+Import-Package: org.osgi.util.position; version="[1.0,2.0)"
+</pre>
+</BODY>
Added: felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/packageinfo?rev=797561&view=auto
==============================================================================
--- felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/packageinfo (added)
+++ felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/packageinfo Fri Jul 24 17:06:37 2009
@@ -0,0 +1 @@
+version 1.0.1
\ No newline at end of file
Added: felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/tracker/AbstractTracked.java
URL: http://svn.apache.org/viewvc/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/tracker/AbstractTracked.java?rev=797561&view=auto
==============================================================================
--- felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/tracker/AbstractTracked.java (added)
+++ felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/tracker/AbstractTracked.java Fri Jul 24 17:06:37 2009
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) OSGi Alliance (2007, 2008). All Rights Reserved.
+ *
+ * Licensed 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.osgi.util.tracker;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Abstract class to track items. If a Tracker is reused (closed then reopened),
+ * then a new AbstractTracked object is used. This class acts a map of tracked
+ * item -> customized object. Subclasses of this class will act as the listener
+ * object for the tracker. This class is used to synchronize access to the
+ * tracked items. This is not a public class. It is only for use by the
+ * implementation of the Tracker class.
+ *
+ * @ThreadSafe
+ * @version $Revision: 5871 $
+ * @since 1.4
+ */
+abstract class AbstractTracked {
+ /* set this to true to compile in debug messages */
+ static final boolean DEBUG = false;
+
+ /**
+ * Map of tracked items to customized objects.
+ *
+ * @GuardedBy this
+ */
+ private final Map tracked;
+
+ /**
+ * Modification count. This field is initialized to zero and incremented by
+ * modified.
+ *
+ * @GuardedBy this
+ */
+ private int trackingCount;
+
+ /**
+ * List of items in the process of being added. This is used to deal with
+ * nesting of events. Since events may be synchronously delivered, events
+ * can be nested. For example, when processing the adding of a service and
+ * the customizer causes the service to be unregistered, notification to the
+ * nested call to untrack that the service was unregistered can be made to
+ * the track method.
+ *
+ * Since the ArrayList implementation is not synchronized, all access to
+ * this list must be protected by the same synchronized object for
+ * thread-safety.
+ *
+ * @GuardedBy this
+ */
+ private final List adding;
+
+ /**
+ * true if the tracked object is closed.
+ *
+ * This field is volatile because it is set by one thread and read by
+ * another.
+ */
+ volatile boolean closed;
+
+ /**
+ * Initial list of items for the tracker. This is used to correctly process
+ * the initial items which could be modified before they are tracked. This
+ * is necessary since the initial set of tracked items are not "announced"
+ * by events and therefore the event which makes the item untracked could be
+ * delivered before we track the item.
+ *
+ * An item must not be in both the initial and adding lists at the same
+ * time. An item must be moved from the initial list to the adding list
+ * "atomically" before we begin tracking it.
+ *
+ * Since the LinkedList implementation is not synchronized, all access to
+ * this list must be protected by the same synchronized object for
+ * thread-safety.
+ *
+ * @GuardedBy this
+ */
+ private final LinkedList initial;
+
+ /**
+ * AbstractTracked constructor.
+ */
+ AbstractTracked() {
+ tracked = new HashMap();
+ trackingCount = 0;
+ adding = new ArrayList(6);
+ initial = new LinkedList();
+ closed = false;
+ }
+
+ /**
+ * Set initial list of items into tracker before events begin to be
+ * received.
+ *
+ * This method must be called from Tracker's open method while synchronized
+ * on this object in the same synchronized block as the add listener call.
+ *
+ * @param list The initial list of items to be tracked. <code>null</code>
+ * entries in the list are ignored.
+ * @GuardedBy this
+ */
+ void setInitial(Object[] list) {
+ if (list == null) {
+ return;
+ }
+ int size = list.length;
+ for (int i = 0; i < size; i++) {
+ Object item = list[i];
+ if (item == null) {
+ continue;
+ }
+ if (DEBUG) {
+ System.out.println("AbstractTracked.setInitial: " + item); //$NON-NLS-1$
+ }
+ initial.add(item);
+ }
+ }
+
+ /**
+ * Track the initial list of items. This is called after events can begin to
+ * be received.
+ *
+ * This method must be called from Tracker's open method while not
+ * synchronized on this object after the add listener call.
+ *
+ */
+ void trackInitial() {
+ while (true) {
+ Object item;
+ synchronized (this) {
+ if (closed || (initial.size() == 0)) {
+ /*
+ * if there are no more initial items
+ */
+ return; /* we are done */
+ }
+ /*
+ * move the first item from the initial list to the adding list
+ * within this synchronized block.
+ */
+ item = initial.removeFirst();
+ if (tracked.get(item) != null) {
+ /* if we are already tracking this item */
+ if (DEBUG) {
+ System.out
+ .println("AbstractTracked.trackInitial[already tracked]: " + item); //$NON-NLS-1$
+ }
+ continue; /* skip this item */
+ }
+ if (adding.contains(item)) {
+ /*
+ * if this item is already in the process of being added.
+ */
+ if (DEBUG) {
+ System.out
+ .println("AbstractTracked.trackInitial[already adding]: " + item); //$NON-NLS-1$
+ }
+ continue; /* skip this item */
+ }
+ adding.add(item);
+ }
+ if (DEBUG) {
+ System.out.println("AbstractTracked.trackInitial: " + item); //$NON-NLS-1$
+ }
+ trackAdding(item, null); /*
+ * Begin tracking it. We call trackAdding
+ * since we have already put the item in the
+ * adding list.
+ */
+ }
+ }
+
+ /**
+ * Called by the owning Tracker object when it is closed.
+ */
+ void close() {
+ closed = true;
+ }
+
+ /**
+ * Begin to track an item.
+ *
+ * @param item Item to be tracked.
+ * @param related Action related object.
+ */
+ void track(final Object item, final Object related) {
+ final Object object;
+ synchronized (this) {
+ if (closed) {
+ return;
+ }
+ object = tracked.get(item);
+ if (object == null) { /* we are not tracking the item */
+ if (adding.contains(item)) {
+ /* if this item is already in the process of being added. */
+ if (DEBUG) {
+ System.out
+ .println("AbstractTracked.track[already adding]: " + item); //$NON-NLS-1$
+ }
+ return;
+ }
+ adding.add(item); /* mark this item is being added */
+ }
+ else { /* we are currently tracking this item */
+ if (DEBUG) {
+ System.out
+ .println("AbstractTracked.track[modified]: " + item); //$NON-NLS-1$
+ }
+ modified(); /* increment modification count */
+ }
+ }
+
+ if (object == null) { /* we are not tracking the item */
+ trackAdding(item, related);
+ }
+ else {
+ /* Call customizer outside of synchronized region */
+ customizerModified(item, related, object);
+ /*
+ * If the customizer throws an unchecked exception, it is safe to
+ * let it propagate
+ */
+ }
+ }
+
+ /**
+ * Common logic to add an item to the tracker used by track and
+ * trackInitial. The specified item must have been placed in the adding list
+ * before calling this method.
+ *
+ * @param item Item to be tracked.
+ * @param related Action related object.
+ */
+ private void trackAdding(final Object item, final Object related) {
+ if (DEBUG) {
+ System.out.println("AbstractTracked.trackAdding: " + item); //$NON-NLS-1$
+ }
+ Object object = null;
+ boolean becameUntracked = false;
+ /* Call customizer outside of synchronized region */
+ try {
+ object = customizerAdding(item, related);
+ /*
+ * If the customizer throws an unchecked exception, it will
+ * propagate after the finally
+ */
+ }
+ finally {
+ synchronized (this) {
+ if (adding.remove(item) && !closed) {
+ /*
+ * if the item was not untracked during the customizer
+ * callback
+ */
+ if (object != null) {
+ tracked.put(item, object);
+ modified(); /* increment modification count */
+ notifyAll(); /* notify any waiters */
+ }
+ }
+ else {
+ becameUntracked = true;
+ }
+ }
+ }
+ /*
+ * The item became untracked during the customizer callback.
+ */
+ if (becameUntracked && (object != null)) {
+ if (DEBUG) {
+ System.out
+ .println("AbstractTracked.trackAdding[removed]: " + item); //$NON-NLS-1$
+ }
+ /* Call customizer outside of synchronized region */
+ customizerRemoved(item, related, object);
+ /*
+ * If the customizer throws an unchecked exception, it is safe to
+ * let it propagate
+ */
+ }
+ }
+
+ /**
+ * Discontinue tracking the item.
+ *
+ * @param item Item to be untracked.
+ * @param related Action related object.
+ */
+ void untrack(final Object item, final Object related) {
+ final Object object;
+ synchronized (this) {
+ if (initial.remove(item)) { /*
+ * if this item is already in the list
+ * of initial references to process
+ */
+ if (DEBUG) {
+ System.out
+ .println("AbstractTracked.untrack[removed from initial]: " + item); //$NON-NLS-1$
+ }
+ return; /*
+ * we have removed it from the list and it will not be
+ * processed
+ */
+ }
+
+ if (adding.remove(item)) { /*
+ * if the item is in the process of
+ * being added
+ */
+ if (DEBUG) {
+ System.out
+ .println("AbstractTracked.untrack[being added]: " + item); //$NON-NLS-1$
+ }
+ return; /*
+ * in case the item is untracked while in the process of
+ * adding
+ */
+ }
+ object = tracked.remove(item); /*
+ * must remove from tracker before
+ * calling customizer callback
+ */
+ if (object == null) { /* are we actually tracking the item */
+ return;
+ }
+ modified(); /* increment modification count */
+ }
+ if (DEBUG) {
+ System.out.println("AbstractTracked.untrack[removed]: " + item); //$NON-NLS-1$
+ }
+ /* Call customizer outside of synchronized region */
+ customizerRemoved(item, related, object);
+ /*
+ * If the customizer throws an unchecked exception, it is safe to let it
+ * propagate
+ */
+ }
+
+ /**
+ * Returns the number of tracked items.
+ *
+ * @return The number of tracked items.
+ *
+ * @GuardedBy this
+ */
+ int size() {
+ return tracked.size();
+ }
+
+ /**
+ * Return the customized object for the specified item
+ *
+ * @param item The item to lookup in the map
+ * @return The customized object for the specified item.
+ *
+ * @GuardedBy this
+ */
+ Object getCustomizedObject(final Object item) {
+ return tracked.get(item);
+ }
+
+ /**
+ * Return the list of tracked items.
+ *
+ * @param list An array to contain the tracked items.
+ * @return The specified list if it is large enough to hold the tracked
+ * items or a new array large enough to hold the tracked items.
+ * @GuardedBy this
+ */
+ Object[] getTracked(final Object[] list) {
+ return tracked.keySet().toArray(list);
+ }
+
+ /**
+ * Increment the modification count. If this method is overridden, the
+ * overriding method MUST call this method to increment the tracking count.
+ *
+ * @GuardedBy this
+ */
+ void modified() {
+ trackingCount++;
+ }
+
+ /**
+ * Returns the tracking count for this <code>ServiceTracker</code> object.
+ *
+ * The tracking count is initialized to 0 when this object is opened. Every
+ * time an item is added, modified or removed from this object the tracking
+ * count is incremented.
+ *
+ * @GuardedBy this
+ * @return The tracking count for this object.
+ */
+ int getTrackingCount() {
+ return trackingCount;
+ }
+
+ /**
+ * Call the specific customizer adding method. This method must not be
+ * called while synchronized on this object.
+ *
+ * @param item Item to be tracked.
+ * @param related Action related object.
+ * @return Customized object for the tracked item or <code>null</code> if
+ * the item is not to be tracked.
+ */
+ abstract Object customizerAdding(final Object item, final Object related);
+
+ /**
+ * Call the specific customizer modified method. This method must not be
+ * called while synchronized on this object.
+ *
+ * @param item Tracked item.
+ * @param related Action related object.
+ * @param object Customized object for the tracked item.
+ */
+ abstract void customizerModified(final Object item, final Object related,
+ final Object object);
+
+ /**
+ * Call the specific customizer removed method. This method must not be
+ * called while synchronized on this object.
+ *
+ * @param item Tracked item.
+ * @param related Action related object.
+ * @param object Customized object for the tracked item.
+ */
+ abstract void customizerRemoved(final Object item, final Object related,
+ final Object object);
+}
Added: felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/tracker/BundleTracker.java
URL: http://svn.apache.org/viewvc/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/tracker/BundleTracker.java?rev=797561&view=auto
==============================================================================
--- felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/tracker/BundleTracker.java (added)
+++ felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/tracker/BundleTracker.java Fri Jul 24 17:06:37 2009
@@ -0,0 +1,471 @@
+/*
+ * Copyright (c) OSGi Alliance (2007, 2008). All Rights Reserved.
+ *
+ * Licensed 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.osgi.util.tracker;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.SynchronousBundleListener;
+
+/**
+ * The <code>BundleTracker</code> class simplifies tracking bundles much like
+ * the <code>ServiceTracker</code> simplifies tracking services.
+ * <p>
+ * A <code>BundleTracker</code> is constructed with state criteria and a
+ * <code>BundleTrackerCustomizer</code> object. A <code>BundleTracker</code> can
+ * use the <code>BundleTrackerCustomizer</code> to select which bundles are
+ * tracked and to create a customized object to be tracked with the bundle. The
+ * <code>BundleTracker</code> can then be opened to begin tracking all bundles
+ * whose state matches the specified state criteria.
+ * <p>
+ * The <code>getBundles</code> method can be called to get the
+ * <code>Bundle</code> objects of the bundles being tracked. The
+ * <code>getObject</code> method can be called to get the customized object for
+ * a tracked bundle.
+ * <p>
+ * The <code>BundleTracker</code> class is thread-safe. It does not call a
+ * <code>BundleTrackerCustomizer</code> while holding any locks.
+ * <code>BundleTrackerCustomizer</code> implementations must also be
+ * thread-safe.
+ *
+ * @ThreadSafe
+ * @version $Revision: 5894 $
+ * @since 1.4
+ */
+public class BundleTracker implements BundleTrackerCustomizer {
+ /* set this to true to compile in debug messages */
+ static final boolean DEBUG = false;
+
+ /**
+ * The Bundle Context used by this <code>BundleTracker</code>.
+ */
+ protected final BundleContext context;
+
+ /**
+ * The <code>BundleTrackerCustomizer</code> object for this tracker.
+ */
+ final BundleTrackerCustomizer customizer;
+
+ /**
+ * Tracked bundles: <code>Bundle</code> object -> customized Object and
+ * <code>BundleListener</code> object
+ */
+ private volatile Tracked tracked;
+
+ /**
+ * Accessor method for the current Tracked object. This method is only
+ * intended to be used by the unsynchronized methods which do not modify the
+ * tracked field.
+ *
+ * @return The current Tracked object.
+ */
+ private Tracked tracked() {
+ return tracked;
+ }
+
+ /**
+ * State mask for bundles being tracked. This field contains the ORed values
+ * of the bundle states being tracked.
+ */
+ final int mask;
+
+ /**
+ * Create a <code>BundleTracker</code> for bundles whose state is present in
+ * the specified state mask.
+ *
+ * <p>
+ * Bundles whose state is present on the specified state mask will be
+ * tracked by this <code>BundleTracker</code>.
+ *
+ * @param context The <code>BundleContext</code> against which the tracking
+ * is done.
+ * @param stateMask The bit mask of the <code>OR</code>ing of the bundle
+ * states to be tracked.
+ * @param customizer The customizer object to call when bundles are added,
+ * modified, or removed in this <code>BundleTracker</code>. If
+ * customizer is <code>null</code>, then this
+ * <code>BundleTracker</code> will be used as the
+ * <code>BundleTrackerCustomizer</code> and this
+ * <code>BundleTracker</code> will call the
+ * <code>BundleTrackerCustomizer</code> methods on itself.
+ * @see Bundle#getState()
+ */
+ public BundleTracker(BundleContext context, int stateMask,
+ BundleTrackerCustomizer customizer) {
+ this.context = context;
+ this.mask = stateMask;
+ this.customizer = (customizer == null) ? this : customizer;
+ }
+
+ /**
+ * Open this <code>BundleTracker</code> and begin tracking bundles.
+ *
+ * <p>
+ * Bundle which match the state criteria specified when this
+ * <code>BundleTracker</code> was created are now tracked by this
+ * <code>BundleTracker</code>.
+ *
+ * @throws java.lang.IllegalStateException If the <code>BundleContext</code>
+ * with which this <code>BundleTracker</code> was created is no
+ * longer valid.
+ * @throws java.lang.SecurityException If the caller and this class do not
+ * have the appropriate
+ * <code>AdminPermission[context bundle,LISTENER]</code>, and the
+ * Java Runtime Environment supports permissions.
+ */
+ public void open() {
+ final Tracked t;
+ synchronized (this) {
+ if (tracked != null) {
+ return;
+ }
+ if (DEBUG) {
+ System.out.println("BundleTracker.open"); //$NON-NLS-1$
+ }
+ t = new Tracked();
+ synchronized (t) {
+ context.addBundleListener(t);
+ Bundle[] bundles = context.getBundles();
+ if (bundles != null) {
+ int length = bundles.length;
+ for (int i = 0; i < length; i++) {
+ int state = bundles[i].getState();
+ if ((state & mask) == 0) {
+ /* null out bundles whose states are not interesting */
+ bundles[i] = null;
+ }
+ }
+ /* set tracked with the initial bundles */
+ t.setInitial(bundles);
+ }
+ }
+ tracked = t;
+ }
+ /* Call tracked outside of synchronized region */
+ t.trackInitial(); /* process the initial references */
+ }
+
+ /**
+ * Close this <code>BundleTracker</code>.
+ *
+ * <p>
+ * This method should be called when this <code>BundleTracker</code> should
+ * end the tracking of bundles.
+ *
+ * <p>
+ * This implementation calls {@link #getBundles()} to get the list of
+ * tracked bundles to remove.
+ */
+ public void close() {
+ final Bundle[] bundles;
+ final Tracked outgoing;
+ synchronized (this) {
+ outgoing = tracked;
+ if (outgoing == null) {
+ return;
+ }
+ if (DEBUG) {
+ System.out.println("BundleTracker.close"); //$NON-NLS-1$
+ }
+ outgoing.close();
+ bundles = getBundles();
+ tracked = null;
+ try {
+ context.removeBundleListener(outgoing);
+ }
+ catch (IllegalStateException e) {
+ /* In case the context was stopped. */
+ }
+ }
+ if (bundles != null) {
+ for (int i = 0; i < bundles.length; i++) {
+ outgoing.untrack(bundles[i], null);
+ }
+ }
+ }
+
+ /**
+ * Default implementation of the
+ * <code>BundleTrackerCustomizer.addingBundle</code> method.
+ *
+ * <p>
+ * This method is only called when this <code>BundleTracker</code> has been
+ * constructed with a <code>null BundleTrackerCustomizer</code> argument.
+ *
+ * <p>
+ * This implementation simply returns the specified <code>Bundle</code>.
+ *
+ * <p>
+ * This method can be overridden in a subclass to customize the object to be
+ * tracked for the bundle being added.
+ *
+ * @param bundle The <code>Bundle</code> being added to this
+ * <code>BundleTracker</code> object.
+ * @param event The bundle event which caused this customizer method to be
+ * called or <code>null</code> if there is no bundle event associated
+ * with the call to this method.
+ * @return The specified bundle.
+ * @see BundleTrackerCustomizer#addingBundle(Bundle, BundleEvent)
+ */
+ public Object addingBundle(Bundle bundle, BundleEvent event) {
+ return bundle;
+ }
+
+ /**
+ * Default implementation of the
+ * <code>BundleTrackerCustomizer.modifiedBundle</code> method.
+ *
+ * <p>
+ * This method is only called when this <code>BundleTracker</code> has been
+ * constructed with a <code>null BundleTrackerCustomizer</code> argument.
+ *
+ * <p>
+ * This implementation does nothing.
+ *
+ * @param bundle The <code>Bundle</code> whose state has been modified.
+ * @param event The bundle event which caused this customizer method to be
+ * called or <code>null</code> if there is no bundle event associated
+ * with the call to this method.
+ * @param object The customized object for the specified Bundle.
+ * @see BundleTrackerCustomizer#modifiedBundle(Bundle, BundleEvent, Object)
+ */
+ public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+ /* do nothing */
+ }
+
+ /**
+ * Default implementation of the
+ * <code>BundleTrackerCustomizer.removedBundle</code> method.
+ *
+ * <p>
+ * This method is only called when this <code>BundleTracker</code> has been
+ * constructed with a <code>null BundleTrackerCustomizer</code> argument.
+ *
+ * <p>
+ * This implementation does nothing.
+ *
+ * @param bundle The <code>Bundle</code> being removed.
+ * @param event The bundle event which caused this customizer method to be
+ * called or <code>null</code> if there is no bundle event associated
+ * with the call to this method.
+ * @param object The customized object for the specified bundle.
+ * @see BundleTrackerCustomizer#removedBundle(Bundle, BundleEvent, Object)
+ */
+ public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+ /* do nothing */
+ }
+
+ /**
+ * Return an array of <code>Bundle</code>s for all bundles being tracked by
+ * this <code>BundleTracker</code>.
+ *
+ * @return An array of <code>Bundle</code>s or <code>null</code> if no
+ * bundles are being tracked.
+ */
+ public Bundle[] getBundles() {
+ final Tracked t = tracked();
+ if (t == null) { /* if BundleTracker is not open */
+ return null;
+ }
+ synchronized (t) {
+ int length = t.size();
+ if (length == 0) {
+ return null;
+ }
+ return (Bundle[]) t.getTracked(new Bundle[length]);
+ }
+ }
+
+ /**
+ * Returns the customized object for the specified <code>Bundle</code> if
+ * the specified bundle is being tracked by this <code>BundleTracker</code>.
+ *
+ * @param bundle The <code>Bundle</code> being tracked.
+ * @return The customized object for the specified <code>Bundle</code> or
+ * <code>null</code> if the specified <code>Bundle</code> is not
+ * being tracked.
+ */
+ public Object getObject(Bundle bundle) {
+ final Tracked t = tracked();
+ if (t == null) { /* if BundleTracker is not open */
+ return null;
+ }
+ synchronized (t) {
+ return t.getCustomizedObject(bundle);
+ }
+ }
+
+ /**
+ * Remove a bundle from this <code>BundleTracker</code>.
+ *
+ * The specified bundle will be removed from this <code>BundleTracker</code>
+ * . If the specified bundle was being tracked then the
+ * <code>BundleTrackerCustomizer.removedBundle</code> method will be called
+ * for that bundle.
+ *
+ * @param bundle The <code>Bundle</code> to be removed.
+ */
+ public void remove(Bundle bundle) {
+ final Tracked t = tracked();
+ if (t == null) { /* if BundleTracker is not open */
+ return;
+ }
+ t.untrack(bundle, null);
+ }
+
+ /**
+ * Return the number of bundles being tracked by this
+ * <code>BundleTracker</code>.
+ *
+ * @return The number of bundles being tracked.
+ */
+ public int size() {
+ final Tracked t = tracked();
+ if (t == null) { /* if BundleTracker is not open */
+ return 0;
+ }
+ synchronized (t) {
+ return t.size();
+ }
+ }
+
+ /**
+ * Returns the tracking count for this <code>BundleTracker</code>.
+ *
+ * The tracking count is initialized to 0 when this
+ * <code>BundleTracker</code> is opened. Every time a bundle is added,
+ * modified or removed from this <code>BundleTracker</code> the tracking
+ * count is incremented.
+ *
+ * <p>
+ * The tracking count can be used to determine if this
+ * <code>BundleTracker</code> has added, modified or removed a bundle by
+ * comparing a tracking count value previously collected with the current
+ * tracking count value. If the value has not changed, then no bundle has
+ * been added, modified or removed from this <code>BundleTracker</code>
+ * since the previous tracking count was collected.
+ *
+ * @return The tracking count for this <code>BundleTracker</code> or -1 if
+ * this <code>BundleTracker</code> is not open.
+ */
+ public int getTrackingCount() {
+ final Tracked t = tracked();
+ if (t == null) { /* if BundleTracker is not open */
+ return -1;
+ }
+ synchronized (t) {
+ return t.getTrackingCount();
+ }
+ }
+
+ /**
+ * Inner class which subclasses AbstractTracked. This class is the
+ * <code>SynchronousBundleListener</code> object for the tracker.
+ *
+ * @ThreadSafe
+ * @since 1.4
+ */
+ class Tracked extends AbstractTracked implements SynchronousBundleListener {
+ /**
+ * Tracked constructor.
+ */
+ Tracked() {
+ super();
+ }
+
+ /**
+ * <code>BundleListener</code> method for the <code>BundleTracker</code>
+ * class. This method must NOT be synchronized to avoid deadlock
+ * potential.
+ *
+ * @param event <code>BundleEvent</code> object from the framework.
+ */
+ public void bundleChanged(final BundleEvent event) {
+ /*
+ * Check if we had a delayed call (which could happen when we
+ * close).
+ */
+ if (closed) {
+ return;
+ }
+ final Bundle bundle = event.getBundle();
+ final int state = bundle.getState();
+ if (DEBUG) {
+ System.out
+ .println("BundleTracker.Tracked.bundleChanged[" + state + "]: " + bundle); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if ((state & mask) != 0) {
+ track(bundle, event);
+ /*
+ * If the customizer throws an unchecked exception, it is safe
+ * to let it propagate
+ */
+ }
+ else {
+ untrack(bundle, event);
+ /*
+ * If the customizer throws an unchecked exception, it is safe
+ * to let it propagate
+ */
+ }
+ }
+
+ /**
+ * Call the specific customizer adding method. This method must not be
+ * called while synchronized on this object.
+ *
+ * @param item Item to be tracked.
+ * @param related Action related object.
+ * @return Customized object for the tracked item or <code>null</code>
+ * if the item is not to be tracked.
+ */
+ Object customizerAdding(final Object item,
+ final Object related) {
+ return customizer
+ .addingBundle((Bundle) item, (BundleEvent) related);
+ }
+
+ /**
+ * Call the specific customizer modified method. This method must not be
+ * called while synchronized on this object.
+ *
+ * @param item Tracked item.
+ * @param related Action related object.
+ * @param object Customized object for the tracked item.
+ */
+ void customizerModified(final Object item,
+ final Object related, final Object object) {
+ customizer.modifiedBundle((Bundle) item, (BundleEvent) related,
+ object);
+ }
+
+ /**
+ * Call the specific customizer removed method. This method must not be
+ * called while synchronized on this object.
+ *
+ * @param item Tracked item.
+ * @param related Action related object.
+ * @param object Customized object for the tracked item.
+ */
+ void customizerRemoved(final Object item,
+ final Object related, final Object object) {
+ customizer.removedBundle((Bundle) item, (BundleEvent) related,
+ object);
+ }
+ }
+}
Added: felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/tracker/BundleTrackerCustomizer.java
URL: http://svn.apache.org/viewvc/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/tracker/BundleTrackerCustomizer.java?rev=797561&view=auto
==============================================================================
--- felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/tracker/BundleTrackerCustomizer.java (added)
+++ felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/tracker/BundleTrackerCustomizer.java Fri Jul 24 17:06:37 2009
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) OSGi Alliance (2007, 2008). All Rights Reserved.
+ *
+ * Licensed 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.osgi.util.tracker;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+
+/**
+ * The <code>BundleTrackerCustomizer</code> interface allows a
+ * <code>BundleTracker</code> to customize the <code>Bundle</code>s that are
+ * tracked. A <code>BundleTrackerCustomizer</code> is called when a bundle is
+ * being added to a <code>BundleTracker</code>. The
+ * <code>BundleTrackerCustomizer</code> can then return an object for the
+ * tracked bundle. A <code>BundleTrackerCustomizer</code> is also called when a
+ * tracked bundle is modified or has been removed from a
+ * <code>BundleTracker</code>.
+ *
+ * <p>
+ * The methods in this interface may be called as the result of a
+ * <code>BundleEvent</code> being received by a <code>BundleTracker</code>.
+ * Since <code>BundleEvent</code>s are received synchronously by the
+ * <code>BundleTracker</code>, it is highly recommended that implementations of
+ * these methods do not alter bundle states while being synchronized on any
+ * object.
+ *
+ * <p>
+ * The <code>BundleTracker</code> class is thread-safe. It does not call a
+ * <code>BundleTrackerCustomizer</code> while holding any locks.
+ * <code>BundleTrackerCustomizer</code> implementations must also be
+ * thread-safe.
+ *
+ * @ThreadSafe
+ * @version $Revision: 5874 $
+ * @since 1.4
+ */
+public interface BundleTrackerCustomizer {
+ /**
+ * A bundle is being added to the <code>BundleTracker</code>.
+ *
+ * <p>
+ * This method is called before a bundle which matched the search parameters
+ * of the <code>BundleTracker</code> is added to the
+ * <code>BundleTracker</code>. This method should return the object to be
+ * tracked for the specified <code>Bundle</code>. The returned object is
+ * stored in the <code>BundleTracker</code> and is available from the
+ * {@link BundleTracker#getObject(Bundle) getObject} method.
+ *
+ * @param bundle The <code>Bundle</code> being added to the
+ * <code>BundleTracker</code>.
+ * @param event The bundle event which caused this customizer method to be
+ * called or <code>null</code> if there is no bundle event associated
+ * with the call to this method.
+ * @return The object to be tracked for the specified <code>Bundle</code>
+ * object or <code>null</code> if the specified <code>Bundle</code>
+ * object should not be tracked.
+ */
+ public Object addingBundle(Bundle bundle, BundleEvent event);
+
+ /**
+ * A bundle tracked by the <code>BundleTracker</code> has been modified.
+ *
+ * <p>
+ * This method is called when a bundle being tracked by the
+ * <code>BundleTracker</code> has had its state modified.
+ *
+ * @param bundle The <code>Bundle</code> whose state has been modified.
+ * @param event The bundle event which caused this customizer method to be
+ * called or <code>null</code> if there is no bundle event associated
+ * with the call to this method.
+ * @param object The tracked object for the specified bundle.
+ */
+ public void modifiedBundle(Bundle bundle, BundleEvent event,
+ Object object);
+
+ /**
+ * A bundle tracked by the <code>BundleTracker</code> has been removed.
+ *
+ * <p>
+ * This method is called after a bundle is no longer being tracked by the
+ * <code>BundleTracker</code>.
+ *
+ * @param bundle The <code>Bundle</code> that has been removed.
+ * @param event The bundle event which caused this customizer method to be
+ * called or <code>null</code> if there is no bundle event associated
+ * with the call to this method.
+ * @param object The tracked object for the specified bundle.
+ */
+ public void removedBundle(Bundle bundle, BundleEvent event,
+ Object object);
+}