Update OSGi R4.3 API. Fix a few bugs. (FELIX-2950)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1124290 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/FilterImpl.java b/framework/src/main/java/org/apache/felix/framework/FilterImpl.java
index a64ba1f..b25121f 100644
--- a/framework/src/main/java/org/apache/felix/framework/FilterImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/FilterImpl.java
@@ -54,7 +54,14 @@
public boolean match(ServiceReference sr)
{
- return CapabilitySet.matches((ServiceReferenceImpl) sr, m_filter);
+ if (sr instanceof ServiceReferenceImpl)
+ {
+ return CapabilitySet.matches((ServiceReferenceImpl) sr, m_filter);
+ }
+ else
+ {
+ return CapabilitySet.matches(new ServiceReferenceCapability(sr), m_filter);
+ }
}
public boolean match(Dictionary<String, ? > dctnr)
@@ -69,7 +76,7 @@
public boolean matches(Map<String, ?> map)
{
- throw new UnsupportedOperationException("Not supported yet.");
+ return CapabilitySet.matches(new DictionaryCapability(map), m_filter);
}
public boolean equals(Object o)
@@ -91,6 +98,12 @@
{
private final Map m_map;
+ public DictionaryCapability(Map map)
+ {
+ super(null, null, Collections.EMPTY_MAP, Collections.EMPTY_MAP);
+ m_map = map;
+ }
+
public DictionaryCapability(Dictionary dict, boolean caseSensitive)
{
super(null, null, Collections.EMPTY_MAP, Collections.EMPTY_MAP);
@@ -128,6 +141,53 @@
}
}
+ static class ServiceReferenceCapability extends BundleCapabilityImpl
+ {
+ private final ServiceReference m_sr;
+ private final Map<String, Object> m_attrs;
+
+ public ServiceReferenceCapability(ServiceReference sr)
+ {
+ super(null, null, Collections.EMPTY_MAP, Collections.EMPTY_MAP);
+ m_sr = sr;
+ m_attrs = new StringMap(false);
+ for (String key : m_sr.getPropertyKeys())
+ {
+ m_attrs.put(key, m_sr.getProperty(key));
+ }
+ }
+
+ @Override
+ public BundleRevision getRevision()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public String getNamespace()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Map<String, String> getDirectives()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Map<String, Object> getAttributes()
+ {
+ return m_attrs;
+ }
+
+ @Override
+ public List<String> getUses()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }
+
private static class DictionaryMap implements Map
{
private final StringMap m_map;
diff --git a/framework/src/main/java/org/osgi/framework/FrameworkUtil.java b/framework/src/main/java/org/osgi/framework/FrameworkUtil.java
index 0e89999..ec0af1e 100644
--- a/framework/src/main/java/org/osgi/framework/FrameworkUtil.java
+++ b/framework/src/main/java/org/osgi/framework/FrameworkUtil.java
@@ -16,20 +16,11 @@
package org.osgi.framework;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.util.AbstractMap;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Dictionary;
-import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
import javax.security.auth.x500.X500Principal;
@@ -76,7 +67,7 @@
*/
public static Filter createFilter(String filter)
throws InvalidSyntaxException {
- return FilterImpl.newInstance(filter);
+ return new org.apache.felix.framework.FilterImpl(filter);
}
/**
@@ -221,1518 +212,6 @@
}
/**
- * RFC 1960-based Filter. Filter objects can be created by calling the
- * constructor with the desired filter string. A Filter object can be called
- * numerous times to determine if the match argument matches the filter
- * string that was used to create the Filter object.
- *
- * <p>
- * The syntax of a filter string is the string representation of LDAP search
- * filters as defined in RFC 1960: <i>A String Representation of LDAP Search
- * Filters</i> (available at http://www.ietf.org/rfc/rfc1960.txt). It should
- * be noted that RFC 2254: <i>A String Representation of LDAP Search
- * Filters</i> (available at http://www.ietf.org/rfc/rfc2254.txt) supersedes
- * RFC 1960 but only adds extensible matching and is not applicable for this
- * API.
- *
- * <p>
- * The string representation of an LDAP search filter is defined by the
- * following grammar. It uses a prefix format.
- *
- * <pre>
- * <filter> ::= '(' <filtercomp> ')'
- * <filtercomp> ::= <and> | <or> | <not> | <item>
- * <and> ::= '&' <filterlist>
- * <or> ::= '|' <filterlist>
- * <not> ::= '!' <filter>
- * <filterlist> ::= <filter> | <filter> <filterlist>
- * <item> ::= <simple> | <present> | <substring>
- * <simple> ::= <attr> <filtertype> <value>
- * <filtertype> ::= <equal> | <approx> | <greater> | <less>
- * <equal> ::= '='
- * <approx> ::= '˜='
- * <greater> ::= '>='
- * <less> ::= '<='
- * <present> ::= <attr> '=*'
- * <substring> ::= <attr> '=' <initial> <any> <final>
- * <initial> ::= NULL | <value>
- * <any> ::= '*' <starval>
- * <starval> ::= NULL | <value> '*' <starval>
- * <final> ::= NULL | <value>
- * </pre>
- *
- * {@code <attr>} is a string representing an attribute, or key,
- * in the properties objects of the registered services. Attribute names are
- * not case sensitive; that is cn and CN both refer to the same attribute.
- * {@code <value>} is a string representing the value, or part of
- * one, of a key in the properties objects of the registered services. If a
- * {@code <value>} must contain one of the characters '
- * {@code *}' or '{@code (}' or '{@code )}', these characters
- * should be escaped by preceding them with the backslash '{@code \}'
- * character. Note that although both the {@code <substring>} and
- * {@code <present>} productions can produce the {@code 'attr=*'}
- * construct, this construct is used only to denote a presence filter.
- *
- * <p>
- * Examples of LDAP filters are:
- *
- * <pre>
- * "(cn=Babs Jensen)"
- * "(!(cn=Tim Howes))"
- * "(&(" + Constants.OBJECTCLASS + "=Person)(|(sn=Jensen)(cn=Babs J*)))"
- * "(o=univ*of*mich*)"
- * </pre>
- *
- * <p>
- * The approximate match ({@code ~=}) is implementation specific but
- * should at least ignore case and white space differences. Optional are
- * codes like soundex or other smart "closeness" comparisons.
- *
- * <p>
- * Comparison of values is not straightforward. Strings are compared
- * differently than numbers and it is possible for a key to have multiple
- * values. Note that that keys in the match argument must always be strings.
- * The comparison is defined by the object type of the key's value. The
- * following rules apply for comparison:
- *
- * <blockquote>
- * <TABLE BORDER=0>
- * <TR>
- * <TD><b>Property Value Type </b></TD>
- * <TD><b>Comparison Type</b></TD>
- * </TR>
- * <TR>
- * <TD>String</TD>
- * <TD>String comparison</TD>
- * </TR>
- * <TR valign=top>
- * <TD>Integer, Long, Float, Double, Byte, Short, BigInteger, BigDecimal</TD>
- * <TD>numerical comparison</TD>
- * </TR>
- * <TR>
- * <TD>Character</TD>
- * <TD>character comparison</TD>
- * </TR>
- * <TR>
- * <TD>Boolean</TD>
- * <TD>equality comparisons only</TD>
- * </TR>
- * <TR>
- * <TD>[] (array)</TD>
- * <TD>recursively applied to values</TD>
- * </TR>
- * <TR>
- * <TD>Collection</TD>
- * <TD>recursively applied to values</TD>
- * </TR>
- * </TABLE>
- * Note: arrays of primitives are also supported. </blockquote>
- *
- * A filter matches a key that has multiple values if it matches at least
- * one of those values. For example,
- *
- * <pre>
- * Dictionary d = new Hashtable();
- * d.put("cn", new String[] {"a", "b", "c"});
- * </pre>
- *
- * d will match {@code (cn=a)} and also {@code (cn=b)}
- *
- * <p>
- * A filter component that references a key having an unrecognizable data
- * type will evaluate to {@code false} .
- */
- static private final class FilterImpl implements Filter {
- /* filter operators */
- private static final int EQUAL = 1;
- private static final int APPROX = 2;
- private static final int GREATER = 3;
- private static final int LESS = 4;
- private static final int PRESENT = 5;
- private static final int SUBSTRING = 6;
- private static final int AND = 7;
- private static final int OR = 8;
- private static final int NOT = 9;
-
- /** filter operation */
- private final int op;
- /** filter attribute or null if operation AND, OR or NOT */
- private final String attr;
- /** filter operands */
- private final Object value;
-
- /* normalized filter string for Filter object */
- private transient String filterString;
-
- /**
- * Constructs a {@link FilterImpl} object. This filter object may be
- * used to match a {@link ServiceReference} or a Dictionary.
- *
- * <p>
- * If the filter cannot be parsed, an {@link InvalidSyntaxException}
- * will be thrown with a human readable message where the filter became
- * unparsable.
- *
- * @param filterString the filter string.
- * @throws InvalidSyntaxException If the filter parameter contains an
- * invalid filter string that cannot be parsed.
- */
- static FilterImpl newInstance(String filterString)
- throws InvalidSyntaxException {
- return new Parser(filterString).parse();
- }
-
- FilterImpl(int operation, String attr, Object value) {
- this.op = operation;
- this.attr = attr;
- this.value = value;
- filterString = null;
- }
-
- /**
- * Filter using a service's properties.
- * <p>
- * This {@code Filter} is executed using the keys and values of the
- * referenced service's properties. The keys are looked up in a case
- * insensitive manner.
- *
- * @param reference The reference to the service whose properties are
- * used in the match.
- * @return {@code true} if the service's properties match this
- * {@code Filter}; {@code false} otherwise.
- */
- public boolean match(ServiceReference< ? > reference) {
- return matches(new ServiceReferenceMap(reference));
- }
-
- /**
- * Filter using a {@code Dictionary} with case insensitive key lookup.
- * This {@code Filter} is executed using the specified
- * {@code Dictionary}'s keys and values. The keys are looked up in a
- * case insensitive manner.
- *
- * @param dictionary The {@code Dictionary} whose key/value pairs are
- * used in the match.
- * @return {@code true} if the {@code Dictionary}'s values match this
- * filter; {@code false} otherwise.
- * @throws IllegalArgumentException If {@code dictionary} contains case
- * variants of the same key name.
- */
- public boolean match(Dictionary<String, ? > dictionary) {
- return matches(new CaseInsensitiveMap(dictionary));
- }
-
- /**
- * Filter using a {@code Dictionary}. This {@code Filter} is executed
- * using the specified {@code Dictionary}'s keys and values. The keys
- * are looked up in a normal manner respecting case.
- *
- * @param dictionary The {@code Dictionary} whose key/value pairs are
- * used in the match.
- * @return {@code true} if the {@code Dictionary}'s values match this
- * filter; {@code false} otherwise.
- * @since 1.3
- */
- public boolean matchCase(Dictionary<String, ? > dictionary) {
- switch (op) {
- case AND : {
- FilterImpl[] filters = (FilterImpl[]) value;
- for (FilterImpl f : filters) {
- if (!f.matchCase(dictionary)) {
- return false;
- }
- }
- return true;
- }
-
- case OR : {
- FilterImpl[] filters = (FilterImpl[]) value;
- for (FilterImpl f : filters) {
- if (f.matchCase(dictionary)) {
- return true;
- }
- }
- return false;
- }
-
- case NOT : {
- FilterImpl filter = (FilterImpl) value;
- return !filter.matchCase(dictionary);
- }
-
- case SUBSTRING :
- case EQUAL :
- case GREATER :
- case LESS :
- case APPROX : {
- Object prop = (dictionary == null) ? null : dictionary
- .get(attr);
- return compare(op, prop, value);
- }
-
- case PRESENT : {
- Object prop = (dictionary == null) ? null : dictionary
- .get(attr);
- return prop != null;
- }
- }
-
- return false;
- }
-
- /**
- * Filter using a {@code Map}. This {@code Filter} is executed using the
- * specified {@code Map}'s keys and values. The keys are looked up in a
- * normal manner respecting case.
- *
- * @param map The {@code Map} whose key/value pairs are used in the
- * match. Maps with {@code null} key or values are not supported.
- * A {@code null} value is considered not present to the filter.
- * @return {@code true} if the {@code Map}'s values match this filter;
- * {@code false} otherwise.
- * @since 1.6
- */
- public boolean matches(Map<String, ? > map) {
- switch (op) {
- case AND : {
- FilterImpl[] filters = (FilterImpl[]) value;
- for (FilterImpl f : filters) {
- if (!f.matches(map)) {
- return false;
- }
- }
- return true;
- }
-
- case OR : {
- FilterImpl[] filters = (FilterImpl[]) value;
- for (FilterImpl f : filters) {
- if (f.matches(map)) {
- return true;
- }
- }
- return false;
- }
-
- case NOT : {
- FilterImpl filter = (FilterImpl) value;
- return !filter.matches(map);
- }
-
- case SUBSTRING :
- case EQUAL :
- case GREATER :
- case LESS :
- case APPROX : {
- Object prop = (map == null) ? null : map.get(attr);
- return compare(op, prop, value);
- }
-
- case PRESENT : {
- Object prop = (map == null) ? null : map.get(attr);
- return prop != null;
- }
- }
-
- return false;
- }
-
- /**
- * Returns this {@code Filter}'s filter string.
- * <p>
- * The filter string is normalized by removing whitespace which does not
- * affect the meaning of the filter.
- *
- * @return This {@code Filter}'s filter string.
- */
- public String toString() {
- String result = filterString;
- if (result == null) {
- filterString = result = normalize().toString();
- }
- return result;
- }
-
- /**
- * Returns this {@code Filter}'s normalized filter string.
- * <p>
- * The filter string is normalized by removing whitespace which does not
- * affect the meaning of the filter.
- *
- * @return This {@code Filter}'s filter string.
- */
- private StringBuffer normalize() {
- StringBuffer sb = new StringBuffer();
- sb.append('(');
-
- switch (op) {
- case AND : {
- sb.append('&');
-
- FilterImpl[] filters = (FilterImpl[]) value;
- for (FilterImpl f : filters) {
- sb.append(f.normalize());
- }
-
- break;
- }
-
- case OR : {
- sb.append('|');
-
- FilterImpl[] filters = (FilterImpl[]) value;
- for (FilterImpl f : filters) {
- sb.append(f.normalize());
- }
-
- break;
- }
-
- case NOT : {
- sb.append('!');
- FilterImpl filter = (FilterImpl) value;
- sb.append(filter.normalize());
-
- break;
- }
-
- case SUBSTRING : {
- sb.append(attr);
- sb.append('=');
-
- String[] substrings = (String[]) value;
-
- for (String substr : substrings) {
- if (substr == null) /* * */{
- sb.append('*');
- }
- else /* xxx */{
- sb.append(encodeValue(substr));
- }
- }
-
- break;
- }
- case EQUAL : {
- sb.append(attr);
- sb.append('=');
- sb.append(encodeValue((String) value));
-
- break;
- }
- case GREATER : {
- sb.append(attr);
- sb.append(">=");
- sb.append(encodeValue((String) value));
-
- break;
- }
- case LESS : {
- sb.append(attr);
- sb.append("<=");
- sb.append(encodeValue((String) value));
-
- break;
- }
- case APPROX : {
- sb.append(attr);
- sb.append("~=");
- sb.append(encodeValue(approxString((String) value)));
-
- break;
- }
-
- case PRESENT : {
- sb.append(attr);
- sb.append("=*");
-
- break;
- }
- }
-
- sb.append(')');
-
- return sb;
- }
-
- /**
- * Compares this {@code Filter} to another {@code Filter}.
- *
- * <p>
- * This implementation returns the result of calling
- * {@code this.toString().equals(obj.toString()}.
- *
- * @param obj The object to compare against this {@code Filter}.
- * @return If the other object is a {@code Filter} object, then
- * returns the result of calling
- * {@code this.toString().equals(obj.toString()};
- * {@code false} otherwise.
- */
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
-
- if (!(obj instanceof Filter)) {
- return false;
- }
-
- return this.toString().equals(obj.toString());
- }
-
- /**
- * Returns the hashCode for this {@code Filter}.
- *
- * <p>
- * This implementation returns the result of calling
- * {@code this.toString().hashCode()}.
- *
- * @return The hashCode of this {@code Filter}.
- */
- public int hashCode() {
- return this.toString().hashCode();
- }
-
- /**
- * Encode the value string such that '(', '*', ')' and '\' are escaped.
- *
- * @param value unencoded value string.
- * @return encoded value string.
- */
- private static String encodeValue(String value) {
- boolean encoded = false;
- int inlen = value.length();
- int outlen = inlen << 1; /* inlen 2 */
-
- char[] output = new char[outlen];
- value.getChars(0, inlen, output, inlen);
-
- int cursor = 0;
- for (int i = inlen; i < outlen; i++) {
- char c = output[i];
-
- switch (c) {
- case '(' :
- case '*' :
- case ')' :
- case '\\' : {
- output[cursor] = '\\';
- cursor++;
- encoded = true;
-
- break;
- }
- }
-
- output[cursor] = c;
- cursor++;
- }
-
- return encoded ? new String(output, 0, cursor) : value;
- }
-
- private boolean compare(int operation, Object value1, Object value2) {
- if (value1 == null) {
- return false;
- }
- if (value1 instanceof String) {
- return compare_String(operation, (String) value1, value2);
- }
-
- Class< ? > clazz = value1.getClass();
- if (clazz.isArray()) {
- Class< ? > type = clazz.getComponentType();
- if (type.isPrimitive()) {
- return compare_PrimitiveArray(operation, type, value1,
- value2);
- }
- return compare_ObjectArray(operation, (Object[]) value1, value2);
- }
- if (value1 instanceof Collection< ? >) {
- return compare_Collection(operation, (Collection< ? >) value1,
- value2);
- }
- if (value1 instanceof Integer) {
- return compare_Integer(operation,
- ((Integer) value1).intValue(), value2);
- }
- if (value1 instanceof Long) {
- return compare_Long(operation, ((Long) value1).longValue(),
- value2);
- }
- if (value1 instanceof Byte) {
- return compare_Byte(operation, ((Byte) value1).byteValue(),
- value2);
- }
- if (value1 instanceof Short) {
- return compare_Short(operation, ((Short) value1).shortValue(),
- value2);
- }
- if (value1 instanceof Character) {
- return compare_Character(operation, ((Character) value1)
- .charValue(), value2);
- }
- if (value1 instanceof Float) {
- return compare_Float(operation, ((Float) value1).floatValue(),
- value2);
- }
- if (value1 instanceof Double) {
- return compare_Double(operation, ((Double) value1)
- .doubleValue(), value2);
- }
- if (value1 instanceof Boolean) {
- return compare_Boolean(operation, ((Boolean) value1)
- .booleanValue(), value2);
- }
- if (value1 instanceof Comparable< ? >) {
- Comparable<Object> comparable = (Comparable<Object>) value1;
- return compare_Comparable(operation, comparable, value2);
- }
- return compare_Unknown(operation, value1, value2);
- }
-
- private boolean compare_Collection(int operation,
- Collection< ? > collection, Object value2) {
- for (Object value1 : collection) {
- if (compare(operation, value1, value2)) {
- return true;
- }
- }
- return false;
- }
-
- private boolean compare_ObjectArray(int operation, Object[] array,
- Object value2) {
- for (Object value1 : array) {
- if (compare(operation, value1, value2)) {
- return true;
- }
- }
- return false;
- }
-
- private boolean compare_PrimitiveArray(int operation, Class< ? > type,
- Object primarray, Object value2) {
- if (Integer.TYPE.isAssignableFrom(type)) {
- int[] array = (int[]) primarray;
- for (int value1 : array) {
- if (compare_Integer(operation, value1, value2)) {
- return true;
- }
- }
- return false;
- }
- if (Long.TYPE.isAssignableFrom(type)) {
- long[] array = (long[]) primarray;
- for (long value1 : array) {
- if (compare_Long(operation, value1, value2)) {
- return true;
- }
- }
- return false;
- }
- if (Byte.TYPE.isAssignableFrom(type)) {
- byte[] array = (byte[]) primarray;
- for (byte value1 : array) {
- if (compare_Byte(operation, value1, value2)) {
- return true;
- }
- }
- return false;
- }
- if (Short.TYPE.isAssignableFrom(type)) {
- short[] array = (short[]) primarray;
- for (short value1 : array) {
- if (compare_Short(operation, value1, value2)) {
- return true;
- }
- }
- return false;
- }
- if (Character.TYPE.isAssignableFrom(type)) {
- char[] array = (char[]) primarray;
- for (char value1 : array) {
- if (compare_Character(operation, value1, value2)) {
- return true;
- }
- }
- return false;
- }
- if (Float.TYPE.isAssignableFrom(type)) {
- float[] array = (float[]) primarray;
- for (float value1 : array) {
- if (compare_Float(operation, value1, value2)) {
- return true;
- }
- }
- return false;
- }
- if (Double.TYPE.isAssignableFrom(type)) {
- double[] array = (double[]) primarray;
- for (double value1 : array) {
- if (compare_Double(operation, value1, value2)) {
- return true;
- }
- }
- return false;
- }
- if (Boolean.TYPE.isAssignableFrom(type)) {
- boolean[] array = (boolean[]) primarray;
- for (boolean value1 : array) {
- if (compare_Boolean(operation, value1, value2)) {
- return true;
- }
- }
- return false;
- }
- return false;
- }
-
- private boolean compare_String(int operation, String string,
- Object value2) {
- switch (operation) {
- case SUBSTRING : {
- String[] substrings = (String[]) value2;
- int pos = 0;
- for (int i = 0, size = substrings.length; i < size; i++) {
- String substr = substrings[i];
-
- if (i + 1 < size) /* if this is not that last substr */{
- if (substr == null) /* * */{
- String substr2 = substrings[i + 1];
-
- if (substr2 == null) /* ** */
- continue; /* ignore first star */
- /* xxx */
- int index = string.indexOf(substr2, pos);
- if (index == -1) {
- return false;
- }
-
- pos = index + substr2.length();
- if (i + 2 < size) // if there are more
- // substrings, increment
- // over the string we just
- // matched; otherwise need
- // to do the last substr
- // check
- i++;
- }
- else /* xxx */{
- int len = substr.length();
- if (string.regionMatches(pos, substr, 0, len)) {
- pos += len;
- }
- else {
- return false;
- }
- }
- }
- else /* last substr */{
- if (substr == null) /* * */{
- return true;
- }
- /* xxx */
- return string.endsWith(substr);
- }
- }
-
- return true;
- }
- case EQUAL : {
- return string.equals(value2);
- }
- case APPROX : {
- string = approxString(string);
- String string2 = approxString((String) value2);
-
- return string.equalsIgnoreCase(string2);
- }
- case GREATER : {
- return string.compareTo((String) value2) >= 0;
- }
- case LESS : {
- return string.compareTo((String) value2) <= 0;
- }
- }
- return false;
- }
-
- private boolean compare_Integer(int operation, int intval, Object value2) {
- if (operation == SUBSTRING) {
- return false;
- }
- int intval2;
- try {
- intval2 = Integer.parseInt(((String) value2).trim());
- }
- catch (IllegalArgumentException e) {
- return false;
- }
- switch (operation) {
- case APPROX :
- case EQUAL : {
- return intval == intval2;
- }
- case GREATER : {
- return intval >= intval2;
- }
- case LESS : {
- return intval <= intval2;
- }
- }
- return false;
- }
-
- private boolean compare_Long(int operation, long longval, Object value2) {
- if (operation == SUBSTRING) {
- return false;
- }
- long longval2;
- try {
- longval2 = Long.parseLong(((String) value2).trim());
- }
- catch (IllegalArgumentException e) {
- return false;
- }
-
- switch (operation) {
- case APPROX :
- case EQUAL : {
- return longval == longval2;
- }
- case GREATER : {
- return longval >= longval2;
- }
- case LESS : {
- return longval <= longval2;
- }
- }
- return false;
- }
-
- private boolean compare_Byte(int operation, byte byteval, Object value2) {
- if (operation == SUBSTRING) {
- return false;
- }
- byte byteval2;
- try {
- byteval2 = Byte.parseByte(((String) value2).trim());
- }
- catch (IllegalArgumentException e) {
- return false;
- }
-
- switch (operation) {
- case APPROX :
- case EQUAL : {
- return byteval == byteval2;
- }
- case GREATER : {
- return byteval >= byteval2;
- }
- case LESS : {
- return byteval <= byteval2;
- }
- }
- return false;
- }
-
- private boolean compare_Short(int operation, short shortval,
- Object value2) {
- if (operation == SUBSTRING) {
- return false;
- }
- short shortval2;
- try {
- shortval2 = Short.parseShort(((String) value2).trim());
- }
- catch (IllegalArgumentException e) {
- return false;
- }
-
- switch (operation) {
- case APPROX :
- case EQUAL : {
- return shortval == shortval2;
- }
- case GREATER : {
- return shortval >= shortval2;
- }
- case LESS : {
- return shortval <= shortval2;
- }
- }
- return false;
- }
-
- private boolean compare_Character(int operation, char charval,
- Object value2) {
- if (operation == SUBSTRING) {
- return false;
- }
- char charval2;
- try {
- charval2 = ((String) value2).charAt(0);
- }
- catch (IndexOutOfBoundsException e) {
- return false;
- }
-
- switch (operation) {
- case EQUAL : {
- return charval == charval2;
- }
- case APPROX : {
- return (charval == charval2)
- || (Character.toUpperCase(charval) == Character
- .toUpperCase(charval2))
- || (Character.toLowerCase(charval) == Character
- .toLowerCase(charval2));
- }
- case GREATER : {
- return charval >= charval2;
- }
- case LESS : {
- return charval <= charval2;
- }
- }
- return false;
- }
-
- private boolean compare_Boolean(int operation, boolean boolval,
- Object value2) {
- if (operation == SUBSTRING) {
- return false;
- }
- boolean boolval2 = Boolean.valueOf(((String) value2).trim())
- .booleanValue();
- switch (operation) {
- case APPROX :
- case EQUAL :
- case GREATER :
- case LESS : {
- return boolval == boolval2;
- }
- }
- return false;
- }
-
- private boolean compare_Float(int operation, float floatval,
- Object value2) {
- if (operation == SUBSTRING) {
- return false;
- }
- float floatval2;
- try {
- floatval2 = Float.parseFloat(((String) value2).trim());
- }
- catch (IllegalArgumentException e) {
- return false;
- }
-
- switch (operation) {
- case APPROX :
- case EQUAL : {
- return Float.compare(floatval, floatval2) == 0;
- }
- case GREATER : {
- return Float.compare(floatval, floatval2) >= 0;
- }
- case LESS : {
- return Float.compare(floatval, floatval2) <= 0;
- }
- }
- return false;
- }
-
- private boolean compare_Double(int operation, double doubleval,
- Object value2) {
- if (operation == SUBSTRING) {
- return false;
- }
- double doubleval2;
- try {
- doubleval2 = Double.parseDouble(((String) value2).trim());
- }
- catch (IllegalArgumentException e) {
- return false;
- }
-
- switch (operation) {
- case APPROX :
- case EQUAL : {
- return Double.compare(doubleval, doubleval2) == 0;
- }
- case GREATER : {
- return Double.compare(doubleval, doubleval2) >= 0;
- }
- case LESS : {
- return Double.compare(doubleval, doubleval2) <= 0;
- }
- }
- return false;
- }
-
- private static final Class< ? >[] constructorType = new Class[] {String.class};
-
- private boolean compare_Comparable(int operation,
- Comparable<Object> value1, Object value2) {
- if (operation == SUBSTRING) {
- return false;
- }
- Constructor< ? > constructor;
- try {
- constructor = value1.getClass().getConstructor(constructorType);
- }
- catch (NoSuchMethodException e) {
- return false;
- }
- try {
- if (!constructor.isAccessible())
- AccessController.doPrivileged(new SetAccessibleAction(
- constructor));
- value2 = constructor
- .newInstance(new Object[] {((String) value2).trim()});
- }
- catch (IllegalAccessException e) {
- return false;
- }
- catch (InvocationTargetException e) {
- return false;
- }
- catch (InstantiationException e) {
- return false;
- }
-
- try {
- switch (operation) {
- case APPROX :
- case EQUAL : {
- return value1.compareTo(value2) == 0;
- }
- case GREATER : {
- return value1.compareTo(value2) >= 0;
- }
- case LESS : {
- return value1.compareTo(value2) <= 0;
- }
- }
- }
- catch (Exception e) {
- // if the compareTo method throws an exception; return false
- return false;
- }
- return false;
- }
-
- private boolean compare_Unknown(int operation, Object value1,
- Object value2) {
- if (operation == SUBSTRING) {
- return false;
- }
- Constructor< ? > constructor;
- try {
- constructor = value1.getClass().getConstructor(constructorType);
- }
- catch (NoSuchMethodException e) {
- return false;
- }
- try {
- if (!constructor.isAccessible())
- AccessController.doPrivileged(new SetAccessibleAction(
- constructor));
- value2 = constructor
- .newInstance(new Object[] {((String) value2).trim()});
- }
- catch (IllegalAccessException e) {
- return false;
- }
- catch (InvocationTargetException e) {
- return false;
- }
- catch (InstantiationException e) {
- return false;
- }
-
- try {
- switch (operation) {
- case APPROX :
- case EQUAL :
- case GREATER :
- case LESS : {
- return value1.equals(value2);
- }
- }
- }
- catch (Exception e) {
- // if the equals method throws an exception; return false
- return false;
- }
- return false;
- }
-
- /**
- * Map a string for an APPROX (~=) comparison.
- *
- * This implementation removes white spaces. This is the minimum
- * implementation allowed by the OSGi spec.
- *
- * @param input Input string.
- * @return String ready for APPROX comparison.
- */
- private static String approxString(String input) {
- boolean changed = false;
- char[] output = input.toCharArray();
- int cursor = 0;
- for (char c : output) {
- if (Character.isWhitespace(c)) {
- changed = true;
- continue;
- }
-
- output[cursor] = c;
- cursor++;
- }
-
- return changed ? new String(output, 0, cursor) : input;
- }
-
- /**
- * Parser class for OSGi filter strings. This class parses the complete
- * filter string and builds a tree of Filter objects rooted at the
- * parent.
- */
- static private final class Parser {
- private final String filterstring;
- private final char[] filterChars;
- private int pos;
-
- Parser(String filterstring) {
- this.filterstring = filterstring;
- filterChars = filterstring.toCharArray();
- pos = 0;
- }
-
- FilterImpl parse() throws InvalidSyntaxException {
- FilterImpl filter;
- try {
- filter = parse_filter();
- }
- catch (ArrayIndexOutOfBoundsException e) {
- throw new InvalidSyntaxException("Filter ended abruptly",
- filterstring, e);
- }
-
- if (pos != filterChars.length) {
- throw new InvalidSyntaxException(
- "Extraneous trailing characters: "
- + filterstring.substring(pos), filterstring);
- }
- return filter;
- }
-
- private FilterImpl parse_filter() throws InvalidSyntaxException {
- FilterImpl filter;
- skipWhiteSpace();
-
- if (filterChars[pos] != '(') {
- throw new InvalidSyntaxException("Missing '(': "
- + filterstring.substring(pos), filterstring);
- }
-
- pos++;
-
- filter = parse_filtercomp();
-
- skipWhiteSpace();
-
- if (filterChars[pos] != ')') {
- throw new InvalidSyntaxException("Missing ')': "
- + filterstring.substring(pos), filterstring);
- }
-
- pos++;
-
- skipWhiteSpace();
-
- return filter;
- }
-
- private FilterImpl parse_filtercomp() throws InvalidSyntaxException {
- skipWhiteSpace();
-
- char c = filterChars[pos];
-
- switch (c) {
- case '&' : {
- pos++;
- return parse_and();
- }
- case '|' : {
- pos++;
- return parse_or();
- }
- case '!' : {
- pos++;
- return parse_not();
- }
- }
- return parse_item();
- }
-
- private FilterImpl parse_and() throws InvalidSyntaxException {
- int lookahead = pos;
- skipWhiteSpace();
-
- if (filterChars[pos] != '(') {
- pos = lookahead - 1;
- return parse_item();
- }
-
- List<FilterImpl> operands = new ArrayList<FilterImpl>(10);
-
- while (filterChars[pos] == '(') {
- FilterImpl child = parse_filter();
- operands.add(child);
- }
-
- return new FilterImpl(FilterImpl.AND, null, operands
- .toArray(new FilterImpl[operands.size()]));
- }
-
- private FilterImpl parse_or() throws InvalidSyntaxException {
- int lookahead = pos;
- skipWhiteSpace();
-
- if (filterChars[pos] != '(') {
- pos = lookahead - 1;
- return parse_item();
- }
-
- List<FilterImpl> operands = new ArrayList<FilterImpl>(10);
-
- while (filterChars[pos] == '(') {
- FilterImpl child = parse_filter();
- operands.add(child);
- }
-
- return new FilterImpl(FilterImpl.OR, null, operands
- .toArray(new FilterImpl[operands.size()]));
- }
-
- private FilterImpl parse_not() throws InvalidSyntaxException {
- int lookahead = pos;
- skipWhiteSpace();
-
- if (filterChars[pos] != '(') {
- pos = lookahead - 1;
- return parse_item();
- }
-
- FilterImpl child = parse_filter();
-
- return new FilterImpl(FilterImpl.NOT, null, child);
- }
-
- private FilterImpl parse_item() throws InvalidSyntaxException {
- String attr = parse_attr();
-
- skipWhiteSpace();
-
- switch (filterChars[pos]) {
- case '~' : {
- if (filterChars[pos + 1] == '=') {
- pos += 2;
- return new FilterImpl(FilterImpl.APPROX, attr,
- parse_value());
- }
- break;
- }
- case '>' : {
- if (filterChars[pos + 1] == '=') {
- pos += 2;
- return new FilterImpl(FilterImpl.GREATER, attr,
- parse_value());
- }
- break;
- }
- case '<' : {
- if (filterChars[pos + 1] == '=') {
- pos += 2;
- return new FilterImpl(FilterImpl.LESS, attr,
- parse_value());
- }
- break;
- }
- case '=' : {
- if (filterChars[pos + 1] == '*') {
- int oldpos = pos;
- pos += 2;
- skipWhiteSpace();
- if (filterChars[pos] == ')') {
- return new FilterImpl(FilterImpl.PRESENT, attr,
- null);
- }
- pos = oldpos;
- }
-
- pos++;
- Object string = parse_substring();
-
- if (string instanceof String) {
- return new FilterImpl(FilterImpl.EQUAL, attr,
- string);
- }
- return new FilterImpl(FilterImpl.SUBSTRING, attr,
- string);
- }
- }
-
- throw new InvalidSyntaxException("Invalid operator: "
- + filterstring.substring(pos), filterstring);
- }
-
- private String parse_attr() throws InvalidSyntaxException {
- skipWhiteSpace();
-
- int begin = pos;
- int end = pos;
-
- char c = filterChars[pos];
-
- while (c != '~' && c != '<' && c != '>' && c != '=' && c != '('
- && c != ')') {
- pos++;
-
- if (!Character.isWhitespace(c)) {
- end = pos;
- }
-
- c = filterChars[pos];
- }
-
- int length = end - begin;
-
- if (length == 0) {
- throw new InvalidSyntaxException("Missing attr: "
- + filterstring.substring(pos), filterstring);
- }
-
- return new String(filterChars, begin, length);
- }
-
- private String parse_value() throws InvalidSyntaxException {
- StringBuffer sb = new StringBuffer(filterChars.length - pos);
-
- parseloop: while (true) {
- char c = filterChars[pos];
-
- switch (c) {
- case ')' : {
- break parseloop;
- }
-
- case '(' : {
- throw new InvalidSyntaxException("Invalid value: "
- + filterstring.substring(pos), filterstring);
- }
-
- case '\\' : {
- pos++;
- c = filterChars[pos];
- /* fall through into default */
- }
-
- default : {
- sb.append(c);
- pos++;
- break;
- }
- }
- }
-
- if (sb.length() == 0) {
- throw new InvalidSyntaxException("Missing value: "
- + filterstring.substring(pos), filterstring);
- }
-
- return sb.toString();
- }
-
- private Object parse_substring() throws InvalidSyntaxException {
- StringBuffer sb = new StringBuffer(filterChars.length - pos);
-
- List<String> operands = new ArrayList<String>(10);
-
- parseloop: while (true) {
- char c = filterChars[pos];
-
- switch (c) {
- case ')' : {
- if (sb.length() > 0) {
- operands.add(sb.toString());
- }
-
- break parseloop;
- }
-
- case '(' : {
- throw new InvalidSyntaxException("Invalid value: "
- + filterstring.substring(pos), filterstring);
- }
-
- case '*' : {
- if (sb.length() > 0) {
- operands.add(sb.toString());
- }
-
- sb.setLength(0);
-
- operands.add(null);
- pos++;
-
- break;
- }
-
- case '\\' : {
- pos++;
- c = filterChars[pos];
- /* fall through into default */
- }
-
- default : {
- sb.append(c);
- pos++;
- break;
- }
- }
- }
-
- int size = operands.size();
-
- if (size == 0) {
- return "";
- }
-
- if (size == 1) {
- Object single = operands.get(0);
-
- if (single != null) {
- return single;
- }
- }
-
- return operands.toArray(new String[size]);
- }
-
- private void skipWhiteSpace() {
- for (int length = filterChars.length; (pos < length)
- && Character.isWhitespace(filterChars[pos]);) {
- pos++;
- }
- }
- }
- }
-
- /**
- * This Map is used for case-insensitive key lookup during filter
- * evaluation. This Map implementation only supports the get operation using
- * a String key as no other operations are used by the Filter
- * implementation.
- */
- static private final class CaseInsensitiveMap extends
- AbstractMap<String, Object>
- implements Map<String, Object> {
- private final Dictionary<String, ? > dictionary;
- private final String[] keys;
-
- /**
- * Create a case insensitive map from the specified dictionary.
- *
- * @param dictionary
- * @throws IllegalArgumentException If {@code dictionary} contains case
- * variants of the same key name.
- */
- CaseInsensitiveMap(Dictionary<String, ? > dictionary) {
- if (dictionary == null) {
- this.dictionary = null;
- this.keys = new String[0];
- return;
- }
- this.dictionary = dictionary;
- List<String> keyList = new ArrayList<String>(dictionary.size());
- for (Enumeration<?> e = dictionary.keys(); e.hasMoreElements();) {
- Object k = e.nextElement();
- if (k instanceof String) {
- String key = (String) k;
- for (String i : keyList) {
- if (key.equalsIgnoreCase(i)) {
- throw new IllegalArgumentException();
- }
- }
- keyList.add(key);
- }
- }
- this.keys = keyList.toArray(new String[keyList.size()]);
- }
-
- public Object get(Object o) {
- String k = (String) o;
- for (String key : keys) {
- if (key.equalsIgnoreCase(k)) {
- return dictionary.get(key);
- }
- }
- return null;
- }
-
- public Set<java.util.Map.Entry<String, Object>> entrySet() {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
- * This Map is used for key lookup from a ServiceReference during filter
- * evaluation. This Map implementation only supports the get operation using
- * a String key as no other operations are used by the Filter
- * implementation.
- */
- static private final class ServiceReferenceMap extends
- AbstractMap<String, Object> implements Map<String, Object> {
- private final ServiceReference< ? > reference;
-
- ServiceReferenceMap(ServiceReference< ? > reference) {
- this.reference = reference;
- }
-
- public Object get(Object key) {
- if (reference == null) {
- return null;
- }
- return reference.getProperty((String) key);
- }
-
- public Set<java.util.Map.Entry<String, Object>> entrySet() {
- throw new UnsupportedOperationException();
- }
- }
-
- static private final class SetAccessibleAction implements
- PrivilegedAction<Object> {
- private final AccessibleObject accessible;
-
- SetAccessibleAction(AccessibleObject accessible) {
- this.accessible = accessible;
- }
-
- public Object run() {
- accessible.setAccessible(true);
- return null;
- }
- }
-
- /**
* This class contains a method to match a distinguished name (DN) chain
* against and DN chain pattern.
* <p>
diff --git a/framework/src/main/java/org/osgi/framework/hooks/bundle/EventHook.java b/framework/src/main/java/org/osgi/framework/hooks/bundle/EventHook.java
new file mode 100644
index 0000000..4b50ab3
--- /dev/null
+++ b/framework/src/main/java/org/osgi/framework/hooks/bundle/EventHook.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) OSGi Alliance (2010). 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.framework.hooks.bundle;
+
+import java.util.Collection;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+
+/**
+ * OSGi Framework Bundle Event Hook Service.
+ *
+ * <p>
+ * Bundles registering this service will be called during framework lifecycle
+ * (install, start, stop, update, and uninstall bundle) operations.
+ *
+ * @ThreadSafe
+ * @version $Id: 18ea1ec1f14f47410a43e99be4da3b2583149722 $
+ */
+public interface EventHook {
+
+ /**
+ * Bundle event hook method. This method is called prior to bundle event
+ * delivery when a bundle is installed, resolved, started, stopped, unresolved, or
+ * uninstalled. This method can filter the bundles which receive the event.
+ * <p>
+ * This method must be called by the framework one and only one time for each bundle
+ * event generated, this included bundle events which are generated when there are no
+ * bundle listeners registered. This method must be called on the same thread that is
+ * performing the action which generated the specified event. The specified
+ * collection includes bundle contexts with synchronous and asynchronous bundle
+ * listeners registered with them.
+ *
+ * @param event The bundle event to be delivered
+ * @param contexts A collection of Bundle Contexts for bundles which have
+ * listeners to which the specified event will be delivered. The
+ * implementation of this method may remove bundle contexts from the
+ * collection to prevent the event from being delivered to the
+ * associated bundles. The collection supports all the optional
+ * {@code Collection} operations except {@code add} and
+ * {@code addAll}. Attempting to add to the collection will
+ * result in an {@code UnsupportedOperationException}. The
+ * collection is not synchronized.
+ */
+ void event(BundleEvent event, Collection<BundleContext> contexts);
+}
diff --git a/framework/src/main/java/org/osgi/framework/hooks/bundle/FindHook.java b/framework/src/main/java/org/osgi/framework/hooks/bundle/FindHook.java
new file mode 100644
index 0000000..e55ee3b
--- /dev/null
+++ b/framework/src/main/java/org/osgi/framework/hooks/bundle/FindHook.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) OSGi Alliance (2011). 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.framework.hooks.bundle;
+
+import java.util.Collection;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+
+/**
+ * OSGi Framework Bundle Context Hook Service.
+ *
+ * <p>
+ * Bundles registering this service will be called during framework bundle find
+ * (get bundles) operations.
+ *
+ * @ThreadSafe
+ * @version $Id: 4492a677df650072fe6acaea9ea35571f31eb5a9 $
+ */
+public interface FindHook {
+ /**
+ * Find hook method. This method is called for the following:
+ * <ul>
+ * <li>Bundle find operations using {@link BundleContext#getBundle(long)}
+ * and {@link BundleContext#getBundles()} methods. The find method can
+ * filter the result of the find operation. Note that a find operation using
+ * the {@link BundleContext#getBundle(String)} method does not cause the
+ * find method to be called.</li>
+ * <li>Bundle install operations when an existing bundle is already
+ * installed at a given location. In this case, the find method is called to
+ * determine if the context performing the install operation is able to find
+ * the bundle. If the context cannot find the existing bundle then the
+ * install operation must fail with a
+ * {@link BundleException#REJECTED_BY_HOOK} exception.</li>
+ * </ul>
+ *
+ * @param context
+ * The bundle context of the bundle performing the find
+ * operation.
+ * @param bundles
+ * A collection of Bundles to be returned as a result of the find
+ * operation. The implementation of this method may remove
+ * bundles from the collection to prevent the bundles from being
+ * returned to the bundle performing the find operation. The
+ * collection supports all the optional {@code Collection}
+ * operations except {@code add} and {@code addAll}. Attempting
+ * to add to the collection will result in an
+ * {@code UnsupportedOperationException}. The collection is not
+ * synchronized.
+ */
+ void find(BundleContext context, Collection<Bundle> bundles);
+}
diff --git a/framework/src/main/java/org/osgi/framework/hooks/resolver/ResolverHook.java b/framework/src/main/java/org/osgi/framework/hooks/resolver/ResolverHook.java
new file mode 100644
index 0000000..bbde7ff
--- /dev/null
+++ b/framework/src/main/java/org/osgi/framework/hooks/resolver/ResolverHook.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) OSGi Alliance (2010, 2011). 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.framework.hooks.resolver;
+
+import java.util.Collection;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.FrameworkWiring;
+
+/**
+ * OSGi Framework Resolver Hook instances are obtained from the OSGi
+ * {@link ResolverHookFactory Framework Resolver Hook Factory} service.
+ *
+ * <p>
+ * A Resolver Hook instance is called by the framework during a resolve process.
+ * A resolver hook may influence the outcome of a resolve process by removing
+ * entries from shrinkable collections that are passed to the hook during a
+ * resolve process. A shrinkable collection is a {@code Collection} that
+ * supports all remove operations. Any other attempts to modify a shrinkable
+ * collection will result in an {@code UnsupportedOperationException} being
+ * thrown.
+ *
+ * <p>
+ * The following steps outline the way a framework uses the resolver hooks
+ * during a resolve process.
+ * <ol>
+ * <li>Collect a snapshot of registered resolver hook factories that will be
+ * called during the current resolve process. Any hook factories registered
+ * after the snapshot is taken must not be called during the current resolve
+ * process. A resolver hook factory contained in the snapshot may become
+ * unregistered during the resolve process. The framework should handle this and
+ * stop calling the resolver hook instance provided by the unregistered hook
+ * factory and the current resolve process must fail. If possible, an exception
+ * must be thrown to the caller of the API which triggered the resolve process.
+ * In cases where the the caller is not available a framework event of type
+ * error should be fired.</li>
+ * <li>For each registered hook factory call the
+ * {@link ResolverHookFactory#begin(Collection)} method to inform the hooks
+ * about a resolve process beginning and to obtain a Resolver Hook instance that
+ * will be used for the duration of the resolve process.</li>
+ * <li>Determine the collection of unresolved bundle revisions that may be
+ * considered for resolution during the current resolution process and place
+ * each of the bundle revisions in a shrinkable collection {@code R}. For each
+ * resolver hook call the {@link #filterResolvable(Collection)} method with the
+ * shrinkable collection {@code R}.</li>
+ * <li>The shrinkable collection {@code R} now contains all the unresolved
+ * bundle revisions that may end up as resolved at the end of the current
+ * resolve process. Any other bundle revisions that got removed from the
+ * shrinkable collection {@code R} must not end up as resolved at the end of the
+ * current resolve process.</li>
+ * <li>For each bundle revision {@code B} left in the shrinkable collection
+ * {@code R} that represents a singleton bundle do the following:<br/>
+ * Determine the collection of available capabilities that have a name space of
+ * {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle}, are singletons,
+ * and have the same symbolic name as the singleton bundle revision {@code B}
+ * and place each of the matching capabilities into a shrinkable collection
+ * {@code S}.
+ *
+ * Remove the {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle}
+ * capability provided by bundle revision {@code B} from shrinkable collection
+ * {@code S}. A singleton bundle cannot collide with itself.
+ *
+ * For each resolver hook call the
+ * {@link #filterSingletonCollisions(BundleCapability, Collection)} with the
+ * {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle} capability
+ * provided by bundle revision {@code B} and the shrinkable collection {@code S}
+ *
+ * The shrinkable collection {@code S} now contains all singleton
+ * {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle} capabilities that
+ * can influence the ability of bundle revision {@code B} to resolve.</li>
+ * <li>During a resolve process a framework is free to attempt to resolve any or
+ * all bundles contained in shrinkable collection {@code R}. For each bundle
+ * revision {@code B} left in the shrinkable collection {@code R} which the
+ * framework attempts to resolve the following steps must be followed:
+ * <p/>
+ * For each requirement {@code T} specified by bundle revision {@code B}
+ * determine the collection of capabilities that satisfy (or match) the
+ * requirement and place each matching capability into a shrinkable collection
+ * {@code C}. A capability is considered to match a particular requirement if
+ * its attributes satisfy a specified requirement and the requirer bundle has
+ * permission to access the capability.
+ *
+ * <p/>
+ * For each resolver hook call the
+ * {@link #filterMatches(BundleRequirement, Collection)} with the requirement
+ * {@code T} and the shrinkable collection {@code C}.
+ *
+ * <p/>
+ * The shrinkable collection {@code C} now contains all the capabilities that
+ * may be used to satisfy the requirement {@code T}. Any other capabilities that
+ * got removed from the shrinkable collection {@code C} must not be used to
+ * satisfy requirement {@code T}.</li>
+ * <li>For each resolver hook call the {@link #end()} method to inform the hooks
+ * about a resolve process ending.</li>
+ * </ol>
+ * In all cases, the order in which the resolver hooks are called is the reverse
+ * compareTo ordering of their Service References. That is, the service with the
+ * highest ranking number must be called first. In cases where a shrinkable
+ * collection becomes empty the framework is required to call the remaining
+ * registered hooks.
+ * <p>
+ * Resolver hooks are low level. Implementations of the resolver hook must be
+ * careful not to create an unresolvable state which is very hard for a
+ * developer or a provisioner to diagnose. Resolver hooks also must not be
+ * allowed to start another synchronous resolve process (e.g. by calling
+ * {@link Bundle#start()} or {@link FrameworkWiring#resolveBundles(Collection)}
+ * ). The framework must detect this and throw an {@link IllegalStateException}.
+ *
+ * @see ResolverHookFactory
+ * @NotThreadSafe
+ * @version $Id: ea23400257d780706250f8825ec886aaebb0e5d8 $
+ */
+public interface ResolverHook {
+ /**
+ * Filter resolvable candidates hook method. This method may be called
+ * multiple times during a single resolve process.
+ * This method can filter the collection of candidates by removing
+ * potential candidates. Removing a candidate will prevent the candidate
+ * from resolving during the current resolve process.
+ *
+ * @param candidates the collection of resolvable candidates available during
+ * a resolve process.
+ */
+ void filterResolvable(Collection<BundleRevision> candidates);
+
+ /**
+ * Filter singleton collisions hook method. This method is called during the
+ * resolve process for the specified singleton. The specified singleton
+ * represents a singleton capability and the specified collection represent
+ * a collection of singleton capabilities which are considered collision
+ * candidates. The singleton capability and the collection of collision
+ * candidates must all use the same name space.
+ * <p>
+ * Currently only capabilities with the name space of
+ * {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle} can be
+ * singletons. In that case all the collision candidates have the name space
+ * of {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle}, are
+ * singletons, and have the same symbolic name as the specified singleton
+ * capability.
+ * <p>
+ * In the future, capabilities in other name spaces may support the
+ * singleton concept. Hook implementations should be prepared to receive
+ * calls to this method for capabilities in name spaces other than
+ * {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle}.
+ * <p>
+ * This method can filter the list of collision candidates by removing
+ * potential collisions. Removing a collision candidate will allow the
+ * specified singleton to resolve regardless of the resolution state of the
+ * removed collision candidate.
+ *
+ * @param singleton the singleton involved in a resolve process
+ * @param collisionCandidates a collection of singleton collision candidates
+ */
+ void filterSingletonCollisions(BundleCapability singleton, Collection<BundleCapability> collisionCandidates);
+
+ /**
+ * Filter matches hook method. This method is called during the resolve process for the
+ * specified requirement. The collection of candidates match the specified requirement.
+ * This method can filter the collection of matching candidates by removing candidates from
+ * the collection. Removing a candidate will prevent the resolve process from choosing the
+ * removed candidate to satisfy the requirement.
+ * <p>
+ * All of the candidates will have the same name space and will
+ * match the specified requirement.
+ * <p>
+ * If the Java Runtime Environment supports permissions then the collection of
+ * candidates will only contain candidates for which the requirer has permission to
+ * access.
+ * @param requirement the requirement to filter candidates for
+ * @param candidates a collection of candidates that match the requirement
+ */
+ void filterMatches(BundleRequirement requirement, Collection<BundleCapability> candidates);
+
+ /**
+ * This method is called once at the end of the resolve process.
+ * After the end method is called the resolve process has ended.
+ * The framework must not hold onto this resolver hook instance
+ * after end has been called.
+ */
+ void end();
+}
diff --git a/framework/src/main/java/org/osgi/framework/hooks/resolver/ResolverHookFactory.java b/framework/src/main/java/org/osgi/framework/hooks/resolver/ResolverHookFactory.java
new file mode 100644
index 0000000..1d4edd4
--- /dev/null
+++ b/framework/src/main/java/org/osgi/framework/hooks/resolver/ResolverHookFactory.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) OSGi Alliance (2011). 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.framework.hooks.resolver;
+
+import java.util.Collection;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.FrameworkWiring;
+
+/**
+ * OSGi Framework Resolver Hook Factory Service.
+ *
+ * <p>
+ * Bundles registering this service will be called by the framework during
+ * a bundle resolver process to obtain a {@link ResolverHook resolver hook}
+ * instance which will be used for the duration of a resolve process.
+ *
+ * @ThreadSafe
+ * @see ResolverHook
+ * @version $Id: 4023566367435f07c047a7ba571f3bedc53aa37a $
+ */
+public interface ResolverHookFactory {
+ /**
+ * This method is called by the framework each time a resolve process begins
+ * to obtain a {@link ResolverHook resolver hook} instance. This resolver hook
+ * instance will be used for the duration of the resolve process. At the end of
+ * the resolve process the method {@link ResolverHook#end()} must be called by
+ * the framework and the framework must not hold any references of the resolver
+ * hook instance.
+ * <p>
+ * The triggers represent the collection of bundles which triggered
+ * the resolve process. This collection may be empty if the triggers
+ * cannot be determined by the framework. In most cases the triggers
+ * can easily be determined. Calling certain methods on
+ * {@link Bundle bundle} when a bundle is in the {@link Bundle#INSTALLED INSTALLED}
+ * state will cause the framework to begin a resolve process in order to resolve the
+ * bundle. The following methods will start a resolve process in this case:
+ * <ul>
+ * <li>{@link Bundle#start() start}</li>
+ * <li>{@link Bundle#loadClass(String) loadClass}</li>
+ * <li>{@link Bundle#findEntries(String, String, boolean) findEntries}</li>
+ * <li>{@link Bundle#getResource(String) getResource}</li>
+ * <li>{@link Bundle#getResources(String) getResources}</li>
+ * </ul>
+ * In such cases the collection will contain the single bundle which the
+ * framework is trying to resolve. Other cases will cause multiple bundles to be
+ * included in the trigger bundles collection. When {@link FrameworkWiring#resolveBundles(Collection)
+ * resolveBundles} is called the collection of triggers must include all the current bundle
+ * revisions for bundles passed to resolveBundles which are in the {@link Bundle#INSTALLED INSTALLED}
+ * state.
+ * <p>
+ * When {@link FrameworkWiring#refreshBundles(Collection, org.osgi.framework.FrameworkListener...)}
+ * is called the collection of triggers is determined with the following steps:
+ * <ul>
+ * <li>If the collection of bundles passed is null then {@link FrameworkWiring#getRemovalPendingBundles()}
+ * is called to get the initial collection of bundles.</li>
+ * <li>The equivalent of calling {@link FrameworkWiring#getDependencyClosure(Collection)} is called with
+ * the initial collection of bundles to get the dependency closure collection of the bundles being refreshed.</li>
+ * <li>Remove any non-active bundles from the dependency closure collection.</li>
+ * <li>For each bundle remaining in the dependency closure collection get the current bundle revision
+ * and add it to the collection of triggers.</li>
+ * </ul>
+ * <p>
+ * As described above, a resolve process is typically initiated as a result of calling API that causes the
+ * framework to attempt to resolve one or more bundles.
+ * The framework is free to start a resolve process at any time for reasons other than calls to framework API.
+ * For example, a resolve process may be used by the framework for diagnostic purposes and result in no
+ * bundles actually becoming resolved at the end of the process.
+ * Resolver hook implementations must be prepared for resolve processes that are initiated for other reasons
+ * besides calls to framework API.
+ * @param triggers an unmodifiable collection of bundles which triggered the resolve process.
+ * This collection may be empty if the collection of trigger bundles cannot be
+ * determined.
+ * @return a resolver hook instance to be used for the duration of the resolve process.
+ * A {@code null} value may be returned which indicates this resolver hook factory abstains from
+ * the resolve process.
+ */
+ ResolverHook begin(Collection<BundleRevision> triggers);
+}
diff --git a/framework/src/main/java/org/osgi/framework/hooks/service/EventHook.java b/framework/src/main/java/org/osgi/framework/hooks/service/EventHook.java
index 1249493..fb2ab09 100644
--- a/framework/src/main/java/org/osgi/framework/hooks/service/EventHook.java
+++ b/framework/src/main/java/org/osgi/framework/hooks/service/EventHook.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2008, 2009). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2008, 2010). 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.
@@ -18,6 +18,7 @@
import java.util.Collection;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceEvent;
/**
@@ -28,7 +29,8 @@
* (register, modify, and unregister service) operations.
*
* @ThreadSafe
- * @version $Revision: 6967 $
+ * @deprecated As of 1.1. Replaced by {@link EventListenerHook}.
+ * @version $Id: 8fb8cfa2c8847f99fd84711e12f02a57bf06932e $
*/
public interface EventHook {
@@ -38,17 +40,15 @@
* This method can filter the bundles which receive the event.
*
* @param event The service event to be delivered.
- * @param contexts A <code>Collection</code> of Bundle Contexts for bundles
- * which have listeners to which the specified event will be
- * delivered. The implementation of this method may remove bundle
- * contexts from the collection to prevent the event from being
- * delivered to the associated bundles. The collection supports all
- * the optional <code>Collection</code> operations except
- * <code>add</code> and <code>addAll</code>. Attempting to add to the
- * collection will result in an
- * <code>UnsupportedOperationException</code>. The collection is not
- * synchronized.
+ * @param contexts A collection of Bundle Contexts for bundles which have
+ * listeners to which the specified event will be delivered. The
+ * implementation of this method may remove bundle contexts from the
+ * collection to prevent the event from being delivered to the
+ * associated bundles. The collection supports all the optional
+ * {@code Collection} operations except {@code add} and
+ * {@code addAll}. Attempting to add to the collection will
+ * result in an {@code UnsupportedOperationException}. The
+ * collection is not synchronized.
*/
- void event(ServiceEvent event,
- Collection/* <BundleContext> */contexts);
+ void event(ServiceEvent event, Collection<BundleContext> contexts);
}
diff --git a/framework/src/main/java/org/osgi/framework/hooks/service/EventListenerHook.java b/framework/src/main/java/org/osgi/framework/hooks/service/EventListenerHook.java
new file mode 100644
index 0000000..6f25291
--- /dev/null
+++ b/framework/src/main/java/org/osgi/framework/hooks/service/EventListenerHook.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) OSGi Alliance (2010). 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.framework.hooks.service;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.hooks.service.ListenerHook.ListenerInfo;
+
+/**
+ * OSGi Framework Service Event Listener Hook Service.
+ *
+ * <p>
+ * Bundles registering this service will be called during framework service
+ * (register, modify, and unregister service) operations.
+ *
+ * @ThreadSafe
+ * @since 1.1
+ * @version $Id: 61c6aa7e7d4c85b3e5a6a3a340155bcda0074505 $
+ */
+
+public interface EventListenerHook {
+ /**
+ * Event listener hook method. This method is called prior to service event
+ * delivery when a publishing bundle registers, modifies or unregisters a
+ * service. This method can filter the listeners which receive the event.
+ *
+ * @param event The service event to be delivered.
+ * @param listeners A map of Bundle Contexts to a collection of Listener
+ * Infos for the bundle's listeners to which the specified event will
+ * be delivered. The implementation of this method may remove bundle
+ * contexts from the map and listener infos from the collection
+ * values to prevent the event from being delivered to the associated
+ * listeners. The map supports all the optional {@code Map}
+ * operations except {@code put} and {@code putAll}. Attempting to
+ * add to the map will result in an
+ * {@code UnsupportedOperationException}. The collection values in
+ * the map supports all the optional {@code Collection} operations
+ * except {@code add} and {@code addAll}. Attempting to add to a
+ * collection will result in an {@code UnsupportedOperationException}
+ * . The map and the collections are not synchronized.
+ */
+ void event(ServiceEvent event,
+ Map<BundleContext, Collection<ListenerInfo>> listeners);
+}
diff --git a/framework/src/main/java/org/osgi/framework/hooks/service/FindHook.java b/framework/src/main/java/org/osgi/framework/hooks/service/FindHook.java
index 0de1f0b..cb334c5 100644
--- a/framework/src/main/java/org/osgi/framework/hooks/service/FindHook.java
+++ b/framework/src/main/java/org/osgi/framework/hooks/service/FindHook.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2008, 2009). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2008, 2010). 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.
@@ -19,6 +19,7 @@
import java.util.Collection;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
/**
* OSGi Framework Service Find Hook Service.
@@ -28,7 +29,7 @@
* (get service references) operations.
*
* @ThreadSafe
- * @version $Revision: 6967 $
+ * @version $Id: 4a939200fa6634a563379b057e11bd1b5d174b9d $
*/
public interface FindHook {
@@ -39,25 +40,23 @@
*
* @param context The bundle context of the bundle performing the find
* operation.
- * @param name The class name of the services to find or <code>null</code>
+ * @param name The class name of the services to find or {@code null}
* to find all services.
* @param filter The filter criteria of the services to find or
- * <code>null</code> for no filter criteria.
- * @param allServices <code>true</code> if the find operation is the result
+ * {@code null} for no filter criteria.
+ * @param allServices {@code true} if the find operation is the result
* of a call to
* {@link BundleContext#getAllServiceReferences(String, String)}
- * @param references A <code>Collection</code> of Service References to be
- * returned as a result of the find operation. The implementation of
- * this method may remove service references from the collection to
- * prevent the references from being returned to the bundle
- * performing the find operation. The collection supports all the
- * optional <code>Collection</code> operations except
- * <code>add</code> and <code>addAll</code>. Attempting to add to the
- * collection will result in an
- * <code>UnsupportedOperationException</code>. The collection is not
- * synchronized.
+ * @param references A collection of Service References to be returned as a
+ * result of the find operation. The implementation of this method
+ * may remove service references from the collection to prevent the
+ * references from being returned to the bundle performing the find
+ * operation. The collection supports all the optional
+ * {@code Collection} operations except {@code add} and
+ * {@code addAll}. Attempting to add to the collection will
+ * result in an {@code UnsupportedOperationException}. The
+ * collection is not synchronized.
*/
void find(BundleContext context, String name, String filter,
- boolean allServices,
- Collection/* <ServiceReference> */references);
+ boolean allServices, Collection<ServiceReference< ? >> references);
}
diff --git a/framework/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java b/framework/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java
index 5934c0c..bdac7b5 100644
--- a/framework/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java
+++ b/framework/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2008, 2009). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2008, 2010). 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.
@@ -28,7 +28,7 @@
* addition and removal.
*
* @ThreadSafe
- * @version $Revision: 6967 $
+ * @version $Id: c1687e95e568589cf3e6d927b7d372c9f88c5d16 $
*/
public interface ListenerHook {
@@ -40,13 +40,13 @@
* method will be called to provide the current collection of service
* listeners which had been added prior to the hook being registered.
*
- * @param listeners A <code>Collection</code> of {@link ListenerInfo}s for
- * newly added service listeners which are now listening to service
- * events. Attempting to add to or remove from the collection will
- * result in an <code>UnsupportedOperationException</code>. The
- * collection is not synchronized.
+ * @param listeners A collection of {@link ListenerInfo}s for newly added
+ * service listeners which are now listening to service events.
+ * Attempting to add to or remove from the collection will result in
+ * an {@code UnsupportedOperationException}. The collection is
+ * not synchronized.
*/
- void added(Collection/* <ListenerInfo> */listeners);
+ void added(Collection<ListenerInfo> listeners);
/**
* Removed listeners hook method. This method is called to provide the hook
@@ -54,19 +54,20 @@
* method will be called as service listeners are removed while this hook is
* registered.
*
- * @param listeners A <code>Collection</code> of {@link ListenerInfo}s for
- * newly removed service listeners which are no longer listening to
- * service events. Attempting to add to or remove from the collection
- * will result in an <code>UnsupportedOperationException</code>. The
- * collection is not synchronized.
+ * @param listeners A collection of {@link ListenerInfo}s for newly removed
+ * service listeners which are no longer listening to service events.
+ * Attempting to add to or remove from the collection will result in
+ * an {@code UnsupportedOperationException}. The collection is
+ * not synchronized.
*/
- void removed(Collection/* <ListenerInfo> */listeners);
+ void removed(Collection<ListenerInfo> listeners);
/**
* Information about a Service Listener. This interface describes the bundle
* which added the Service Listener and the filter with which it was added.
*
* @ThreadSafe
+ * @noimplement
*/
public interface ListenerInfo {
/**
@@ -80,17 +81,17 @@
* Return the filter string with which the listener was added.
*
* @return The filter string with which the listener was added. This may
- * be <code>null</code> if the listener was added without a
+ * be {@code null} if the listener was added without a
* filter.
*/
String getFilter();
/**
* Return the state of the listener for this addition and removal life
- * cycle. Initially this method will return <code>false</code>
+ * cycle. Initially this method will return {@code false}
* indicating the listener has been added but has not been removed.
* After the listener has been removed, this method must always return
- * <code>true</code>.
+ * {@code true}.
*
* <p>
* There is an extremely rare case in which removed notification to
@@ -102,32 +103,32 @@
* service listener. This method can be used to detect this rare
* occurrence.
*
- * @return <code>false</code> if the listener has not been been removed,
- * <code>true</code> otherwise.
+ * @return {@code false} if the listener has not been been removed,
+ * {@code true} otherwise.
*/
boolean isRemoved();
/**
- * Compares this <code>ListenerInfo</code> to another
- * <code>ListenerInfo</code>. Two <code>ListenerInfo</code>s are equals
+ * Compares this {@code ListenerInfo} to another
+ * {@code ListenerInfo}. Two {@code ListenerInfo}s are equals
* if they refer to the same listener for a given addition and removal
* life cycle. If the same listener is added again, it must have a
- * different <code>ListenerInfo</code> which is not equal to this
- * <code>ListenerInfo</code>.
+ * different {@code ListenerInfo} which is not equal to this
+ * {@code ListenerInfo}.
*
* @param obj The object to compare against this
- * <code>ListenerInfo</code>.
- * @return <code>true</code> if the other object is a
- * <code>ListenerInfo</code> object and both objects refer to
+ * {@code ListenerInfo}.
+ * @return {@code true} if the other object is a
+ * {@code ListenerInfo} object and both objects refer to
* the same listener for a given addition and removal life
* cycle.
*/
boolean equals(Object obj);
/**
- * Returns the hash code for this <code>ListenerInfo</code>.
+ * Returns the hash code for this {@code ListenerInfo}.
*
- * @return The hash code of this <code>ListenerInfo</code>.
+ * @return The hash code of this {@code ListenerInfo}.
*/
int hashCode();
}
diff --git a/framework/src/main/java/org/osgi/framework/hooks/weaving/WeavingException.java b/framework/src/main/java/org/osgi/framework/hooks/weaving/WeavingException.java
new file mode 100644
index 0000000..8842797
--- /dev/null
+++ b/framework/src/main/java/org/osgi/framework/hooks/weaving/WeavingException.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) OSGi Alliance (2010). 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.framework.hooks.weaving;
+
+/**
+ * A weaving exception used to indicate that the class load should be failed but
+ * the weaving hook must not be blacklisted by the framework.
+ *
+ * <p>
+ * This exception conforms to the general purpose exception chaining mechanism.
+ *
+ * @version $Id: eb38b85f6ed66ec445fb2f0ee7143df021327a9a $
+ */
+
+public class WeavingException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates a {@code WeavingException} with the specified message and
+ * exception cause.
+ *
+ * @param msg The associated message.
+ * @param cause The cause of this exception.
+ */
+ public WeavingException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+ /**
+ * Creates a {@code WeavingException} with the specified message.
+ *
+ * @param msg The message.
+ */
+ public WeavingException(String msg) {
+ super(msg);
+ }
+}
diff --git a/framework/src/main/java/org/osgi/framework/hooks/weaving/WeavingHook.java b/framework/src/main/java/org/osgi/framework/hooks/weaving/WeavingHook.java
new file mode 100644
index 0000000..be57658
--- /dev/null
+++ b/framework/src/main/java/org/osgi/framework/hooks/weaving/WeavingHook.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) OSGi Alliance (2010). 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.framework.hooks.weaving;
+
+/**
+ * OSGi Framework Weaving Hook Service.
+ *
+ * <p>
+ * Bundles registering this service will be called during framework class
+ * loading operations. Weaving hook services are called when a class is being
+ * loaded by the framework and have an opportunity to transform the class file
+ * bytes that represents the class being loaded. Weaving hooks may also ask the
+ * framework to wire in additional dynamic imports to the bundle.
+ *
+ * <p>
+ * When a class is being loaded, the framework will create a {@link WovenClass}
+ * object for the class and pass it to each registered weaving hook service for
+ * possible modification. The first weaving hook called will see the original
+ * class file bytes. Subsequently called weaving hooks will see the class file
+ * bytes as modified by previously called weaving hooks.
+ *
+ * @ThreadSafe
+ * @version $Id: d1985029024baba2db1c56aab1e06ee953fd6365 $
+ */
+
+public interface WeavingHook {
+ /**
+ * Weaving hook method.
+ *
+ * This method can modify the specified woven class object to weave the
+ * class being defined.
+ *
+ * <p>
+ * If this method throws any exception, the framework must log the exception
+ * and fail the class load in progress. This weaving hook service must be
+ * blacklisted by the framework and must not be called again. The
+ * blacklisting of this weaving hook service must expire when this weaving
+ * hook service is unregistered. However, this method can throw a
+ * {@link WeavingException} to deliberately fail the class load in progress
+ * without being blacklisted by the framework.
+ *
+ * @param wovenClass The {@link WovenClass} object that represents the data
+ * that will be used to define the class.
+ * @throws WeavingException If this weaving hook wants to deliberately fail
+ * the class load in progress without being blacklisted by the
+ * framework
+ */
+ public void weave(WovenClass wovenClass);
+}
diff --git a/framework/src/main/java/org/osgi/framework/hooks/weaving/WovenClass.java b/framework/src/main/java/org/osgi/framework/hooks/weaving/WovenClass.java
new file mode 100644
index 0000000..34aa6d2
--- /dev/null
+++ b/framework/src/main/java/org/osgi/framework/hooks/weaving/WovenClass.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) OSGi Alliance (2010, 2011). 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.framework.hooks.weaving;
+
+import java.security.ProtectionDomain;
+import java.util.List;
+
+import org.osgi.framework.wiring.BundleWiring;
+
+/**
+ * A class being woven.
+ *
+ * This object represents a class being woven and is passed to each
+ * {@link WeavingHook} for possible modification. It allows access to the most
+ * recently transformed class file bytes and to any additional packages that
+ * should be added to the bundle as dynamic imports.
+ *
+ * <p>
+ * After weaving is {@link #isWeavingComplete() complete}, this object becomes
+ * effectively immutable.
+ *
+ * @NotThreadSafe
+ * @noimplement
+ * @version $Id: c689a4c27dc39af1bf5f51338f1a8eaca1dddc1a $
+ */
+public interface WovenClass {
+
+ /**
+ * Returns the class file bytes to be used to define the
+ * {@link WovenClass#getClassName() named} class.
+ *
+ * <p>
+ * While weaving is not {@link #isWeavingComplete() complete}, this method
+ * returns a reference to the class files byte array contained in this
+ * object. After weaving is {@link #isWeavingComplete() complete}, this
+ * object becomes effectively immutable and a copy of the class file byte
+ * array is returned.
+ *
+ * @return The bytes to be used to define the
+ * {@link WovenClass#getClassName() named} class.
+ * @throws SecurityException If the caller does not have
+ * {@code AdminPermission[bundle,WEAVE]} and the Java runtime
+ * environment supports permissions.
+ */
+ public byte[] getBytes();
+
+ /**
+ * Set the class file bytes to be used to define the
+ * {@link WovenClass#getClassName() named} class. This method must not be
+ * called outside invocations of the {@link WeavingHook#weave(WovenClass)
+ * weave} method by the framework.
+ *
+ * <p>
+ * While weaving is not {@link #isWeavingComplete() complete}, this method
+ * replaces the reference to the array contained in this object with the
+ * specified array. After weaving is {@link #isWeavingComplete() complete},
+ * this object becomes effectively immutable and this method will throw an
+ * {@link IllegalStateException}.
+ *
+ * @param newBytes The new classfile that will be used to define the
+ * {@link WovenClass#getClassName() named} class. The specified array
+ * is retained by this object and the caller must not modify the
+ * specified array.
+ * @throws NullPointerException If newBytes is {@code null}.
+ * @throws IllegalStateException If weaving is {@link #isWeavingComplete()
+ * complete}.
+ * @throws SecurityException If the caller does not have
+ * {@code AdminPermission[bundle,WEAVE]} and the Java runtime
+ * environment supports permissions.
+ */
+ public void setBytes(byte[] newBytes);
+
+ /**
+ * Returns the list of dynamic import package descriptions to add to the
+ * {@link #getBundleWiring() bundle wiring} for this woven class. Changes
+ * made to the returned list will be visible to later {@link WeavingHook
+ * weaving hooks} called with this object. The returned list must not be
+ * modified outside invocations of the {@link WeavingHook#weave(WovenClass)
+ * weave} method by the framework.
+ *
+ * <p>
+ * After weaving is {@link #isWeavingComplete() complete}, this object
+ * becomes effectively immutable and the returned list will be unmodifiable.
+ *
+ * <p>
+ * If the Java runtime environment supports permissions, the caller must
+ * have {@code AdminPermission[bundle,WEAVE]} to modify the returned list.
+ *
+ * @return A list containing zero or more dynamic import package
+ * descriptions to add to the bundle wiring for this woven class.
+ * This list must throw {@code IllegalArgumentException} if a
+ * malformed dynamic import package description is added.
+ * @see "Core Specification, Dynamic Import Package, for the syntax of a dynamic import package description."
+ */
+ public List<String> getDynamicImports();
+
+ /**
+ * Returns whether weaving is complete in this woven class. Weaving is
+ * complete after the last {@link WeavingHook weaving hook} is called and
+ * the class is defined.
+ *
+ * <p>
+ * After weaving is complete, this object becomes effectively immutable.
+ *
+ * @return {@code true} weaving is complete, {@code false} otherwise.
+ */
+ public boolean isWeavingComplete();
+
+ /**
+ * Returns the fully qualified name of the class being woven.
+ *
+ * @return The fully qualified name of the class being woven.
+ */
+ public String getClassName();
+
+ /**
+ * Returns the protection domain to which the woven class will be assigned
+ * when it is defined.
+ *
+ * @return The protection domain to which the woven class will be assigned
+ * when it is defined, or {@code null} if no protection domain will
+ * be assigned.
+ */
+ public ProtectionDomain getProtectionDomain();
+
+ /**
+ * Returns the class associated with this woven class. When loading a class
+ * for the first time this method will return {@code null} until weaving is
+ * {@link #isWeavingComplete() complete}. Once weaving is complete, this
+ * method will return the class object.
+ *
+ * @return The class associated with this woven class, or {@code null} if
+ * weaving is not complete or the class definition failed.
+ */
+ public Class< ? > getDefinedClass();
+
+ /**
+ * Returns the bundle wiring whose class loader will define the woven class.
+ *
+ * @return The bundle wiring whose class loader will define the woven class.
+ */
+ public BundleWiring getBundleWiring();
+}
diff --git a/framework/src/main/java/org/osgi/framework/launch/Framework.java b/framework/src/main/java/org/osgi/framework/launch/Framework.java
index f7618aa..672db44 100644
--- a/framework/src/main/java/org/osgi/framework/launch/Framework.java
+++ b/framework/src/main/java/org/osgi/framework/launch/Framework.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2008, 2009). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2008, 2010). 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.
@@ -17,6 +17,8 @@
package org.osgi.framework.launch;
import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
@@ -32,7 +34,8 @@
* instance.
*
* @ThreadSafe
- * @version $Revision: 6542 $
+ * @noimplement
+ * @version $Id: 2be857d06f3605a04f701b59f11e127c0f8940dc $
*/
public interface Framework extends Bundle {
@@ -40,14 +43,17 @@
* Initialize this Framework. After calling this method, this Framework
* must:
* <ul>
+ * <li>Have generated a new {@link Constants#FRAMEWORK_UUID framework UUID}.
+ * </li>
* <li>Be in the {@link #STARTING} state.</li>
* <li>Have a valid Bundle Context.</li>
* <li>Be at start level 0.</li>
* <li>Have event handling enabled.</li>
* <li>Have reified Bundle objects for all installed bundles.</li>
* <li>Have registered any framework services. For example,
- * <code>PackageAdmin</code>, <code>ConditionalPermissionAdmin</code>,
- * <code>StartLevel</code>.</li>
+ * {@code ConditionalPermissionAdmin}.</li>
+ * <li>Be {@link #adapt(Class) adaptable} to the OSGi defined types to which
+ * a system bundle can be adapted.</li>
* </ul>
*
* <p>
@@ -61,8 +67,8 @@
* @throws BundleException If this Framework could not be initialized.
* @throws SecurityException If the Java Runtime Environment supports
* permissions and the caller does not have the appropriate
- * <code>AdminPermission[this,EXECUTE]</code> or if there is a
- * security manager already installed and the
+ * {@code AdminPermission[this,EXECUTE]} or if there is a security
+ * manager already installed and the
* {@link Constants#FRAMEWORK_SECURITY} configuration property is
* set.
*
@@ -70,8 +76,8 @@
void init() throws BundleException;
/**
- * Wait until this Framework has completely stopped. The <code>stop</code>
- * and <code>update</code> methods on a Framework performs an asynchronous
+ * Wait until this Framework has completely stopped. The {@code stop}
+ * and {@code update} methods on a Framework performs an asynchronous
* stop of the Framework. This method can be used to wait until the
* asynchronous stop of this Framework has completed. This method will only
* wait if called when this Framework is in the {@link #STARTING},
@@ -84,7 +90,7 @@
* Framework has completely stopped. A value of zero will wait
* indefinitely.
* @return A Framework Event indicating the reason this method returned. The
- * following <code>FrameworkEvent</code> types may be returned by
+ * following {@code FrameworkEvent} types may be returned by
* this method.
* <ul>
* <li>{@link FrameworkEvent#STOPPED STOPPED} - This Framework has
@@ -98,7 +104,7 @@
* STOPPED_BOOTCLASSPATH_MODIFIED} - This Framework has been stopped
* and a bootclasspath extension bundle has been installed or
* updated. The VM must be restarted in order for the changed boot
- * class path to take affect. </li>
+ * class path to take effect. </li>
*
* <li>{@link FrameworkEvent#ERROR ERROR} - The Framework
* encountered an error while shutting down or an error has occurred
@@ -127,12 +133,10 @@
* <li>All installed bundles must be started in accordance with each
* bundle's persistent <i>autostart setting</i>. This means some bundles
* will not be started, some will be started with <i>eager activation</i>
- * and some will be started with their <i>declared activation</i> policy. If
- * this Framework implements the optional <i>Start Level Service
- * Specification</i>, then the start level of this Framework is moved to the
- * start level specified by the
- * {@link Constants#FRAMEWORK_BEGINNING_STARTLEVEL beginning start level}
- * framework property, as described in the <i>Start Level Service
+ * and some will be started with their <i>declared activation</i> policy.
+ * The start level of this Framework is moved to the start level specified
+ * by the {@link Constants#FRAMEWORK_BEGINNING_STARTLEVEL beginning start
+ * level} framework property, as described in the <i>Start Level
* Specification</i>. If this framework property is not specified, then the
* start level of this Framework is moved to start level one (1). Any
* exceptions that occur during bundle starting must be wrapped in a
@@ -144,9 +148,9 @@
*
* @throws BundleException If this Framework could not be started.
* @throws SecurityException If the caller does not have the appropriate
- * <code>AdminPermission[this,EXECUTE]</code>, and the Java Runtime
+ * {@code AdminPermission[this,EXECUTE]}, and the Java Runtime
* Environment supports permissions.
- * @see "Start Level Service Specification"
+ * @see "Start Level Specification"
*/
void start() throws BundleException;
@@ -160,7 +164,7 @@
* @param options Ignored. There are no start options for the Framework.
* @throws BundleException If this Framework could not be started.
* @throws SecurityException If the caller does not have the appropriate
- * <code>AdminPermission[this,EXECUTE]</code>, and the Java Runtime
+ * {@code AdminPermission[this,EXECUTE]}, and the Java Runtime
* Environment supports permissions.
* @see #start()
*/
@@ -175,12 +179,11 @@
* <ol>
* <li>This Framework's state is set to {@link #STOPPING}.</li>
* <li>All installed bundles must be stopped without changing each bundle's
- * persistent <i>autostart setting</i>. If this Framework implements the
- * optional <i>Start Level Service Specification</i>, then the start level
- * of this Framework is moved to start level zero (0), as described in the
- * <i>Start Level Service Specification</i>. Any exceptions that occur
- * during bundle stopping must be wrapped in a {@link BundleException} and
- * then published as a framework event of type {@link FrameworkEvent#ERROR}</li>
+ * persistent <i>autostart setting</i>. The start level of this Framework is
+ * moved to start level zero (0), as described in the <i>Start Level
+ * Specification</i>. Any exceptions that occur during bundle stopping must
+ * be wrapped in a {@link BundleException} and then published as a framework
+ * event of type {@link FrameworkEvent#ERROR}</li>
* <li>Unregister all services registered by this Framework.</li>
* <li>Event handling is disabled.</li>
* <li>This Framework's state is set to {@link #RESOLVED}.</li>
@@ -196,9 +199,9 @@
* @throws BundleException If stopping this Framework could not be
* initiated.
* @throws SecurityException If the caller does not have the appropriate
- * <code>AdminPermission[this,EXECUTE]</code>, and the Java Runtime
+ * {@code AdminPermission[this,EXECUTE]}, and the Java Runtime
* Environment supports permissions.
- * @see "Start Level Service Specification"
+ * @see "Start Level Specification"
*/
void stop() throws BundleException;
@@ -213,7 +216,7 @@
* @throws BundleException If stopping this Framework could not be
* initiated.
* @throws SecurityException If the caller does not have the appropriate
- * <code>AdminPermission[this,EXECUTE]</code>, and the Java Runtime
+ * {@code AdminPermission[this,EXECUTE]}, and the Java Runtime
* Environment supports permissions.
* @see #stop()
*/
@@ -227,7 +230,7 @@
*
* @throws BundleException This Framework cannot be uninstalled.
* @throws SecurityException If the caller does not have the appropriate
- * <code>AdminPermission[this,LIFECYCLE]</code>, and the Java
+ * {@code AdminPermission[this,LIFECYCLE]}, and the Java
* Runtime Environment supports permissions.
*/
void uninstall() throws BundleException;
@@ -248,7 +251,7 @@
* @throws BundleException If stopping and restarting this Framework could
* not be initiated.
* @throws SecurityException If the caller does not have the appropriate
- * <code>AdminPermission[this,LIFECYCLE]</code>, and the Java
+ * {@code AdminPermission[this,LIFECYCLE]}, and the Java
* Runtime Environment supports permissions.
*/
void update() throws BundleException;
@@ -265,7 +268,7 @@
* @throws BundleException If stopping and restarting this Framework could
* not be initiated.
* @throws SecurityException If the caller does not have the appropriate
- * <code>AdminPermission[this,LIFECYCLE]</code>, and the Java
+ * {@code AdminPermission[this,LIFECYCLE]}, and the Java
* Runtime Environment supports permissions.
*/
void update(InputStream in) throws BundleException;
@@ -281,12 +284,12 @@
/**
* Returns the Framework location identifier. This Framework is assigned the
- * unique location "<code>System Bundle</code>" since this
+ * unique location "{@code System Bundle}" since this
* Framework is also a System Bundle.
*
- * @return The string "<code>System Bundle</code>".
+ * @return The string "{@code System Bundle}".
* @throws SecurityException If the caller does not have the appropriate
- * <code>AdminPermission[this,METADATA]</code>, and the Java Runtime
+ * {@code AdminPermission[this,METADATA]}, and the Java Runtime
* Environment supports permissions.
* @see Bundle#getLocation()
* @see Constants#SYSTEM_BUNDLE_LOCATION
@@ -296,7 +299,7 @@
/**
* Returns the symbolic name of this Framework. The symbolic name is unique
* for the implementation of the framework. However, the symbolic name
- * "<code>system.bundle</code>" must be recognized as an alias to
+ * "{@code system.bundle}" must be recognized as an alias to
* the implementation-defined symbolic name since this Framework is also a
* System Bundle.
*
@@ -305,4 +308,56 @@
* @see Constants#SYSTEM_BUNDLE_SYMBOLICNAME
*/
String getSymbolicName();
+
+ /**
+ * Returns {@code null} as a framework implementation does not have a
+ * proper bundle from which to return entry paths.
+ *
+ * @param path Ignored.
+ * @return {@code null} as a framework implementation does not have a
+ * proper bundle from which to return entry paths.
+ */
+ Enumeration<String> getEntryPaths(String path);
+
+ /**
+ * Returns {@code null} as a framework implementation does not have a
+ * proper bundle from which to return an entry.
+ *
+ * @param path Ignored.
+ * @return {@code null} as a framework implementation does not have a
+ * proper bundle from which to return an entry.
+ */
+ URL getEntry(String path);
+
+ /**
+ * Returns {@code null} as a framework implementation does not have a proper
+ * bundle from which to return entries.
+ *
+ * @param path Ignored.
+ * @param filePattern Ignored.
+ * @param recurse Ignored.
+ * @return {@code null} as a framework implementation does not have a proper
+ * bundle from which to return entries.
+ */
+ Enumeration<URL> findEntries(String path, String filePattern,
+ boolean recurse);
+
+ /**
+ * Adapt this Framework to the specified type.
+ *
+ * <p>
+ * Adapting this Framework to the specified type may require certain checks,
+ * including security checks, to succeed. If a check does not succeed, then
+ * this Framework cannot be adapted and {@code null} is returned. If this
+ * Framework is not {@link #init() initialized}, then {@code null} is
+ * returned if the specified type is one of the OSGi defined types to which
+ * a system bundle can be adapted.
+ *
+ * @param <A> The type to which this Framework is to be adapted.
+ * @param type Class object for the type to which this Framework is to be
+ * adapted.
+ * @return The object, of the specified type, to which this Framework has
+ * been adapted or {@code null} if this Framework cannot be adapted
+ */
+ <A> A adapt(Class<A> type);
}
diff --git a/framework/src/main/java/org/osgi/framework/launch/FrameworkFactory.java b/framework/src/main/java/org/osgi/framework/launch/FrameworkFactory.java
index bcb6da3..649ef4b 100644
--- a/framework/src/main/java/org/osgi/framework/launch/FrameworkFactory.java
+++ b/framework/src/main/java/org/osgi/framework/launch/FrameworkFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2009). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2009, 2010). 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.
@@ -41,11 +41,12 @@
* the resource and then load and construct a FrameworkFactory object for the
* framework implementation. The FrameworkFactory implementation class must have
* a public, no-argument constructor. Java™ SE 6 introduced the
- * <code>ServiceLoader</code> class which can create a FrameworkFactory instance
+ * {@code ServiceLoader} class which can create a FrameworkFactory instance
* from the resource.
*
* @ThreadSafe
- * @version $Revision: 6888 $
+ * @noimplement
+ * @version $Id: c370e19dba77231f0dbf1601218ad97b20391ea0 $
*/
public interface FrameworkFactory {
@@ -58,15 +59,15 @@
* use some reasonable default configuration appropriate for the
* current VM. For example, the system packages for the current
* execution environment should be properly exported. The specified
- * configuration argument may be <code>null</code>. The created
+ * configuration argument may be {@code null}. The created
* framework instance must copy any information needed from the
* specified configuration argument since the configuration argument
* can be changed after the framework instance has been created.
* @return A new, configured {@link Framework} instance. The framework
* instance must be in the {@link Bundle#INSTALLED} state.
* @throws SecurityException If the caller does not have
- * <code>AllPermission</code>, and the Java Runtime Environment
+ * {@code AllPermission}, and the Java Runtime Environment
* supports permissions.
*/
- Framework newFramework(Map configuration);
+ Framework newFramework(Map<String, String> configuration);
}
diff --git a/framework/src/main/java/org/osgi/service/packageadmin/ExportedPackage.java b/framework/src/main/java/org/osgi/service/packageadmin/ExportedPackage.java
index 67ba3e9..abe1515 100644
--- a/framework/src/main/java/org/osgi/service/packageadmin/ExportedPackage.java
+++ b/framework/src/main/java/org/osgi/service/packageadmin/ExportedPackage.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2001, 2008). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2001, 2010). 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.
@@ -31,18 +31,21 @@
*
* <p>
* The information about an exported package provided by this object may change.
- * An <code>ExportedPackage</code> object becomes stale if the package it
+ * An {@code ExportedPackage} object becomes stale if the package it
* references has been updated or removed as a result of calling
- * <code>PackageAdmin.refreshPackages()</code>.
+ * {@code PackageAdmin.refreshPackages()}.
*
- * If this object becomes stale, its <code>getName()</code> and
- * <code>getVersion()</code> methods continue to return their original values,
- * <code>isRemovalPending()</code> returns <code>true</code>, and
- * <code>getExportingBundle()</code> and <code>getImportingBundles()</code>
- * return <code>null</code>.
+ * If this object becomes stale, its {@code getName()} and
+ * {@code getVersion()} methods continue to return their original values,
+ * {@code isRemovalPending()} returns {@code true}, and
+ * {@code getExportingBundle()} and {@code getImportingBundles()}
+ * return {@code null}.
*
* @ThreadSafe
- * @version $Revision: 5673 $
+ * @noimplement
+ * @deprecated The PackageAdmin service has been replaced by the
+ * <code>org.osgi.framework.wiring</code> package.
+ * @version $Id: c56b99465e3f62a9808297a47de8cb7edb802119 $
*/
public interface ExportedPackage {
/**
@@ -56,8 +59,8 @@
* Returns the bundle exporting the package associated with this exported
* package.
*
- * @return The exporting bundle, or <code>null</code> if this
- * <code>ExportedPackage</code> object has become stale.
+ * @return The exporting bundle, or {@code null} if this
+ * {@code ExportedPackage} object has become stale.
*/
public Bundle getExportingBundle();
@@ -71,8 +74,8 @@
* in the returned array. See {@link RequiredBundle#getRequiringBundles()}.
*
* @return The array of resolved bundles currently wired to this exported
- * package, or <code>null</code> if this
- * <code>ExportedPackage</code> object has become stale. The array
+ * package, or {@code null} if this
+ * {@code ExportedPackage} object has become stale. The array
* will be empty if no bundles are wired to this exported package.
*/
public Bundle[] getImportingBundles();
@@ -80,7 +83,7 @@
/**
* Returns the version of this exported package.
*
- * @return The version of this exported package, or <code>null</code> if
+ * @return The version of this exported package, or {@code null} if
* no version information is available.
* @deprecated As of 1.2, replaced by {@link #getVersion}.
*/
@@ -97,14 +100,14 @@
public Version getVersion();
/**
- * Returns <code>true</code> if the package associated with this
- * <code>ExportedPackage</code> object has been exported by a bundle that
+ * Returns {@code true} if the package associated with this
+ * {@code ExportedPackage} object has been exported by a bundle that
* has been updated or uninstalled.
*
- * @return <code>true</code> if the associated package is being exported
+ * @return {@code true} if the associated package is being exported
* by a bundle that has been updated or uninstalled, or if this
- * <code>ExportedPackage</code> object has become stale;
- * <code>false</code> otherwise.
+ * {@code ExportedPackage} object has become stale;
+ * {@code false} otherwise.
*/
public boolean isRemovalPending();
}
diff --git a/framework/src/main/java/org/osgi/service/packageadmin/PackageAdmin.java b/framework/src/main/java/org/osgi/service/packageadmin/PackageAdmin.java
index c93cd28..2c57890 100644
--- a/framework/src/main/java/org/osgi/service/packageadmin/PackageAdmin.java
+++ b/framework/src/main/java/org/osgi/service/packageadmin/PackageAdmin.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2001, 2009). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2001, 2010). 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.
@@ -28,7 +28,10 @@
* with the Framework.
*
* @ThreadSafe
- * @version $Revision: 6779 $
+ * @noimplement
+ * @version $Id: a268c3bdc986080fa16bdb2f56ba1d3800d030dd $
+ * @deprecated This service has been replaced by the
+ * <code>org.osgi.framework.wiring</code> package.
* @see org.osgi.service.packageadmin.ExportedPackage
* @see org.osgi.service.packageadmin.RequiredBundle
*/
@@ -37,19 +40,19 @@
* Gets the exported packages for the specified bundle.
*
* @param bundle The bundle whose exported packages are to be returned, or
- * <code>null</code> if all exported packages are to be returned. If
+ * {@code null} if all exported packages are to be returned. If
* the specified bundle is the system bundle (that is, the bundle
* with id zero), this method returns all the packages known to be
* exported by the system bundle. This will include the package
- * specified by the <code>org.osgi.framework.system.packages</code>
+ * specified by the {@code org.osgi.framework.system.packages}
* system property as well as any other package exported by the
* framework implementation.
*
- * @return An array of exported packages, or <code>null</code> if the
+ * @return An array of exported packages, or {@code null} if the
* specified bundle has no exported packages.
- * @throws IllegalArgumentException If the specified <code>Bundle</code> was
+ * @throws IllegalArgumentException If the specified {@code Bundle} was
* not created by the same framework instance that registered this
- * <code>PackageAdmin</code> service.
+ * {@code PackageAdmin} service.
*/
public ExportedPackage[] getExportedPackages(Bundle bundle);
@@ -58,7 +61,7 @@
*
* @param name The name of the exported packages to be returned.
*
- * @return An array of the exported packages, or <code>null</code> if no
+ * @return An array of the exported packages, or {@code null} if no
* exported packages with the specified name exists.
* @since 1.2
*/
@@ -73,7 +76,7 @@
*
* @param name The name of the exported package to be returned.
*
- * @return The exported package, or <code>null</code> if no exported
+ * @return The exported package, or {@code null} if no exported
* package with the specified name exists.
* @see #getExportedPackages(String)
*/
@@ -101,49 +104,49 @@
* graph any bundle that is wired to a package that is currently exported by
* a bundle in the graph. The graph is fully constructed when there is no
* bundle outside the graph that is wired to a bundle in the graph. The
- * graph may contain <code>UNINSTALLED</code> bundles that are currently
+ * graph may contain {@code UNINSTALLED} bundles that are currently
* still exporting packages.
*
- * <li>Each bundle in the graph that is in the <code>ACTIVE</code> state
- * will be stopped as described in the <code>Bundle.stop</code> method.
+ * <li>Each bundle in the graph that is in the {@code ACTIVE} state
+ * will be stopped as described in the {@code Bundle.stop} method.
*
- * <li>Each bundle in the graph that is in the <code>RESOLVED</code> state
- * is unresolved and thus moved to the <code>INSTALLED</code> state. The
+ * <li>Each bundle in the graph that is in the {@code RESOLVED} state
+ * is unresolved and thus moved to the {@code INSTALLED} state. The
* effect of this step is that bundles in the graph are no longer
- * <code>RESOLVED</code>.
+ * {@code RESOLVED}.
*
- * <li>Each bundle in the graph that is in the <code>UNINSTALLED</code>
+ * <li>Each bundle in the graph that is in the {@code UNINSTALLED}
* state is removed from the graph and is now completely removed from the
* Framework.
*
- * <li>Each bundle in the graph that was in the <code>ACTIVE</code> state
- * prior to Step 2 is started as described in the <code>Bundle.start</code>
+ * <li>Each bundle in the graph that was in the {@code ACTIVE} state
+ * prior to Step 2 is started as described in the {@code Bundle.start}
* method, causing all bundles required for the restart to be resolved. It
* is possible that, as a result of the previous steps, packages that were
* previously exported no longer are. Therefore, some bundles may be
* unresolvable until another bundle offering a compatible package for
* export has been installed in the Framework.
* <li>A framework event of type
- * <code>FrameworkEvent.PACKAGES_REFRESHED</code> is fired.
+ * {@code FrameworkEvent.PACKAGES_REFRESHED} is fired.
* </ol>
*
* <p>
* For any exceptions that are thrown during any of these steps, a
- * <code>FrameworkEvent</code> of type <code>ERROR</code> is fired
+ * {@code FrameworkEvent} of type {@code ERROR} is fired
* containing the exception. The source bundle for these events should be
* the specific bundle to which the exception is related. If no specific
* bundle can be associated with the exception then the System Bundle must
* be used as the source bundle for the event.
*
* @param bundles The bundles whose exported packages are to be updated or
- * removed, or <code>null</code> for all bundles updated or
+ * removed, or {@code null} for all bundles updated or
* uninstalled since the last call to this method.
* @throws SecurityException If the caller does not have
- * <code>AdminPermission[System Bundle,RESOLVE]</code> and the Java
+ * {@code AdminPermission[System Bundle,RESOLVE]} and the Java
* runtime environment supports permissions.
- * @throws IllegalArgumentException If the specified <code>Bundle</code>s
+ * @throws IllegalArgumentException If the specified {@code Bundle}s
* were not created by the same framework instance that registered
- * this <code>PackageAdmin</code> service.
+ * this {@code PackageAdmin} service.
*/
public void refreshPackages(Bundle[] bundles);
@@ -155,20 +158,20 @@
* resolve all unresolved bundles installed in the framework.
*
* <p>
- * If <code>null</code> is specified then the Framework will attempt to
+ * If {@code null} is specified then the Framework will attempt to
* resolve all unresolved bundles. This method must not cause any bundle to
* be refreshed, stopped, or started. This method will not return until the
* operation has completed.
*
- * @param bundles The bundles to resolve or <code>null</code> to resolve all
+ * @param bundles The bundles to resolve or {@code null} to resolve all
* unresolved bundles installed in the Framework.
- * @return <code>true</code> if all specified bundles are resolved;
+ * @return {@code true} if all specified bundles are resolved;
* @throws SecurityException If the caller does not have
- * <code>AdminPermission[System Bundle,RESOLVE]</code> and the Java
+ * {@code AdminPermission[System Bundle,RESOLVE]} and the Java
* runtime environment supports permissions.
- * @throws IllegalArgumentException If the specified <code>Bundle</code>s
+ * @throws IllegalArgumentException If the specified {@code Bundle}s
* were not created by the same framework instance that registered
- * this <code>PackageAdmin</code> service.
+ * this {@code PackageAdmin} service.
* @since 1.2
*/
public boolean resolveBundles(Bundle[] bundles);
@@ -177,12 +180,12 @@
* Returns an array of required bundles having the specified symbolic name.
*
* <p>
- * If <code>null</code> is specified, then all required bundles will be
+ * If {@code null} is specified, then all required bundles will be
* returned.
*
- * @param symbolicName The bundle symbolic name or <code>null</code> for
+ * @param symbolicName The bundle symbolic name or {@code null} for
* all required bundles.
- * @return An array of required bundles or <code>null</code> if no
+ * @return An array of required bundles or {@code null} if no
* required bundles exist for the specified symbolic name.
* @since 1.2
*/
@@ -191,7 +194,7 @@
/**
* Returns the bundles with the specified symbolic name whose bundle version
* is within the specified version range. If no bundles are installed that
- * have the specified symbolic name, then <code>null</code> is returned.
+ * have the specified symbolic name, then {@code null} is returned.
* If a version range is specified, then only the bundles that have the
* specified symbolic name and whose bundle versions belong to the specified
* version range are returned. The returned bundles are ordered by version
@@ -201,31 +204,31 @@
* @see org.osgi.framework.Constants#BUNDLE_VERSION_ATTRIBUTE
* @param symbolicName The symbolic name of the desired bundles.
* @param versionRange The version range of the desired bundles, or
- * <code>null</code> if all versions are desired.
+ * {@code null} if all versions are desired.
* @return An array of bundles with the specified name belonging to the
* specified version range ordered in descending version order, or
- * <code>null</code> if no bundles are found.
+ * {@code null} if no bundles are found.
* @since 1.2
*/
public Bundle[] getBundles(String symbolicName, String versionRange);
/**
* Returns an array of attached fragment bundles for the specified bundle.
- * If the specified bundle is a fragment then <code>null</code> is returned.
+ * If the specified bundle is a fragment then {@code null} is returned.
* If no fragments are attached to the specified bundle then
- * <code>null</code> is returned.
+ * {@code null} is returned.
* <p>
* This method does not attempt to resolve the specified bundle. If the
- * specified bundle is not resolved then <code>null</code> is returned.
+ * specified bundle is not resolved then {@code null} is returned.
*
* @param bundle The bundle whose attached fragment bundles are to be
* returned.
- * @return An array of fragment bundles or <code>null</code> if the bundle
+ * @return An array of fragment bundles or {@code null} if the bundle
* does not have any attached fragment bundles or the bundle is not
* resolved.
- * @throws IllegalArgumentException If the specified <code>Bundle</code> was
+ * @throws IllegalArgumentException If the specified {@code Bundle} was
* not created by the same framework instance that registered this
- * <code>PackageAdmin</code> service.
+ * {@code PackageAdmin} service.
* @since 1.2
*/
public Bundle[] getFragments(Bundle bundle);
@@ -236,11 +239,11 @@
*
* @param bundle The fragment bundle whose host bundles are to be returned.
* @return An array containing the host bundles to which the specified
- * fragment is attached or <code>null</code> if the specified bundle
+ * fragment is attached or {@code null} if the specified bundle
* is not a fragment or is not attached to any host bundles.
- * @throws IllegalArgumentException If the specified <code>Bundle</code> was
+ * @throws IllegalArgumentException If the specified {@code Bundle} was
* not created by the same framework instance that registered this
- * <code>PackageAdmin</code> service.
+ * {@code PackageAdmin} service.
* @since 1.2
*/
public Bundle[] getHosts(Bundle bundle);
@@ -249,13 +252,13 @@
* Returns the bundle from which the specified class is loaded. The class
* loader of the returned bundle must have been used to load the specified
* class. If the class was not loaded by a bundle class loader then
- * <code>null</code> is returned.
+ * {@code null} is returned.
*
* @param clazz The class object from which to locate the bundle.
* @return The bundle from which the specified class is loaded or
- * <code>null</code> if the class was not loaded by a bundle class
+ * {@code null} if the class was not loaded by a bundle class
* loader created by the same framework instance that registered
- * this <code>PackageAdmin</code> service.
+ * this {@code PackageAdmin} service.
* @since 1.2
*/
public Bundle getBundle(Class clazz);
@@ -264,7 +267,7 @@
* Bundle type indicating the bundle is a fragment bundle.
*
* <p>
- * The value of <code>BUNDLE_TYPE_FRAGMENT</code> is 0x00000001.
+ * The value of {@code BUNDLE_TYPE_FRAGMENT} is 0x00000001.
*
* @since 1.2
*/
@@ -286,9 +289,9 @@
*
* @param bundle The bundle for which to return the special type.
* @return The special type of the bundle.
- * @throws IllegalArgumentException If the specified <code>Bundle</code> was
+ * @throws IllegalArgumentException If the specified {@code Bundle} was
* not created by the same framework instance that registered this
- * <code>PackageAdmin</code> service.
+ * {@code PackageAdmin} service.
* @since 1.2
*/
public int getBundleType(Bundle bundle);
diff --git a/framework/src/main/java/org/osgi/service/packageadmin/RequiredBundle.java b/framework/src/main/java/org/osgi/service/packageadmin/RequiredBundle.java
index b15c5df..34c0b08 100644
--- a/framework/src/main/java/org/osgi/service/packageadmin/RequiredBundle.java
+++ b/framework/src/main/java/org/osgi/service/packageadmin/RequiredBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2004, 2008). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2004, 2010). 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.
@@ -25,25 +25,28 @@
* Objects implementing this interface are created by the Package Admin service.
*
* <p>
- * The term <i>required bundle</i> refers to a resolved bundle that has a
- * bundle symbolic name and is not a fragment. That is, a bundle that may be
- * required by other bundles. This bundle may or may not be currently required
- * by other bundles.
+ * The term <i>required bundle</i> refers to a resolved bundle that has a bundle
+ * symbolic name and is not a fragment. That is, a bundle that may be required
+ * by other bundles. This bundle may or may not be currently required by other
+ * bundles.
*
* <p>
* The information about a required bundle provided by this object may change. A
- * <code>RequiredBundle</code> object becomes stale if an exported package of
+ * {@code RequiredBundle} object becomes stale if an exported package of
* the bundle it references has been updated or removed as a result of calling
- * <code>PackageAdmin.refreshPackages()</code>).
+ * {@code PackageAdmin.refreshPackages()}).
*
- * If this object becomes stale, its <code>getSymbolicName()</code> and
- * <code>getVersion()</code> methods continue to return their original values,
- * <code>isRemovalPending()</code> returns true, and <code>getBundle()</code>
- * and <code>getRequiringBundles()</code> return <code>null</code>.
+ * If this object becomes stale, its {@code getSymbolicName()} and
+ * {@code getVersion()} methods continue to return their original values,
+ * {@code isRemovalPending()} returns true, and {@code getBundle()}
+ * and {@code getRequiringBundles()} return {@code null}.
*
* @since 1.2
* @ThreadSafe
- * @version $Revision: 5673 $
+ * @noimplement
+ * @deprecated The PackageAdmin service has been replaced by the
+ * <code>org.osgi.framework.wiring</code> package.
+ * @version $Id: 1606b0422cae6769b7eedc2d565df61841da1e22 $
*/
public interface RequiredBundle {
/**
@@ -56,8 +59,8 @@
/**
* Returns the bundle associated with this required bundle.
*
- * @return The bundle, or <code>null</code> if this
- * <code>RequiredBundle</code> object has become stale.
+ * @return The bundle, or {@code null} if this
+ * {@code RequiredBundle} object has become stale.
*/
public Bundle getBundle();
@@ -70,7 +73,7 @@
* included in the returned array.
*
* @return An array of bundles currently requiring this required bundle, or
- * <code>null</code> if this <code>RequiredBundle</code> object
+ * {@code null} if this {@code RequiredBundle} object
* has become stale. The array will be empty if no bundles require
* this required package.
*/
@@ -86,12 +89,12 @@
public Version getVersion();
/**
- * Returns <code>true</code> if the bundle associated with this
- * <code>RequiredBundle</code> object has been updated or uninstalled.
+ * Returns {@code true} if the bundle associated with this
+ * {@code RequiredBundle} object has been updated or uninstalled.
*
- * @return <code>true</code> if the required bundle has been updated or
- * uninstalled, or if the <code>RequiredBundle</code> object has
- * become stale; <code>false</code> otherwise.
+ * @return {@code true} if the required bundle has been updated or
+ * uninstalled, or if the {@code RequiredBundle} object has
+ * become stale; {@code false} otherwise.
*/
public boolean isRemovalPending();
}
diff --git a/framework/src/main/java/org/osgi/service/startlevel/StartLevel.java b/framework/src/main/java/org/osgi/service/startlevel/StartLevel.java
index 8a69b03..5efb41c 100644
--- a/framework/src/main/java/org/osgi/service/startlevel/StartLevel.java
+++ b/framework/src/main/java/org/osgi/service/startlevel/StartLevel.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2002, 2009). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 2010). 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.
@@ -31,7 +31,7 @@
* higher start level than 1.
* <p>
* Access to the StartLevel service is protected by corresponding
- * <code>ServicePermission</code>. In addition <code>AdminPermission</code>
+ * {@code ServicePermission}. In addition {@code AdminPermission}
* is required to actually modify start level information.
* <p>
* Start Level support in the Framework includes the ability to control the
@@ -48,17 +48,17 @@
* When the Framework is launched, the Framework will enter start level one and
* all bundles which are assigned to start level one and whose autostart setting
* indicates the bundle should be started are started as described in the
- * <code>Bundle.start</code> method. The Framework will continue to increase
+ * {@code Bundle.start} method. The Framework will continue to increase
* the start level, starting bundles at each start level, until the Framework
* has reached a beginning start level. At this point the Framework has
* completed starting bundles and will then fire a Framework event of type
- * <code>FrameworkEvent.STARTED</code> to announce it has completed its
+ * {@code FrameworkEvent.STARTED} to announce it has completed its
* launch.
*
* <p>
* Within a start level, bundles may be started in an order defined by the
* Framework implementation. This may be something like ascending
- * <code>Bundle.getBundleId</code> order or an order based upon dependencies
+ * {@code Bundle.getBundleId} order or an order based upon dependencies
* between bundles. A similar but reversed order may be used when stopping
* bundles within a start level.
*
@@ -67,7 +67,10 @@
* start level of the framework.
*
* @ThreadSafe
- * @version $Revision: 6747 $
+ * @noimplement
+ * @version $Id: bf1b71ed6c9f9d75785b26dccb34362017d93f4a $
+ * @deprecated This service has been replaced by the
+ * <code>org.osgi.framework.startlevel</code> package.
*/
public interface StartLevel {
/**
@@ -103,12 +106,12 @@
* the {@link Bundle#start(int)} method using the
* {@link Bundle#START_TRANSIENT} option. The
* {@link Bundle#START_ACTIVATION_POLICY} option must also be used if
- * {@link #isBundleActivationPolicyUsed(Bundle)} returns <code>true</code>
+ * {@link #isBundleActivationPolicyUsed(Bundle)} returns {@code true}
* for the bundle.
* </ol>
* When this process completes after the specified start level is reached,
* the Framework will fire a Framework event of type
- * <code>FrameworkEvent.STARTLEVEL_CHANGED</code> to announce it has moved
+ * {@code FrameworkEvent.STARTLEVEL_CHANGED} to announce it has moved
* to the specified start level.
*
* <p>
@@ -126,13 +129,13 @@
* </ol>
* When this process completes after the specified start level is reached,
* the Framework will fire a Framework event of type
- * <code>FrameworkEvent.STARTLEVEL_CHANGED</code> to announce it has moved
+ * {@code FrameworkEvent.STARTLEVEL_CHANGED} to announce it has moved
* to the specified start level.
*
* <p>
* If the specified start level is equal to the active start level, then no
* bundles are started or stopped, however, the Framework must fire a
- * Framework event of type <code>FrameworkEvent.STARTLEVEL_CHANGED</code>
+ * Framework event of type {@code FrameworkEvent.STARTLEVEL_CHANGED}
* to announce it has finished moving to the specified start level. This
* event may arrive before this method return.
*
@@ -140,7 +143,7 @@
* @throws IllegalArgumentException If the specified start level is less
* than or equal to zero.
* @throws SecurityException If the caller does not have
- * <code>AdminPermission[System Bundle,STARTLEVEL]</code> and the
+ * {@code AdminPermission[System Bundle,STARTLEVEL]} and the
* Java runtime environment supports permissions.
*/
public void setStartLevel(int startlevel);
@@ -153,7 +156,7 @@
* @throws java.lang.IllegalArgumentException If the specified bundle has
* been uninstalled or if the specified bundle was not created by
* the same framework instance that registered this
- * <code>StartLevel</code> service.
+ * {@code StartLevel} service.
*/
public int getBundleStartLevel(Bundle bundle);
@@ -171,7 +174,7 @@
* specified bundle as described in the {@link Bundle#start(int)} method
* using the {@link Bundle#START_TRANSIENT} option. The
* {@link Bundle#START_ACTIVATION_POLICY} option must also be used if
- * {@link #isBundleActivationPolicyUsed(Bundle)} returns <code>true</code>
+ * {@link #isBundleActivationPolicyUsed(Bundle)} returns {@code true}
* for the bundle. The actual starting of this bundle must occur
* asynchronously.
* <p>
@@ -187,9 +190,9 @@
* uninstalled, or if the specified start level is less than or
* equal to zero, or if the specified bundle is the system bundle,
* or if the specified bundle was not created by the same framework
- * instance that registered this <code>StartLevel</code> service.
+ * instance that registered this {@code StartLevel} service.
* @throws SecurityException If the caller does not have
- * <code>AdminPermission[bundle,EXECUTE]</code> and the Java runtime
+ * {@code AdminPermission[bundle,EXECUTE]} and the Java runtime
* environment supports permissions.
*/
public void setBundleStartLevel(Bundle bundle, int startlevel);
@@ -213,7 +216,7 @@
* Framework.
*
* <p>
- * When a Bundle is installed via <code>BundleContext.installBundle</code>,
+ * When a Bundle is installed via {@code BundleContext.installBundle},
* it is assigned the initial bundle start level value.
*
* <p>
@@ -227,7 +230,7 @@
* @throws IllegalArgumentException If the specified start level is less
* than or equal to zero.
* @throws SecurityException If the caller does not have
- * <code>AdminPermission[System Bundle,STARTLEVEL]</code> and the
+ * {@code AdminPermission[System Bundle,STARTLEVEL]} and the
* Java runtime environment supports permissions.
*/
public void setInitialBundleStartLevel(int startlevel);
@@ -240,13 +243,13 @@
* started when its start level is reached.
*
* @param bundle The bundle whose autostart setting is to be examined.
- * @return <code>true</code> if the autostart setting of the bundle
- * indicates the bundle is to be started. <code>false</code>
+ * @return {@code true} if the autostart setting of the bundle
+ * indicates the bundle is to be started. {@code false}
* otherwise.
* @throws java.lang.IllegalArgumentException If the specified bundle has
* been uninstalled or if the specified bundle was not created by
* the same framework instance that registered this
- * <code>StartLevel</code> service.
+ * {@code StartLevel} service.
* @see Bundle#START_TRANSIENT
*/
public boolean isBundlePersistentlyStarted(Bundle bundle);
@@ -259,13 +262,13 @@
* activation policy is to be used when the bundle is started.
*
* @param bundle The bundle whose autostart setting is to be examined.
- * @return <code>true</code> if the bundle's autostart setting indicates the
+ * @return {@code true} if the bundle's autostart setting indicates the
* activation policy declared in the manifest must be used.
- * <code>false</code> if the bundle must be eagerly activated.
+ * {@code false} if the bundle must be eagerly activated.
* @throws java.lang.IllegalArgumentException If the specified bundle has
* been uninstalled or if the specified bundle was not created by
* the same framework instance that registered this
- * <code>StartLevel</code> service.
+ * {@code StartLevel} service.
* @since 1.1
* @see Bundle#START_ACTIVATION_POLICY
*/
diff --git a/framework/src/main/java/org/osgi/service/url/AbstractURLStreamHandlerService.java b/framework/src/main/java/org/osgi/service/url/AbstractURLStreamHandlerService.java
index 1ad37a2..c20a051 100644
--- a/framework/src/main/java/org/osgi/service/url/AbstractURLStreamHandlerService.java
+++ b/framework/src/main/java/org/osgi/service/url/AbstractURLStreamHandlerService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2002, 2008). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 2010). 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.
@@ -19,16 +19,16 @@
import java.net.*;
/**
- * Abstract implementation of the <code>URLStreamHandlerService</code>
+ * Abstract implementation of the {@code URLStreamHandlerService}
* interface. All the methods simply invoke the corresponding methods on
- * <code>java.net.URLStreamHandler</code> except for <code>parseURL</code>
- * and <code>setURL</code>, which use the <code>URLStreamHandlerSetter</code>
+ * {@code java.net.URLStreamHandler} except for {@code parseURL}
+ * and {@code setURL}, which use the {@code URLStreamHandlerSetter}
* parameter. Subclasses of this abstract class should not need to override the
- * <code>setURL</code> and <code>parseURL(URLStreamHandlerSetter,...)</code>
+ * {@code setURL} and {@code parseURL(URLStreamHandlerSetter,...)}
* methods.
*
* @ThreadSafe
- * @version $Revision: 5673 $
+ * @version $Id: 465a0ed86f5d49b338ffc6a13bb68f60f04e54d6 $
*/
public abstract class AbstractURLStreamHandlerService extends URLStreamHandler
implements URLStreamHandlerService {
@@ -39,18 +39,18 @@
throws java.io.IOException;
/**
- * The <code>URLStreamHandlerSetter</code> object passed to the parseURL
+ * The {@code URLStreamHandlerSetter} object passed to the parseURL
* method.
*/
protected volatile URLStreamHandlerSetter realHandler;
/**
- * Parse a URL using the <code>URLStreamHandlerSetter</code> object. This
- * method sets the <code>realHandler</code> field with the specified
- * <code>URLStreamHandlerSetter</code> object and then calls
- * <code>parseURL(URL,String,int,int)</code>.
+ * Parse a URL using the {@code URLStreamHandlerSetter} object. This
+ * method sets the {@code realHandler} field with the specified
+ * {@code URLStreamHandlerSetter} object and then calls
+ * {@code parseURL(URL,String,int,int)}.
*
- * @param realHandler The object on which the <code>setURL</code> method
+ * @param realHandler The object on which the {@code setURL} method
* must be invoked for the specified URL.
* @see "java.net.URLStreamHandler.parseURL"
*/
@@ -61,7 +61,7 @@
}
/**
- * This method calls <code>super.toExternalForm</code>.
+ * This method calls {@code super.toExternalForm}.
*
* @see "java.net.URLStreamHandler.toExternalForm"
*/
@@ -70,7 +70,7 @@
}
/**
- * This method calls <code>super.equals(URL,URL)</code>.
+ * This method calls {@code super.equals(URL,URL)}.
*
* @see "java.net.URLStreamHandler.equals(URL,URL)"
*/
@@ -79,7 +79,7 @@
}
/**
- * This method calls <code>super.getDefaultPort</code>.
+ * This method calls {@code super.getDefaultPort}.
*
* @see "java.net.URLStreamHandler.getDefaultPort"
*/
@@ -88,7 +88,7 @@
}
/**
- * This method calls <code>super.getHostAddress</code>.
+ * This method calls {@code super.getHostAddress}.
*
* @see "java.net.URLStreamHandler.getHostAddress"
*/
@@ -97,7 +97,7 @@
}
/**
- * This method calls <code>super.hashCode(URL)</code>.
+ * This method calls {@code super.hashCode(URL)}.
*
* @see "java.net.URLStreamHandler.hashCode(URL)"
*/
@@ -106,7 +106,7 @@
}
/**
- * This method calls <code>super.hostsEqual</code>.
+ * This method calls {@code super.hostsEqual}.
*
* @see "java.net.URLStreamHandler.hostsEqual"
*/
@@ -115,7 +115,7 @@
}
/**
- * This method calls <code>super.sameFile</code>.
+ * This method calls {@code super.sameFile}.
*
* @see "java.net.URLStreamHandler.sameFile"
*/
@@ -125,7 +125,7 @@
/**
* This method calls
- * <code>realHandler.setURL(URL,String,String,int,String,String)</code>.
+ * {@code realHandler.setURL(URL,String,String,int,String,String)}.
*
* @see "java.net.URLStreamHandler.setURL(URL,String,String,int,String,String)"
* @deprecated This method is only for compatibility with handlers written
@@ -138,7 +138,7 @@
/**
* This method calls
- * <code>realHandler.setURL(URL,String,String,int,String,String,String,String)</code>.
+ * {@code realHandler.setURL(URL,String,String,int,String,String,String,String)}.
*
* @see "java.net.URLStreamHandler.setURL(URL,String,String,int,String,String,String,String)"
*/
diff --git a/framework/src/main/java/org/osgi/service/url/URLConstants.java b/framework/src/main/java/org/osgi/service/url/URLConstants.java
index ae95305..fbf768b 100644
--- a/framework/src/main/java/org/osgi/service/url/URLConstants.java
+++ b/framework/src/main/java/org/osgi/service/url/URLConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2002, 2008). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 2010). 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.
@@ -18,15 +18,16 @@
/**
* Defines standard names for property keys associated with
- * {@link URLStreamHandlerService} and <code>java.net.ContentHandler</code>
+ * {@link URLStreamHandlerService} and {@code java.net.ContentHandler}
* services.
*
* <p>
* The values associated with these keys are of type
- * <code>java.lang.String[]</code> or <code>java.lang.String</code>, unless
+ * {@code java.lang.String[]} or {@code java.lang.String}, unless
* otherwise indicated.
*
- * @version $Revision: 5673 $
+ * @noimplement
+ * @version $Id: 5ec8db316249f4b956fe083b986c11153d0fa8fe $
*/
public interface URLConstants {
/**
diff --git a/framework/src/main/java/org/osgi/service/url/URLStreamHandlerService.java b/framework/src/main/java/org/osgi/service/url/URLStreamHandlerService.java
index b1ff7d8..7cc5d6e 100644
--- a/framework/src/main/java/org/osgi/service/url/URLStreamHandlerService.java
+++ b/framework/src/main/java/org/osgi/service/url/URLStreamHandlerService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2002, 2008). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 2010). 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.
@@ -20,22 +20,22 @@
/**
* Service interface with public versions of the protected
- * <code>java.net.URLStreamHandler</code> methods.
+ * {@code java.net.URLStreamHandler} methods.
* <p>
* The important differences between this interface and the
- * <code>URLStreamHandler</code> class are that the <code>setURL</code>
- * method is absent and the <code>parseURL</code> method takes a
+ * {@code URLStreamHandler} class are that the {@code setURL}
+ * method is absent and the {@code parseURL} method takes a
* {@link URLStreamHandlerSetter} object as the first argument. Classes
- * implementing this interface must call the <code>setURL</code> method on the
- * <code>URLStreamHandlerSetter</code> object received in the
- * <code>parseURL</code> method instead of
- * <code>URLStreamHandler.setURL</code> to avoid a
- * <code>SecurityException</code>.
+ * implementing this interface must call the {@code setURL} method on the
+ * {@code URLStreamHandlerSetter} object received in the
+ * {@code parseURL} method instead of
+ * {@code URLStreamHandler.setURL} to avoid a
+ * {@code SecurityException}.
*
* @see AbstractURLStreamHandlerService
*
* @ThreadSafe
- * @version $Revision: 5673 $
+ * @version $Id: 4982ef5b407669975afe2856a9702246d2d9c2ba $
*/
public interface URLStreamHandlerService {
/**
@@ -44,11 +44,11 @@
public URLConnection openConnection(URL u) throws java.io.IOException;
/**
- * Parse a URL. This method is called by the <code>URLStreamHandler</code>
- * proxy, instead of <code>java.net.URLStreamHandler.parseURL</code>,
- * passing a <code>URLStreamHandlerSetter</code> object.
+ * Parse a URL. This method is called by the {@code URLStreamHandler}
+ * proxy, instead of {@code java.net.URLStreamHandler.parseURL},
+ * passing a {@code URLStreamHandlerSetter} object.
*
- * @param realHandler The object on which <code>setURL</code> must be
+ * @param realHandler The object on which {@code setURL} must be
* invoked for this URL.
* @see "java.net.URLStreamHandler.parseURL"
*/
diff --git a/framework/src/main/java/org/osgi/service/url/URLStreamHandlerSetter.java b/framework/src/main/java/org/osgi/service/url/URLStreamHandlerSetter.java
index 36bdce8..dd2e0c2 100644
--- a/framework/src/main/java/org/osgi/service/url/URLStreamHandlerSetter.java
+++ b/framework/src/main/java/org/osgi/service/url/URLStreamHandlerSetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2002, 2008). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 2010). 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.
@@ -19,20 +19,20 @@
import java.net.URL;
/**
- * Interface used by <code>URLStreamHandlerService</code> objects to call the
- * <code>setURL</code> method on the proxy <code>URLStreamHandler</code>
+ * Interface used by {@code URLStreamHandlerService} objects to call the
+ * {@code setURL} method on the proxy {@code URLStreamHandler}
* object.
*
* <p>
* Objects of this type are passed to the
* {@link URLStreamHandlerService#parseURL} method. Invoking the
- * <code>setURL</code> method on the <code>URLStreamHandlerSetter</code>
- * object will invoke the <code>setURL</code> method on the proxy
- * <code>URLStreamHandler</code> object that is actually registered with
- * <code>java.net.URL</code> for the protocol.
+ * {@code setURL} method on the {@code URLStreamHandlerSetter}
+ * object will invoke the {@code setURL} method on the proxy
+ * {@code URLStreamHandler} object that is actually registered with
+ * {@code java.net.URL} for the protocol.
*
* @ThreadSafe
- * @version $Revision: 5673 $
+ * @version $Id: f55d4c29678503c244f56dcb2b5621b3be11cc8d $
*/
public interface URLStreamHandlerSetter {
/**
diff --git a/framework/src/main/java/org/osgi/util/tracker/AbstractTracked.java b/framework/src/main/java/org/osgi/util/tracker/AbstractTracked.java
index 681148f..64a271a 100644
--- a/framework/src/main/java/org/osgi/util/tracker/AbstractTracked.java
+++ b/framework/src/main/java/org/osgi/util/tracker/AbstractTracked.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2007, 2008). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2007, 2010). 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,11 +30,14 @@
* tracked items. This is not a public class. It is only for use by the
* implementation of the Tracker class.
*
+ * @param <S> The tracked item. It is the key.
+ * @param <T> The value mapped to the tracked item.
+ * @param <R> The reason the tracked item is being tracked or untracked.
* @ThreadSafe
- * @version $Revision: 5871 $
+ * @version $Id: 79452e6c28683021f2bcf11d3689ec75c6b5642f $
* @since 1.4
*/
-abstract class AbstractTracked {
+abstract class AbstractTracked<S, T, R> {
/* set this to true to compile in debug messages */
static final boolean DEBUG = false;
@@ -43,7 +46,7 @@
*
* @GuardedBy this
*/
- private final Map tracked;
+ private final Map<S, T> tracked;
/**
* Modification count. This field is initialized to zero and incremented by
@@ -67,7 +70,7 @@
*
* @GuardedBy this
*/
- private final List adding;
+ private final List<S> adding;
/**
* true if the tracked object is closed.
@@ -94,16 +97,16 @@
*
* @GuardedBy this
*/
- private final LinkedList initial;
+ private final LinkedList<S> initial;
/**
* AbstractTracked constructor.
*/
AbstractTracked() {
- tracked = new HashMap();
+ tracked = new HashMap<S, T>();
trackingCount = 0;
- adding = new ArrayList(6);
- initial = new LinkedList();
+ adding = new ArrayList<S>(6);
+ initial = new LinkedList<S>();
closed = false;
}
@@ -114,17 +117,15 @@
* 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>
+ * @param list The initial list of items to be tracked. {@code null}
* entries in the list are ignored.
* @GuardedBy this
*/
- void setInitial(Object[] list) {
+ void setInitial(S[] list) {
if (list == null) {
return;
}
- int size = list.length;
- for (int i = 0; i < size; i++) {
- Object item = list[i];
+ for (S item : list) {
if (item == null) {
continue;
}
@@ -145,7 +146,7 @@
*/
void trackInitial() {
while (true) {
- Object item;
+ S item;
synchronized (this) {
if (closed || (initial.size() == 0)) {
/*
@@ -202,8 +203,8 @@
* @param item Item to be tracked.
* @param related Action related object.
*/
- void track(final Object item, final Object related) {
- final Object object;
+ void track(final S item, final R related) {
+ final T object;
synchronized (this) {
if (closed) {
return;
@@ -250,11 +251,11 @@
* @param item Item to be tracked.
* @param related Action related object.
*/
- private void trackAdding(final Object item, final Object related) {
+ private void trackAdding(final S item, final R related) {
if (DEBUG) {
System.out.println("AbstractTracked.trackAdding: " + item); //$NON-NLS-1$
}
- Object object = null;
+ T object = null;
boolean becameUntracked = false;
/* Call customizer outside of synchronized region */
try {
@@ -305,8 +306,8 @@
* @param item Item to be untracked.
* @param related Action related object.
*/
- void untrack(final Object item, final Object related) {
- final Object object;
+ void untrack(final S item, final R related) {
+ final T object;
synchronized (this) {
if (initial.remove(item)) { /*
* if this item is already in the list
@@ -367,6 +368,18 @@
}
/**
+ * Returns if the tracker is empty.
+ *
+ * @return Whether the tracker is empty.
+ *
+ * @GuardedBy this
+ * @since 1.5
+ */
+ boolean isEmpty() {
+ return tracked.isEmpty();
+ }
+
+ /**
* Return the customized object for the specified item
*
* @param item The item to lookup in the map
@@ -374,19 +387,19 @@
*
* @GuardedBy this
*/
- Object getCustomizedObject(final Object item) {
+ T getCustomizedObject(final S item) {
return tracked.get(item);
}
/**
- * Return the list of tracked items.
+ * Copy the tracked items into an array.
*
* @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) {
+ S[] copyKeys(final S[] list) {
return tracked.keySet().toArray(list);
}
@@ -401,7 +414,7 @@
}
/**
- * Returns the tracking count for this <code>ServiceTracker</code> object.
+ * Returns the tracking count for this {@code ServiceTracker} 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
@@ -415,15 +428,32 @@
}
/**
+ * Copy the tracked items and associated values into the specified map.
+ *
+ * @param <M> Type of {@code Map} to hold the tracked items and
+ * associated values.
+ * @param map The map into which to copy the tracked items and associated
+ * values. This map must not be a user provided map so that user code
+ * is not executed while synchronized on this.
+ * @return The specified map.
+ * @GuardedBy this
+ * @since 1.5
+ */
+ <M extends Map< ? super S, ? super T>> M copyEntries(final M map) {
+ map.putAll(tracked);
+ return map;
+ }
+
+ /**
* 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
+ * @return Customized object for the tracked item or {@code null} if
* the item is not to be tracked.
*/
- abstract Object customizerAdding(final Object item, final Object related);
+ abstract T customizerAdding(final S item, final R related);
/**
* Call the specific customizer modified method. This method must not be
@@ -433,8 +463,8 @@
* @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);
+ abstract void customizerModified(final S item, final R related,
+ final T object);
/**
* Call the specific customizer removed method. This method must not be
@@ -444,6 +474,6 @@
* @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);
+ abstract void customizerRemoved(final S item, final R related,
+ final T object);
}
diff --git a/framework/src/main/java/org/osgi/util/tracker/BundleTracker.java b/framework/src/main/java/org/osgi/util/tracker/BundleTracker.java
index 8791d98..4973503 100644
--- a/framework/src/main/java/org/osgi/util/tracker/BundleTracker.java
+++ b/framework/src/main/java/org/osgi/util/tracker/BundleTracker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2007, 2008). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2007, 2010). 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.
@@ -16,55 +16,59 @@
package org.osgi.util.tracker;
+import java.util.HashMap;
+import java.util.Map;
+
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.
+ * The {@code BundleTracker} class simplifies tracking bundles much like
+ * the {@code ServiceTracker} 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
+ * A {@code BundleTracker} is constructed with state criteria and a
+ * {@code BundleTrackerCustomizer} object. A {@code BundleTracker} can
+ * use the {@code BundleTrackerCustomizer} 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
+ * {@code BundleTracker} 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
+ * The {@code getBundles} method can be called to get the
+ * {@code Bundle} objects of the bundles being tracked. The
+ * {@code getObject} 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
+ * The {@code BundleTracker} class is thread-safe. It does not call a
+ * {@code BundleTrackerCustomizer} while holding any locks.
+ * {@code BundleTrackerCustomizer} implementations must also be
* thread-safe.
*
+ * @param <T> The type of the tracked object.
* @ThreadSafe
- * @version $Revision: 5894 $
+ * @version $Id: ebfd73a4e19f025d6ad9029d99c17944ee8c420a $
* @since 1.4
*/
-public class BundleTracker implements BundleTrackerCustomizer {
+public class BundleTracker<T> implements BundleTrackerCustomizer<T> {
/* set this to true to compile in debug messages */
- static final boolean DEBUG = false;
+ static final boolean DEBUG = false;
/**
- * The Bundle Context used by this <code>BundleTracker</code>.
+ * The Bundle Context used by this {@code BundleTracker}.
*/
- protected final BundleContext context;
+ protected final BundleContext context;
/**
- * The <code>BundleTrackerCustomizer</code> object for this tracker.
+ * The {@code BundleTrackerCustomizer} object for this tracker.
*/
- final BundleTrackerCustomizer customizer;
+ final BundleTrackerCustomizer<T> customizer;
/**
- * Tracked bundles: <code>Bundle</code> object -> customized Object and
- * <code>BundleListener</code> object
+ * Tracked bundles: {@code Bundle} object -> customized Object and
+ * {@code BundleListener} object
*/
- private volatile Tracked tracked;
+ private volatile Tracked tracked;
/**
* Accessor method for the current Tracked object. This method is only
@@ -81,50 +85,50 @@
* State mask for bundles being tracked. This field contains the ORed values
* of the bundle states being tracked.
*/
- final int mask;
+ final int mask;
/**
- * Create a <code>BundleTracker</code> for bundles whose state is present in
+ * Create a {@code BundleTracker} 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>.
+ * tracked by this {@code BundleTracker}.
*
- * @param context The <code>BundleContext</code> against which the tracking
+ * @param context The {@code BundleContext} against which the tracking
* is done.
- * @param stateMask The bit mask of the <code>OR</code>ing of the bundle
+ * @param stateMask The bit mask of the {@code OR}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.
+ * modified, or removed in this {@code BundleTracker}. If
+ * customizer is {@code null}, then this
+ * {@code BundleTracker} will be used as the
+ * {@code BundleTrackerCustomizer} and this
+ * {@code BundleTracker} will call the
+ * {@code BundleTrackerCustomizer} methods on itself.
* @see Bundle#getState()
*/
public BundleTracker(BundleContext context, int stateMask,
- BundleTrackerCustomizer customizer) {
+ BundleTrackerCustomizer<T> customizer) {
this.context = context;
this.mask = stateMask;
this.customizer = (customizer == null) ? this : customizer;
}
/**
- * Open this <code>BundleTracker</code> and begin tracking bundles.
+ * Open this {@code BundleTracker} 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>.
+ * {@code BundleTracker} was created are now tracked by this
+ * {@code BundleTracker}.
*
- * @throws java.lang.IllegalStateException If the <code>BundleContext</code>
- * with which this <code>BundleTracker</code> was created is no
+ * @throws java.lang.IllegalStateException If the {@code BundleContext}
+ * with which this {@code BundleTracker} 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
+ * {@code AdminPermission[context bundle,LISTENER]}, and the
* Java Runtime Environment supports permissions.
*/
public void open() {
@@ -150,7 +154,7 @@
}
}
/* set tracked with the initial bundles */
- t.setInitial(bundles);
+ t.setInitial(bundles);
}
}
tracked = t;
@@ -160,10 +164,10 @@
}
/**
- * Close this <code>BundleTracker</code>.
+ * Close this {@code BundleTracker}.
*
* <p>
- * This method should be called when this <code>BundleTracker</code> should
+ * This method should be called when this {@code BundleTracker} should
* end the tracking of bundles.
*
* <p>
@@ -200,80 +204,81 @@
/**
* Default implementation of the
- * <code>BundleTrackerCustomizer.addingBundle</code> method.
+ * {@code BundleTrackerCustomizer.addingBundle} method.
*
* <p>
- * This method is only called when this <code>BundleTracker</code> has been
- * constructed with a <code>null BundleTrackerCustomizer</code> argument.
+ * This method is only called when this {@code BundleTracker} has been
+ * constructed with a {@code null BundleTrackerCustomizer} argument.
*
* <p>
- * This implementation simply returns the specified <code>Bundle</code>.
+ * This implementation simply returns the specified {@code Bundle}.
*
* <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 bundle The {@code Bundle} being added to this
+ * {@code BundleTracker} 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
+ * called or {@code null} 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;
+ public T addingBundle(Bundle bundle, BundleEvent event) {
+ T result = (T) bundle;
+ return result;
}
/**
* Default implementation of the
- * <code>BundleTrackerCustomizer.modifiedBundle</code> method.
+ * {@code BundleTrackerCustomizer.modifiedBundle} method.
*
* <p>
- * This method is only called when this <code>BundleTracker</code> has been
- * constructed with a <code>null BundleTrackerCustomizer</code> argument.
+ * This method is only called when this {@code BundleTracker} has been
+ * constructed with a {@code null BundleTrackerCustomizer} argument.
*
* <p>
* This implementation does nothing.
*
- * @param bundle The <code>Bundle</code> whose state has been modified.
+ * @param bundle The {@code Bundle} 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
+ * called or {@code null} 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) {
+ public void modifiedBundle(Bundle bundle, BundleEvent event, T object) {
/* do nothing */
}
/**
* Default implementation of the
- * <code>BundleTrackerCustomizer.removedBundle</code> method.
+ * {@code BundleTrackerCustomizer.removedBundle} method.
*
* <p>
- * This method is only called when this <code>BundleTracker</code> has been
- * constructed with a <code>null BundleTrackerCustomizer</code> argument.
+ * This method is only called when this {@code BundleTracker} has been
+ * constructed with a {@code null BundleTrackerCustomizer} argument.
*
* <p>
* This implementation does nothing.
*
- * @param bundle The <code>Bundle</code> being removed.
+ * @param bundle The {@code Bundle} 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
+ * called or {@code null} 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) {
+ public void removedBundle(Bundle bundle, BundleEvent event, T 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}s for all bundles being tracked by
+ * this {@code BundleTracker}.
*
- * @return An array of <code>Bundle</code>s or <code>null</code> if no
+ * @return An array of {@code Bundle}s or {@code null} if no
* bundles are being tracked.
*/
public Bundle[] getBundles() {
@@ -286,20 +291,20 @@
if (length == 0) {
return null;
}
- return (Bundle[]) t.getTracked(new Bundle[length]);
+ return t.copyKeys(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>.
+ * Returns the customized object for the specified {@code Bundle} if
+ * the specified bundle is being tracked by this {@code BundleTracker}.
*
- * @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
+ * @param bundle The {@code Bundle} being tracked.
+ * @return The customized object for the specified {@code Bundle} or
+ * {@code null} if the specified {@code Bundle} is not
* being tracked.
*/
- public Object getObject(Bundle bundle) {
+ public T getObject(Bundle bundle) {
final Tracked t = tracked();
if (t == null) { /* if BundleTracker is not open */
return null;
@@ -310,14 +315,14 @@
}
/**
- * Remove a bundle from this <code>BundleTracker</code>.
+ * Remove a bundle from this {@code BundleTracker}.
*
- * The specified bundle will be removed from this <code>BundleTracker</code>
+ * The specified bundle will be removed from this {@code BundleTracker}
* . If the specified bundle was being tracked then the
- * <code>BundleTrackerCustomizer.removedBundle</code> method will be called
+ * {@code BundleTrackerCustomizer.removedBundle} method will be called
* for that bundle.
*
- * @param bundle The <code>Bundle</code> to be removed.
+ * @param bundle The {@code Bundle} to be removed.
*/
public void remove(Bundle bundle) {
final Tracked t = tracked();
@@ -329,7 +334,7 @@
/**
* Return the number of bundles being tracked by this
- * <code>BundleTracker</code>.
+ * {@code BundleTracker}.
*
* @return The number of bundles being tracked.
*/
@@ -344,23 +349,22 @@
}
/**
- * Returns the tracking count for this <code>BundleTracker</code>.
+ * Returns the tracking count for this {@code BundleTracker}.
*
- * 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.
+ * The tracking count is initialized to 0 when this {@code BundleTracker} is
+ * opened. Every time a bundle is added, modified or removed from this
+ * {@code BundleTracker} 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.
+ * The tracking count can be used to determine if this {@code BundleTracker}
+ * 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} 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.
+ * @return The tracking count for this {@code BundleTracker} or -1 if this
+ * {@code BundleTracker} is not open.
*/
public int getTrackingCount() {
final Tracked t = tracked();
@@ -373,13 +377,53 @@
}
/**
+ * Return a {@code Map} with the {@code Bundle}s and customized
+ * objects for all bundles being tracked by this {@code BundleTracker}.
+ *
+ * @return A {@code Map} with the {@code Bundle}s and customized
+ * objects for all services being tracked by this
+ * {@code BundleTracker}. If no bundles are being tracked, then
+ * the returned map is empty.
+ * @since 1.5
+ */
+ public Map<Bundle, T> getTracked() {
+ Map<Bundle, T> map = new HashMap<Bundle, T>();
+ final Tracked t = tracked();
+ if (t == null) { /* if BundleTracker is not open */
+ return map;
+ }
+ synchronized (t) {
+ return t.copyEntries(map);
+ }
+ }
+
+ /**
+ * Return if this {@code BundleTracker} is empty.
+ *
+ * @return {@code true} if this {@code BundleTracker} is not tracking any
+ * bundles.
+ * @since 1.5
+ */
+ public boolean isEmpty() {
+ final Tracked t = tracked();
+ if (t == null) { /* if BundleTracker is not open */
+ return true;
+ }
+ synchronized (t) {
+ return t.isEmpty();
+ }
+ }
+
+ /**
* Inner class which subclasses AbstractTracked. This class is the
- * <code>SynchronousBundleListener</code> object for the tracker.
+ * {@code SynchronousBundleListener} object for the tracker.
*
* @ThreadSafe
* @since 1.4
*/
- class Tracked extends AbstractTracked implements SynchronousBundleListener {
+ private final class Tracked extends AbstractTracked<Bundle, T, BundleEvent>
+ implements
+ SynchronousBundleListener {
/**
* Tracked constructor.
*/
@@ -388,11 +432,11 @@
}
/**
- * <code>BundleListener</code> method for the <code>BundleTracker</code>
+ * {@code BundleListener} method for the {@code BundleTracker}
* class. This method must NOT be synchronized to avoid deadlock
* potential.
*
- * @param event <code>BundleEvent</code> object from the framework.
+ * @param event {@code BundleEvent} object from the framework.
*/
public void bundleChanged(final BundleEvent event) {
/*
@@ -431,13 +475,11 @@
*
* @param item Item to be tracked.
* @param related Action related object.
- * @return Customized object for the tracked item or <code>null</code>
+ * @return Customized object for the tracked item or {@code null}
* if the item is not to be tracked.
*/
- Object customizerAdding(final Object item,
- final Object related) {
- return customizer
- .addingBundle((Bundle) item, (BundleEvent) related);
+ T customizerAdding(final Bundle item, final BundleEvent related) {
+ return customizer.addingBundle(item, related);
}
/**
@@ -448,10 +490,9 @@
* @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);
+ void customizerModified(final Bundle item, final BundleEvent related,
+ final T object) {
+ customizer.modifiedBundle(item, related, object);
}
/**
@@ -462,10 +503,9 @@
* @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);
+ void customizerRemoved(final Bundle item, final BundleEvent related,
+ final T object) {
+ customizer.removedBundle(item, related, object);
}
}
}
diff --git a/framework/src/main/java/org/osgi/util/tracker/BundleTrackerCustomizer.java b/framework/src/main/java/org/osgi/util/tracker/BundleTrackerCustomizer.java
index 100c6b4..a7c9a23 100644
--- a/framework/src/main/java/org/osgi/util/tracker/BundleTrackerCustomizer.java
+++ b/framework/src/main/java/org/osgi/util/tracker/BundleTrackerCustomizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2007, 2008). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2007, 2010). 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.
@@ -20,85 +20,86 @@
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
+ * The {@code BundleTrackerCustomizer} interface allows a
+ * {@code BundleTracker} to customize the {@code Bundle}s that are
+ * tracked. A {@code BundleTrackerCustomizer} is called when a bundle is
+ * being added to a {@code BundleTracker}. The
+ * {@code BundleTrackerCustomizer} can then return an object for the
+ * tracked bundle. A {@code BundleTrackerCustomizer} is also called when a
* tracked bundle is modified or has been removed from a
- * <code>BundleTracker</code>.
+ * {@code BundleTracker}.
*
* <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
+ * {@code BundleEvent} being received by a {@code BundleTracker}.
+ * Since {@code BundleEvent}s are received synchronously by the
+ * {@code BundleTracker}, 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
+ * The {@code BundleTracker} class is thread-safe. It does not call a
+ * {@code BundleTrackerCustomizer} while holding any locks.
+ * {@code BundleTrackerCustomizer} implementations must also be
* thread-safe.
*
+ * @param <T> The type of the tracked object.
* @ThreadSafe
- * @version $Revision: 5874 $
+ * @version $Id: 0e80f2555530b217faef57726a5938f0087a45c5 $
* @since 1.4
*/
-public interface BundleTrackerCustomizer {
+public interface BundleTrackerCustomizer<T> {
/**
- * A bundle is being added to the <code>BundleTracker</code>.
+ * A bundle is being added to the {@code BundleTracker}.
*
* <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
+ * of the {@code BundleTracker} is added to the
+ * {@code BundleTracker}. This method should return the object to be
+ * tracked for the specified {@code Bundle}. The returned object is
+ * stored in the {@code BundleTracker} 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 bundle The {@code Bundle} being added to the
+ * {@code BundleTracker}.
* @param event The bundle event which caused this customizer method to be
- * called or <code>null</code> if there is no bundle event associated
+ * called or {@code null} 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>
+ * @return The object to be tracked for the specified {@code Bundle}
+ * object or {@code null} if the specified {@code Bundle}
* object should not be tracked.
*/
- public Object addingBundle(Bundle bundle, BundleEvent event);
+ public T addingBundle(Bundle bundle, BundleEvent event);
/**
- * A bundle tracked by the <code>BundleTracker</code> has been modified.
+ * A bundle tracked by the {@code BundleTracker} has been modified.
*
* <p>
* This method is called when a bundle being tracked by the
- * <code>BundleTracker</code> has had its state modified.
+ * {@code BundleTracker} has had its state modified.
*
- * @param bundle The <code>Bundle</code> whose state has been modified.
+ * @param bundle The {@code Bundle} 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
+ * called or {@code null} 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);
+ T object);
/**
- * A bundle tracked by the <code>BundleTracker</code> has been removed.
+ * A bundle tracked by the {@code BundleTracker} has been removed.
*
* <p>
* This method is called after a bundle is no longer being tracked by the
- * <code>BundleTracker</code>.
+ * {@code BundleTracker}.
*
- * @param bundle The <code>Bundle</code> that has been removed.
+ * @param bundle The {@code Bundle} 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
+ * called or {@code null} 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);
+ T object);
}
diff --git a/framework/src/main/java/org/osgi/util/tracker/ServiceTracker.java b/framework/src/main/java/org/osgi/util/tracker/ServiceTracker.java
index b4e373b..f5cd086 100644
--- a/framework/src/main/java/org/osgi/util/tracker/ServiceTracker.java
+++ b/framework/src/main/java/org/osgi/util/tracker/ServiceTracker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2000, 2009). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2010). 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.
@@ -16,8 +16,10 @@
package org.osgi.util.tracker;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+import java.lang.reflect.Array;
+import java.util.Collections;
+import java.util.SortedMap;
+import java.util.TreeMap;
import org.osgi.framework.AllServiceListener;
import org.osgi.framework.BundleContext;
@@ -27,73 +29,74 @@
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
-import org.osgi.framework.Version;
/**
- * The <code>ServiceTracker</code> class simplifies using services from the
+ * The {@code ServiceTracker} class simplifies using services from the
* Framework's service registry.
* <p>
- * A <code>ServiceTracker</code> object is constructed with search criteria and
- * a <code>ServiceTrackerCustomizer</code> object. A <code>ServiceTracker</code>
- * can use a <code>ServiceTrackerCustomizer</code> to customize the service
- * objects to be tracked. The <code>ServiceTracker</code> can then be opened to
+ * A {@code ServiceTracker} object is constructed with search criteria and
+ * a {@code ServiceTrackerCustomizer} object. A {@code ServiceTracker}
+ * can use a {@code ServiceTrackerCustomizer} to customize the service
+ * objects to be tracked. The {@code ServiceTracker} can then be opened to
* begin tracking all services in the Framework's service registry that match
- * the specified search criteria. The <code>ServiceTracker</code> correctly
- * handles all of the details of listening to <code>ServiceEvent</code>s and
+ * the specified search criteria. The {@code ServiceTracker} correctly
+ * handles all of the details of listening to {@code ServiceEvent}s and
* getting and ungetting services.
* <p>
- * The <code>getServiceReferences</code> method can be called to get references
- * to the services being tracked. The <code>getService</code> and
- * <code>getServices</code> methods can be called to get the service objects for
+ * The {@code getServiceReferences} method can be called to get references
+ * to the services being tracked. The {@code getService} and
+ * {@code getServices} methods can be called to get the service objects for
* the tracked service.
* <p>
- * The <code>ServiceTracker</code> class is thread-safe. It does not call a
- * <code>ServiceTrackerCustomizer</code> while holding any locks.
- * <code>ServiceTrackerCustomizer</code> implementations must also be
+ * The {@code ServiceTracker} class is thread-safe. It does not call a
+ * {@code ServiceTrackerCustomizer} while holding any locks.
+ * {@code ServiceTrackerCustomizer} implementations must also be
* thread-safe.
*
+ * @param <S> The type of the service being tracked.
+ * @param <T> The type of the tracked object.
* @ThreadSafe
- * @version $Revision: 6386 $
+ * @version $Id: df62459c90f49d06e89ff8f20915a9eec401217e $
*/
-public class ServiceTracker implements ServiceTrackerCustomizer {
+public class ServiceTracker<S, T> implements ServiceTrackerCustomizer<S, T> {
/* set this to true to compile in debug messages */
- static final boolean DEBUG = false;
+ static final boolean DEBUG = false;
/**
- * The Bundle Context used by this <code>ServiceTracker</code>.
+ * The Bundle Context used by this {@code ServiceTracker}.
*/
- protected final BundleContext context;
+ protected final BundleContext context;
/**
- * The Filter used by this <code>ServiceTracker</code> which specifies the
+ * The Filter used by this {@code ServiceTracker} which specifies the
* search criteria for the services to track.
*
* @since 1.1
*/
- protected final Filter filter;
+ protected final Filter filter;
/**
- * The <code>ServiceTrackerCustomizer</code> for this tracker.
+ * The {@code ServiceTrackerCustomizer} for this tracker.
*/
- final ServiceTrackerCustomizer customizer;
+ final ServiceTrackerCustomizer<S, T> customizer;
/**
* Filter string for use when adding the ServiceListener. If this field is
* set, then certain optimizations can be taken since we don't have a user
* supplied filter.
*/
- final String listenerFilter;
+ final String listenerFilter;
/**
* Class name to be tracked. If this field is set, then we are tracking by
* class name.
*/
- private final String trackClass;
+ private final String trackClass;
/**
* Reference to be tracked. If this field is set, then we are tracking a
* single ServiceReference.
*/
- private final ServiceReference trackReference;
+ private final ServiceReference<S> trackReference;
/**
- * Tracked services: <code>ServiceReference</code> -> customized Object and
- * <code>ServiceListener</code> object
+ * Tracked services: {@code ServiceReference} -> customized Object and
+ * {@code ServiceListener} object
*/
- private volatile Tracked tracked;
+ private volatile Tracked tracked;
/**
* Accessor method for the current Tracked object. This method is only
@@ -111,49 +114,43 @@
*
* This field is volatile since it is accessed by multiple threads.
*/
- private volatile ServiceReference cachedReference;
+ private volatile ServiceReference<S> cachedReference;
/**
* Cached service object for getService.
*
* This field is volatile since it is accessed by multiple threads.
*/
- private volatile Object cachedService;
+ private volatile T cachedService;
/**
- * org.osgi.framework package version which introduced
- * {@link ServiceEvent#MODIFIED_ENDMATCH}
- */
- private static final Version endMatchVersion = new Version(1, 5, 0);
-
- /**
- * Create a <code>ServiceTracker</code> on the specified
- * <code>ServiceReference</code>.
+ * Create a {@code ServiceTracker} on the specified
+ * {@code ServiceReference}.
*
* <p>
- * The service referenced by the specified <code>ServiceReference</code>
- * will be tracked by this <code>ServiceTracker</code>.
+ * The service referenced by the specified {@code ServiceReference}
+ * will be tracked by this {@code ServiceTracker}.
*
- * @param context The <code>BundleContext</code> against which the tracking
+ * @param context The {@code BundleContext} against which the tracking
* is done.
- * @param reference The <code>ServiceReference</code> for the service to be
+ * @param reference The {@code ServiceReference} for the service to be
* tracked.
* @param customizer The customizer object to call when services are added,
- * modified, or removed in this <code>ServiceTracker</code>. If
- * customizer is <code>null</code>, then this
- * <code>ServiceTracker</code> will be used as the
- * <code>ServiceTrackerCustomizer</code> and this
- * <code>ServiceTracker</code> will call the
- * <code>ServiceTrackerCustomizer</code> methods on itself.
+ * modified, or removed in this {@code ServiceTracker}. If
+ * customizer is {@code null}, then this
+ * {@code ServiceTracker} will be used as the
+ * {@code ServiceTrackerCustomizer} and this
+ * {@code ServiceTracker} will call the
+ * {@code ServiceTrackerCustomizer} methods on itself.
*/
public ServiceTracker(final BundleContext context,
- final ServiceReference reference,
- final ServiceTrackerCustomizer customizer) {
+ final ServiceReference<S> reference,
+ final ServiceTrackerCustomizer<S, T> customizer) {
this.context = context;
this.trackReference = reference;
this.trackClass = null;
this.customizer = (customizer == null) ? this : customizer;
this.listenerFilter = "(" + Constants.SERVICE_ID + "="
- + reference.getProperty(Constants.SERVICE_ID).toString() + ")";
+ + reference.getProperty(Constants.SERVICE_ID).toString() + ")";
try {
this.filter = context.createFilter(listenerFilter);
}
@@ -170,32 +167,32 @@
}
/**
- * Create a <code>ServiceTracker</code> on the specified class name.
+ * Create a {@code ServiceTracker} on the specified class name.
*
* <p>
* Services registered under the specified class name will be tracked by
- * this <code>ServiceTracker</code>.
+ * this {@code ServiceTracker}.
*
- * @param context The <code>BundleContext</code> against which the tracking
+ * @param context The {@code BundleContext} against which the tracking
* is done.
* @param clazz The class name of the services to be tracked.
* @param customizer The customizer object to call when services are added,
- * modified, or removed in this <code>ServiceTracker</code>. If
- * customizer is <code>null</code>, then this
- * <code>ServiceTracker</code> will be used as the
- * <code>ServiceTrackerCustomizer</code> and this
- * <code>ServiceTracker</code> will call the
- * <code>ServiceTrackerCustomizer</code> methods on itself.
+ * modified, or removed in this {@code ServiceTracker}. If
+ * customizer is {@code null}, then this
+ * {@code ServiceTracker} will be used as the
+ * {@code ServiceTrackerCustomizer} and this
+ * {@code ServiceTracker} will call the
+ * {@code ServiceTrackerCustomizer} methods on itself.
*/
public ServiceTracker(final BundleContext context, final String clazz,
- final ServiceTrackerCustomizer customizer) {
+ final ServiceTrackerCustomizer<S, T> customizer) {
this.context = context;
this.trackReference = null;
this.trackClass = clazz;
this.customizer = (customizer == null) ? this : customizer;
// we call clazz.toString to verify clazz is non-null!
this.listenerFilter = "(" + Constants.OBJECTCLASS + "="
- + clazz.toString() + ")";
+ + clazz.toString() + ")";
try {
this.filter = context.createFilter(listenerFilter);
}
@@ -212,42 +209,31 @@
}
/**
- * Create a <code>ServiceTracker</code> on the specified <code>Filter</code>
+ * Create a {@code ServiceTracker} on the specified {@code Filter}
* object.
*
* <p>
- * Services which match the specified <code>Filter</code> object will be
- * tracked by this <code>ServiceTracker</code>.
+ * Services which match the specified {@code Filter} object will be
+ * tracked by this {@code ServiceTracker}.
*
- * @param context The <code>BundleContext</code> against which the tracking
+ * @param context The {@code BundleContext} against which the tracking
* is done.
- * @param filter The <code>Filter</code> to select the services to be
+ * @param filter The {@code Filter} to select the services to be
* tracked.
* @param customizer The customizer object to call when services are added,
- * modified, or removed in this <code>ServiceTracker</code>. If
- * customizer is null, then this <code>ServiceTracker</code> will be
- * used as the <code>ServiceTrackerCustomizer</code> and this
- * <code>ServiceTracker</code> will call the
- * <code>ServiceTrackerCustomizer</code> methods on itself.
+ * modified, or removed in this {@code ServiceTracker}. If
+ * customizer is null, then this {@code ServiceTracker} will be
+ * used as the {@code ServiceTrackerCustomizer} and this
+ * {@code ServiceTracker} will call the
+ * {@code ServiceTrackerCustomizer} methods on itself.
* @since 1.1
*/
public ServiceTracker(final BundleContext context, final Filter filter,
- final ServiceTrackerCustomizer customizer) {
+ final ServiceTrackerCustomizer<S, T> customizer) {
this.context = context;
this.trackReference = null;
this.trackClass = null;
- final Version frameworkVersion = (Version) AccessController
- .doPrivileged(new PrivilegedAction() {
- public Object run() {
- String version = context
- .getProperty(Constants.FRAMEWORK_VERSION);
- return (version == null) ? Version.emptyVersion
- : new Version(version);
- }
- });
- final boolean endMatchSupported = (frameworkVersion
- .compareTo(endMatchVersion) >= 0);
- this.listenerFilter = endMatchSupported ? filter.toString() : null;
+ this.listenerFilter = filter.toString();
this.filter = filter;
this.customizer = (customizer == null) ? this : customizer;
if ((context == null) || (filter == null)) {
@@ -259,13 +245,37 @@
}
/**
- * Open this <code>ServiceTracker</code> and begin tracking services.
+ * Create a {@code ServiceTracker} on the specified class.
*
* <p>
- * This implementation calls <code>open(false)</code>.
+ * Services registered under the name of the specified class will be tracked
+ * by this {@code ServiceTracker}.
*
- * @throws java.lang.IllegalStateException If the <code>BundleContext</code>
- * with which this <code>ServiceTracker</code> was created is no
+ * @param context The {@code BundleContext} against which the tracking
+ * is done.
+ * @param clazz The class of the services to be tracked.
+ * @param customizer The customizer object to call when services are added,
+ * modified, or removed in this {@code ServiceTracker}. If
+ * customizer is {@code null}, then this
+ * {@code ServiceTracker} will be used as the
+ * {@code ServiceTrackerCustomizer} and this
+ * {@code ServiceTracker} will call the
+ * {@code ServiceTrackerCustomizer} methods on itself.
+ * @since 1.5
+ */
+ public ServiceTracker(final BundleContext context, final Class<S> clazz,
+ final ServiceTrackerCustomizer<S, T> customizer) {
+ this(context, clazz.getName(), customizer);
+ }
+
+ /**
+ * Open this {@code ServiceTracker} and begin tracking services.
+ *
+ * <p>
+ * This implementation calls {@code open(false)}.
+ *
+ * @throws java.lang.IllegalStateException If the {@code BundleContext}
+ * with which this {@code ServiceTracker} was created is no
* longer valid.
* @see #open(boolean)
*/
@@ -274,22 +284,22 @@
}
/**
- * Open this <code>ServiceTracker</code> and begin tracking services.
+ * Open this {@code ServiceTracker} and begin tracking services.
*
* <p>
* Services which match the search criteria specified when this
- * <code>ServiceTracker</code> was created are now tracked by this
- * <code>ServiceTracker</code>.
+ * {@code ServiceTracker} was created are now tracked by this
+ * {@code ServiceTracker}.
*
- * @param trackAllServices If <code>true</code>, then this
- * <code>ServiceTracker</code> will track all matching services
- * regardless of class loader accessibility. If <code>false</code>,
- * then this <code>ServiceTracker</code> will only track matching
+ * @param trackAllServices If {@code true}, then this
+ * {@code ServiceTracker} will track all matching services
+ * regardless of class loader accessibility. If {@code false},
+ * then this {@code ServiceTracker} will only track matching
* services which are class loader accessible to the bundle whose
- * <code>BundleContext</code> is used by this
- * <code>ServiceTracker</code>.
- * @throws java.lang.IllegalStateException If the <code>BundleContext</code>
- * with which this <code>ServiceTracker</code> was created is no
+ * {@code BundleContext} is used by this
+ * {@code ServiceTracker}.
+ * @throws java.lang.IllegalStateException If the {@code BundleContext}
+ * with which this {@code ServiceTracker} was created is no
* longer valid.
* @since 1.3
*/
@@ -300,13 +310,13 @@
return;
}
if (DEBUG) {
- System.out.println("ServiceTracker.open: " + filter);
+ System.out.println("ServiceTracker.open: " + filter);
}
t = trackAllServices ? new AllTracked() : new Tracked();
synchronized (t) {
try {
context.addServiceListener(t, listenerFilter);
- ServiceReference[] references = null;
+ ServiceReference<S>[] references = null;
if (trackClass != null) {
references = getInitialReferences(trackAllServices,
trackClass, null);
@@ -314,23 +324,22 @@
else {
if (trackReference != null) {
if (trackReference.getBundle() != null) {
- references = new ServiceReference[] {trackReference};
+ ServiceReference<S>[] single = new ServiceReference[] {trackReference};
+ references = single;
}
}
else { /* user supplied filter */
references = getInitialReferences(trackAllServices,
- null,
- (listenerFilter != null) ? listenerFilter
- : filter.toString());
+ null, listenerFilter);
}
}
/* set tracked with the initial references */
- t.setInitial(references);
+ t.setInitial(references);
}
catch (InvalidSyntaxException e) {
throw new RuntimeException(
"unexpected InvalidSyntaxException: "
- + e.getMessage(), e);
+ + e.getMessage(), e);
}
}
tracked = t;
@@ -340,33 +349,33 @@
}
/**
- * Returns the list of initial <code>ServiceReference</code>s that will be
- * tracked by this <code>ServiceTracker</code>.
+ * Returns the list of initial {@code ServiceReference}s that will be
+ * tracked by this {@code ServiceTracker}.
*
- * @param trackAllServices If <code>true</code>, use
- * <code>getAllServiceReferences</code>.
+ * @param trackAllServices If {@code true}, use
+ * {@code getAllServiceReferences}.
* @param className The class name with which the service was registered, or
- * <code>null</code> for all services.
- * @param filterString The filter criteria or <code>null</code> for all
+ * {@code null} for all services.
+ * @param filterString The filter criteria or {@code null} for all
* services.
- * @return The list of initial <code>ServiceReference</code>s.
+ * @return The list of initial {@code ServiceReference}s.
* @throws InvalidSyntaxException If the specified filterString has an
* invalid syntax.
*/
- private ServiceReference[] getInitialReferences(boolean trackAllServices,
- String className, String filterString)
+ private ServiceReference<S>[] getInitialReferences(
+ boolean trackAllServices, String className, String filterString)
throws InvalidSyntaxException {
- if (trackAllServices) {
- return context.getAllServiceReferences(className, filterString);
- }
- return context.getServiceReferences(className, filterString);
+ ServiceReference<S>[] result = (ServiceReference<S>[]) ((trackAllServices) ? context
+ .getAllServiceReferences(className, filterString)
+ : context.getServiceReferences(className, filterString));
+ return result;
}
/**
- * Close this <code>ServiceTracker</code>.
+ * Close this {@code ServiceTracker}.
*
* <p>
- * This method should be called when this <code>ServiceTracker</code> should
+ * This method should be called when this {@code ServiceTracker} should
* end the tracking of services.
*
* <p>
@@ -375,14 +384,14 @@
*/
public void close() {
final Tracked outgoing;
- final ServiceReference[] references;
+ final ServiceReference<S>[] references;
synchronized (this) {
outgoing = tracked;
if (outgoing == null) {
return;
}
if (DEBUG) {
- System.out.println("ServiceTracker.close: " + filter);
+ System.out.println("ServiceTracker.close: " + filter);
}
outgoing.close();
references = getServiceReferences();
@@ -405,26 +414,25 @@
}
if (DEBUG) {
if ((cachedReference == null) && (cachedService == null)) {
- System.out
- .println("ServiceTracker.close[cached cleared]: "
- + filter);
+ System.out.println("ServiceTracker.close[cached cleared]: "
+ + filter);
}
}
}
/**
* Default implementation of the
- * <code>ServiceTrackerCustomizer.addingService</code> method.
+ * {@code ServiceTrackerCustomizer.addingService} method.
*
* <p>
- * This method is only called when this <code>ServiceTracker</code> has been
- * constructed with a <code>null ServiceTrackerCustomizer</code> argument.
+ * This method is only called when this {@code ServiceTracker} has been
+ * constructed with a {@code null ServiceTrackerCustomizer} argument.
*
* <p>
- * This implementation returns the result of calling <code>getService</code>
- * on the <code>BundleContext</code> with which this
- * <code>ServiceTracker</code> was created passing the specified
- * <code>ServiceReference</code>.
+ * This implementation returns the result of calling {@code getService}
+ * on the {@code BundleContext} with which this
+ * {@code ServiceTracker} was created passing the specified
+ * {@code ServiceReference}.
* <p>
* This method can be overridden in a subclass to customize the service
* object to be tracked for the service being added. In that case, take care
@@ -433,22 +441,23 @@
* the service.
*
* @param reference The reference to the service being added to this
- * <code>ServiceTracker</code>.
+ * {@code ServiceTracker}.
* @return The service object to be tracked for the service added to this
- * <code>ServiceTracker</code>.
+ * {@code ServiceTracker}.
* @see ServiceTrackerCustomizer#addingService(ServiceReference)
*/
- public Object addingService(ServiceReference reference) {
- return context.getService(reference);
+ public T addingService(ServiceReference<S> reference) {
+ T result = (T) context.getService(reference);
+ return result;
}
/**
* Default implementation of the
- * <code>ServiceTrackerCustomizer.modifiedService</code> method.
+ * {@code ServiceTrackerCustomizer.modifiedService} method.
*
* <p>
- * This method is only called when this <code>ServiceTracker</code> has been
- * constructed with a <code>null ServiceTrackerCustomizer</code> argument.
+ * This method is only called when this {@code ServiceTracker} has been
+ * constructed with a {@code null ServiceTrackerCustomizer} argument.
*
* <p>
* This implementation does nothing.
@@ -457,22 +466,22 @@
* @param service The service object for the modified service.
* @see ServiceTrackerCustomizer#modifiedService(ServiceReference, Object)
*/
- public void modifiedService(ServiceReference reference, Object service) {
+ public void modifiedService(ServiceReference<S> reference, T service) {
/* do nothing */
}
/**
* Default implementation of the
- * <code>ServiceTrackerCustomizer.removedService</code> method.
+ * {@code ServiceTrackerCustomizer.removedService} method.
*
* <p>
- * This method is only called when this <code>ServiceTracker</code> has been
- * constructed with a <code>null ServiceTrackerCustomizer</code> argument.
+ * This method is only called when this {@code ServiceTracker} has been
+ * constructed with a {@code null ServiceTrackerCustomizer} argument.
*
* <p>
- * This implementation calls <code>ungetService</code>, on the
- * <code>BundleContext</code> with which this <code>ServiceTracker</code>
- * was created, passing the specified <code>ServiceReference</code>.
+ * This implementation calls {@code ungetService}, on the
+ * {@code BundleContext} with which this {@code ServiceTracker}
+ * was created, passing the specified {@code ServiceReference}.
* <p>
* This method can be overridden in a subclass. If the default
* implementation of {@link #addingService(ServiceReference) addingService}
@@ -482,19 +491,19 @@
* @param service The service object for the removed service.
* @see ServiceTrackerCustomizer#removedService(ServiceReference, Object)
*/
- public void removedService(ServiceReference reference, Object service) {
+ public void removedService(ServiceReference<S> reference, T service) {
context.ungetService(reference);
}
/**
* Wait for at least one service to be tracked by this
- * <code>ServiceTracker</code>. This method will also return when this
- * <code>ServiceTracker</code> is closed.
+ * {@code ServiceTracker}. This method will also return when this
+ * {@code ServiceTracker} is closed.
*
* <p>
- * It is strongly recommended that <code>waitForService</code> is not used
- * during the calling of the <code>BundleActivator</code> methods.
- * <code>BundleActivator</code> methods are expected to complete in a short
+ * It is strongly recommended that {@code waitForService} is not used
+ * during the calling of the {@code BundleActivator} methods.
+ * {@code BundleActivator} methods are expected to complete in a short
* period of time.
*
* <p>
@@ -508,11 +517,11 @@
* current thread.
* @throws IllegalArgumentException If the value of timeout is negative.
*/
- public Object waitForService(long timeout) throws InterruptedException {
+ public T waitForService(long timeout) throws InterruptedException {
if (timeout < 0) {
- throw new IllegalArgumentException("timeout value is negative");
+ throw new IllegalArgumentException("timeout value is negative");
}
- Object object = getService();
+ T object = getService();
while (object == null) {
final Tracked t = tracked();
if (t == null) { /* if ServiceTracker is not open */
@@ -523,7 +532,7 @@
t.wait(timeout);
}
}
- object = getService();
+ object = getService();
if (timeout > 0) {
return object;
}
@@ -532,13 +541,13 @@
}
/**
- * Return an array of <code>ServiceReference</code>s for all services being
- * tracked by this <code>ServiceTracker</code>.
+ * Return an array of {@code ServiceReference}s for all services being
+ * tracked by this {@code ServiceTracker}.
*
- * @return Array of <code>ServiceReference</code>s or <code>null</code> if
+ * @return Array of {@code ServiceReference}s or {@code null} if
* no services are being tracked.
*/
- public ServiceReference[] getServiceReferences() {
+ public ServiceReference<S>[] getServiceReferences() {
final Tracked t = tracked();
if (t == null) { /* if ServiceTracker is not open */
return null;
@@ -548,45 +557,45 @@
if (length == 0) {
return null;
}
- return (ServiceReference[]) t
- .getTracked(new ServiceReference[length]);
+ ServiceReference<S>[] result = new ServiceReference[length];
+ return t.copyKeys(result);
}
}
/**
- * Returns a <code>ServiceReference</code> for one of the services being
- * tracked by this <code>ServiceTracker</code>.
+ * Returns a {@code ServiceReference} for one of the services being
+ * tracked by this {@code ServiceTracker}.
*
* <p>
* If multiple services are being tracked, the service with the highest
- * ranking (as specified in its <code>service.ranking</code> property) is
+ * ranking (as specified in its {@code service.ranking} property) is
* returned. If there is a tie in ranking, the service with the lowest
- * service ID (as specified in its <code>service.id</code> property); that
+ * service ID (as specified in its {@code service.id} property); that
* is, the service that was registered first is returned. This is the same
- * algorithm used by <code>BundleContext.getServiceReference</code>.
+ * algorithm used by {@code BundleContext.getServiceReference}.
*
* <p>
* This implementation calls {@link #getServiceReferences()} to get the list
* of references for the tracked services.
*
- * @return A <code>ServiceReference</code> or <code>null</code> if no
+ * @return A {@code ServiceReference} or {@code null} if no
* services are being tracked.
* @since 1.1
*/
- public ServiceReference getServiceReference() {
- ServiceReference reference = cachedReference;
+ public ServiceReference<S> getServiceReference() {
+ ServiceReference<S> reference = cachedReference;
if (reference != null) {
if (DEBUG) {
System.out
.println("ServiceTracker.getServiceReference[cached]: "
- + filter);
+ + filter);
}
return reference;
}
if (DEBUG) {
- System.out.println("ServiceTracker.getServiceReference: " + filter);
+ System.out.println("ServiceTracker.getServiceReference: " + filter);
}
- ServiceReference[] references = getServiceReferences();
+ ServiceReference<S>[] references = getServiceReferences();
int length = (references == null) ? 0 : references.length;
if (length == 0) { /* if no service is being tracked */
return null;
@@ -634,15 +643,15 @@
/**
* Returns the service object for the specified
- * <code>ServiceReference</code> if the specified referenced service is
- * being tracked by this <code>ServiceTracker</code>.
+ * {@code ServiceReference} if the specified referenced service is
+ * being tracked by this {@code ServiceTracker}.
*
* @param reference The reference to the desired service.
- * @return A service object or <code>null</code> if the service referenced
- * by the specified <code>ServiceReference</code> is not being
+ * @return A service object or {@code null} if the service referenced
+ * by the specified {@code ServiceReference} is not being
* tracked.
*/
- public Object getService(ServiceReference reference) {
+ public T getService(ServiceReference<S> reference) {
final Tracked t = tracked();
if (t == null) { /* if ServiceTracker is not open */
return null;
@@ -654,7 +663,7 @@
/**
* Return an array of service objects for all services being tracked by this
- * <code>ServiceTracker</code>.
+ * {@code ServiceTracker}.
*
* <p>
* This implementation calls {@link #getServiceReferences()} to get the list
@@ -662,7 +671,7 @@
* {@link #getService(ServiceReference)} for each reference to get the
* tracked service object.
*
- * @return An array of service objects or <code>null</code> if no services
+ * @return An array of service objects or {@code null} if no services
* are being tracked.
*/
public Object[] getServices() {
@@ -671,14 +680,14 @@
return null;
}
synchronized (t) {
- ServiceReference[] references = getServiceReferences();
+ ServiceReference<S>[] references = getServiceReferences();
int length = (references == null) ? 0 : references.length;
if (length == 0) {
return null;
}
Object[] objects = new Object[length];
for (int i = 0; i < length; i++) {
- objects[i] = getService(references[i]);
+ objects[i] = getService(references[i]);
}
return objects;
}
@@ -686,46 +695,45 @@
/**
* Returns a service object for one of the services being tracked by this
- * <code>ServiceTracker</code>.
+ * {@code ServiceTracker}.
*
* <p>
* If any services are being tracked, this implementation returns the result
- * of calling <code>getService(getServiceReference())</code>.
+ * of calling {@code getService(getServiceReference())}.
*
- * @return A service object or <code>null</code> if no services are being
+ * @return A service object or {@code null} if no services are being
* tracked.
*/
- public Object getService() {
- Object service = cachedService;
+ public T getService() {
+ T service = cachedService;
if (service != null) {
if (DEBUG) {
- System.out
- .println("ServiceTracker.getService[cached]: "
- + filter);
+ System.out.println("ServiceTracker.getService[cached]: "
+ + filter);
}
return service;
}
if (DEBUG) {
- System.out.println("ServiceTracker.getService: " + filter);
+ System.out.println("ServiceTracker.getService: " + filter);
}
- ServiceReference reference = getServiceReference();
+ ServiceReference<S> reference = getServiceReference();
if (reference == null) {
return null;
}
- return cachedService = getService(reference);
+ return cachedService = getService(reference);
}
/**
- * Remove a service from this <code>ServiceTracker</code>.
+ * Remove a service from this {@code ServiceTracker}.
*
* The specified service will be removed from this
- * <code>ServiceTracker</code>. If the specified service was being tracked
- * then the <code>ServiceTrackerCustomizer.removedService</code> method will
+ * {@code ServiceTracker}. If the specified service was being tracked
+ * then the {@code ServiceTrackerCustomizer.removedService} method will
* be called for that service.
*
* @param reference The reference to the service to be removed.
*/
- public void remove(ServiceReference reference) {
+ public void remove(ServiceReference<S> reference) {
final Tracked t = tracked();
if (t == null) { /* if ServiceTracker is not open */
return;
@@ -735,7 +743,7 @@
/**
* Return the number of services being tracked by this
- * <code>ServiceTracker</code>.
+ * {@code ServiceTracker}.
*
* @return The number of services being tracked.
*/
@@ -750,24 +758,23 @@
}
/**
- * Returns the tracking count for this <code>ServiceTracker</code>.
+ * Returns the tracking count for this {@code ServiceTracker}.
*
- * The tracking count is initialized to 0 when this
- * <code>ServiceTracker</code> is opened. Every time a service is added,
- * modified or removed from this <code>ServiceTracker</code>, the tracking
- * count is incremented.
+ * The tracking count is initialized to 0 when this {@code ServiceTracker}
+ * is opened. Every time a service is added, modified or removed from this
+ * {@code ServiceTracker}, the tracking count is incremented.
*
* <p>
* The tracking count can be used to determine if this
- * <code>ServiceTracker</code> has added, modified or removed a service by
+ * {@code ServiceTracker} has added, modified or removed a service by
* comparing a tracking count value previously collected with the current
* tracking count value. If the value has not changed, then no service has
- * been added, modified or removed from this <code>ServiceTracker</code>
- * since the previous tracking count was collected.
+ * been added, modified or removed from this {@code ServiceTracker} since
+ * the previous tracking count was collected.
*
* @since 1.2
- * @return The tracking count for this <code>ServiceTracker</code> or -1 if
- * this <code>ServiceTracker</code> is not open.
+ * @return The tracking count for this {@code ServiceTracker} or -1 if this
+ * {@code ServiceTracker} is not open.
*/
public int getTrackingCount() {
final Tracked t = tracked();
@@ -792,17 +799,113 @@
cachedReference = null; /* clear cached value */
cachedService = null; /* clear cached value */
if (DEBUG) {
- System.out.println("ServiceTracker.modified: " + filter);
+ System.out.println("ServiceTracker.modified: " + filter);
+ }
+ }
+
+ /**
+ * Return a {@code SortedMap} of the {@code ServiceReference}s and
+ * service objects for all services being tracked by this
+ * {@code ServiceTracker}. The map is sorted in reverse natural order
+ * of {@code ServiceReference}. That is, the first entry is the service
+ * with the highest ranking and the lowest service id.
+ *
+ * @return A {@code SortedMap} with the {@code ServiceReference}s
+ * and service objects for all services being tracked by this
+ * {@code ServiceTracker}. If no services are being tracked,
+ * then the returned map is empty.
+ * @since 1.5
+ */
+ public SortedMap<ServiceReference<S>, T> getTracked() {
+ SortedMap<ServiceReference<S>, T> map = new TreeMap<ServiceReference<S>, T>(
+ Collections.reverseOrder());
+ final Tracked t = tracked();
+ if (t == null) { /* if ServiceTracker is not open */
+ return map;
+ }
+ synchronized (t) {
+ return t.copyEntries(map);
+ }
+ }
+
+ /**
+ * Return if this {@code ServiceTracker} is empty.
+ *
+ * @return {@code true} if this {@code ServiceTracker} is not tracking any
+ * services.
+ * @since 1.5
+ */
+ public boolean isEmpty() {
+ final Tracked t = tracked();
+ if (t == null) { /* if ServiceTracker is not open */
+ return true;
+ }
+ synchronized (t) {
+ return t.isEmpty();
+ }
+ }
+
+ /**
+ * Return an array of service objects for all services being tracked by this
+ * {@code ServiceTracker}. The runtime type of the returned array is that of
+ * the specified array.
+ *
+ * <p>
+ * This implementation calls {@link #getServiceReferences()} to get the list
+ * of references for the tracked services and then calls
+ * {@link #getService(ServiceReference)} for each reference to get the
+ * tracked service object.
+ *
+ * @param array An array into which the tracked service objects will be
+ * stored, if the array is large enough.
+ * @return An array of service objects being tracked. If the specified array
+ * is large enough to hold the result, then the specified array is
+ * returned. If the specified array is longer then necessary to hold
+ * the result, the array element after the last service object is
+ * set to {@code null}. If the specified array is not large enough
+ * to hold the result, a new array is created and returned.
+ * @since 1.5
+ */
+ public T[] getServices(T[] array) {
+ final Tracked t = tracked();
+ if (t == null) { /* if ServiceTracker is not open */
+ if (array.length > 0) {
+ array[0] = null;
+ }
+ return array;
+ }
+ synchronized (t) {
+ ServiceReference<S>[] references = getServiceReferences();
+ int length = (references == null) ? 0 : references.length;
+ if (length == 0) {
+ if (array.length > 0) {
+ array[0] = null;
+ }
+ return array;
+ }
+ if (length > array.length) {
+ array = (T[]) Array.newInstance(array.getClass()
+ .getComponentType(), length);
+ }
+ for (int i = 0; i < length; i++) {
+ array[i] = getService(references[i]);
+ }
+ if (array.length > length) {
+ array[length] = null;
+ }
+ return array;
}
}
/**
* Inner class which subclasses AbstractTracked. This class is the
- * <code>ServiceListener</code> object for the tracker.
+ * {@code ServiceListener} object for the tracker.
*
* @ThreadSafe
*/
- class Tracked extends AbstractTracked implements ServiceListener {
+ private class Tracked extends
+ AbstractTracked<ServiceReference<S>, T, ServiceEvent>
+ implements ServiceListener {
/**
* Tracked constructor.
*/
@@ -811,13 +914,13 @@
}
/**
- * <code>ServiceListener</code> method for the
- * <code>ServiceTracker</code> class. This method must NOT be
+ * {@code ServiceListener} method for the
+ * {@code ServiceTracker} class. This method must NOT be
* synchronized to avoid deadlock potential.
*
- * @param event <code>ServiceEvent</code> object from the framework.
+ * @param event {@code ServiceEvent} object from the framework.
*/
- public void serviceChanged(final ServiceEvent event) {
+ final public void serviceChanged(final ServiceEvent event) {
/*
* Check if we had a delayed call (which could happen when we
* close).
@@ -825,40 +928,21 @@
if (closed) {
return;
}
- final ServiceReference reference = event.getServiceReference();
+ final ServiceReference<S> reference = (ServiceReference<S>) event
+ .getServiceReference();
if (DEBUG) {
- System.out
- .println("ServiceTracker.Tracked.serviceChanged["
- + event.getType() + "]: " + reference);
+ System.out.println("ServiceTracker.Tracked.serviceChanged["
+ + event.getType() + "]: " + reference);
}
switch (event.getType()) {
case ServiceEvent.REGISTERED :
case ServiceEvent.MODIFIED :
- if (listenerFilter != null) { // service listener added with
- // filter
- track(reference, event);
- /*
- * If the customizer throws an unchecked exception, it
- * is safe to let it propagate
- */
- }
- else { // service listener added without filter
- if (filter.match(reference)) {
- track(reference, event);
- /*
- * If the customizer throws an unchecked exception,
- * it is safe to let it propagate
- */
- }
- else {
- untrack(reference, event);
- /*
- * If the customizer throws an unchecked exception,
- * it is safe to let it propagate
- */
- }
- }
+ track(reference, event);
+ /*
+ * If the customizer throws an unchecked exception, it is
+ * safe to let it propagate
+ */
break;
case ServiceEvent.MODIFIED_ENDMATCH :
case ServiceEvent.UNREGISTERING :
@@ -877,7 +961,7 @@
*
* @GuardedBy this
*/
- void modified() {
+ final void modified() {
super.modified(); /* increment the modification count */
ServiceTracker.this.modified();
}
@@ -888,12 +972,12 @@
*
* @param item Item to be tracked.
* @param related Action related object.
- * @return Customized object for the tracked item or <code>null</code>
+ * @return Customized object for the tracked item or {@code null}
* if the item is not to be tracked.
*/
- Object customizerAdding(final Object item,
- final Object related) {
- return customizer.addingService((ServiceReference) item);
+ final T customizerAdding(final ServiceReference<S> item,
+ final ServiceEvent related) {
+ return customizer.addingService(item);
}
/**
@@ -904,9 +988,9 @@
* @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.modifiedService((ServiceReference) item, object);
+ final void customizerModified(final ServiceReference<S> item,
+ final ServiceEvent related, final T object) {
+ customizer.modifiedService(item, object);
}
/**
@@ -917,9 +1001,9 @@
* @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.removedService((ServiceReference) item, object);
+ final void customizerRemoved(final ServiceReference<S> item,
+ final ServiceEvent related, final T object) {
+ customizer.removedService(item, object);
}
}
@@ -930,7 +1014,7 @@
* @since 1.3
* @ThreadSafe
*/
- class AllTracked extends Tracked implements AllServiceListener {
+ private class AllTracked extends Tracked implements AllServiceListener {
/**
* AllTracked constructor.
*/
diff --git a/framework/src/main/java/org/osgi/util/tracker/ServiceTrackerCustomizer.java b/framework/src/main/java/org/osgi/util/tracker/ServiceTrackerCustomizer.java
index 5c270e3..b2caddc 100644
--- a/framework/src/main/java/org/osgi/util/tracker/ServiceTrackerCustomizer.java
+++ b/framework/src/main/java/org/osgi/util/tracker/ServiceTrackerCustomizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2000, 2008). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2010). 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.
@@ -19,76 +19,78 @@
import org.osgi.framework.ServiceReference;
/**
- * The <code>ServiceTrackerCustomizer</code> interface allows a
- * <code>ServiceTracker</code> to customize the service objects that are
- * tracked. A <code>ServiceTrackerCustomizer</code> is called when a service is
- * being added to a <code>ServiceTracker</code>. The
- * <code>ServiceTrackerCustomizer</code> can then return an object for the
- * tracked service. A <code>ServiceTrackerCustomizer</code> is also called when
+ * The {@code ServiceTrackerCustomizer} interface allows a
+ * {@code ServiceTracker} to customize the service objects that are
+ * tracked. A {@code ServiceTrackerCustomizer} is called when a service is
+ * being added to a {@code ServiceTracker}. The
+ * {@code ServiceTrackerCustomizer} can then return an object for the
+ * tracked service. A {@code ServiceTrackerCustomizer} is also called when
* a tracked service is modified or has been removed from a
- * <code>ServiceTracker</code>.
+ * {@code ServiceTracker}.
*
* <p>
* The methods in this interface may be called as the result of a
- * <code>ServiceEvent</code> being received by a <code>ServiceTracker</code>.
- * Since <code>ServiceEvent</code>s are synchronously delivered by the
+ * {@code ServiceEvent} being received by a {@code ServiceTracker}.
+ * Since {@code ServiceEvent}s are synchronously delivered by the
* Framework, it is highly recommended that implementations of these methods do
- * not register (<code>BundleContext.registerService</code>), modify (
- * <code>ServiceRegistration.setProperties</code>) or unregister (
- * <code>ServiceRegistration.unregister</code>) a service while being
+ * not register ({@code BundleContext.registerService}), modify (
+ * {@code ServiceRegistration.setProperties}) or unregister (
+ * {@code ServiceRegistration.unregister}) a service while being
* synchronized on any object.
*
* <p>
- * The <code>ServiceTracker</code> class is thread-safe. It does not call a
- * <code>ServiceTrackerCustomizer</code> while holding any locks.
- * <code>ServiceTrackerCustomizer</code> implementations must also be
+ * The {@code ServiceTracker} class is thread-safe. It does not call a
+ * {@code ServiceTrackerCustomizer} while holding any locks.
+ * {@code ServiceTrackerCustomizer} implementations must also be
* thread-safe.
*
+ * @param <S> The type of the service being tracked.
+ * @param <T> The type of the tracked object.
* @ThreadSafe
- * @version $Revision: 5874 $
+ * @version $Id: c654a963336cee74762b8f54c8cef8d5774f8b4d $
*/
-public interface ServiceTrackerCustomizer {
+public interface ServiceTrackerCustomizer<S, T> {
/**
- * A service is being added to the <code>ServiceTracker</code>.
+ * A service is being added to the {@code ServiceTracker}.
*
* <p>
* This method is called before a service which matched the search
- * parameters of the <code>ServiceTracker</code> is added to the
- * <code>ServiceTracker</code>. This method should return the service object
- * to be tracked for the specified <code>ServiceReference</code>. The
- * returned service object is stored in the <code>ServiceTracker</code> and
- * is available from the <code>getService</code> and
- * <code>getServices</code> methods.
+ * parameters of the {@code ServiceTracker} is added to the
+ * {@code ServiceTracker}. This method should return the service object
+ * to be tracked for the specified {@code ServiceReference}. The
+ * returned service object is stored in the {@code ServiceTracker} and
+ * is available from the {@code getService} and
+ * {@code getServices} methods.
*
* @param reference The reference to the service being added to the
- * <code>ServiceTracker</code>.
+ * {@code ServiceTracker}.
* @return The service object to be tracked for the specified referenced
- * service or <code>null</code> if the specified referenced service
+ * service or {@code null} if the specified referenced service
* should not be tracked.
*/
- public Object addingService(ServiceReference reference);
+ public T addingService(ServiceReference<S> reference);
/**
- * A service tracked by the <code>ServiceTracker</code> has been modified.
+ * A service tracked by the {@code ServiceTracker} has been modified.
*
* <p>
* This method is called when a service being tracked by the
- * <code>ServiceTracker</code> has had it properties modified.
+ * {@code ServiceTracker} has had it properties modified.
*
* @param reference The reference to the service that has been modified.
* @param service The service object for the specified referenced service.
*/
- public void modifiedService(ServiceReference reference, Object service);
+ public void modifiedService(ServiceReference<S> reference, T service);
/**
- * A service tracked by the <code>ServiceTracker</code> has been removed.
+ * A service tracked by the {@code ServiceTracker} has been removed.
*
* <p>
* This method is called after a service is no longer being tracked by the
- * <code>ServiceTracker</code>.
+ * {@code ServiceTracker}.
*
* @param reference The reference to the service that has been removed.
* @param service The service object for the specified referenced service.
*/
- public void removedService(ServiceReference reference, Object service);
+ public void removedService(ServiceReference<S> reference, T service);
}
diff --git a/framework/src/main/resources/org/osgi/framework/hooks/bundle/packageinfo b/framework/src/main/resources/org/osgi/framework/hooks/bundle/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/framework/src/main/resources/org/osgi/framework/hooks/bundle/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/framework/src/main/resources/org/osgi/framework/hooks/resolver/packageinfo b/framework/src/main/resources/org/osgi/framework/hooks/resolver/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/framework/src/main/resources/org/osgi/framework/hooks/resolver/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/framework/src/main/resources/org/osgi/framework/hooks/service/packageinfo b/framework/src/main/resources/org/osgi/framework/hooks/service/packageinfo
index 7c8de03..3987f9c 100644
--- a/framework/src/main/resources/org/osgi/framework/hooks/service/packageinfo
+++ b/framework/src/main/resources/org/osgi/framework/hooks/service/packageinfo
@@ -1 +1 @@
-version 1.0
+version 1.1
diff --git a/framework/src/main/resources/org/osgi/framework/hooks/weaving/packageinfo b/framework/src/main/resources/org/osgi/framework/hooks/weaving/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/framework/src/main/resources/org/osgi/framework/hooks/weaving/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/framework/src/main/resources/org/osgi/framework/packageinfo b/framework/src/main/resources/org/osgi/framework/packageinfo
index ccee95e..fec6063 100644
--- a/framework/src/main/resources/org/osgi/framework/packageinfo
+++ b/framework/src/main/resources/org/osgi/framework/packageinfo
@@ -1 +1 @@
-version 1.5
+version 1.6
diff --git a/framework/src/main/resources/org/osgi/framework/startlevel/packageinfo b/framework/src/main/resources/org/osgi/framework/startlevel/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/framework/src/main/resources/org/osgi/framework/startlevel/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/framework/src/main/resources/org/osgi/framework/wiring/packageinfo b/framework/src/main/resources/org/osgi/framework/wiring/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/framework/src/main/resources/org/osgi/framework/wiring/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/framework/src/main/resources/org/osgi/util/tracker/packageinfo b/framework/src/main/resources/org/osgi/util/tracker/packageinfo
index cc13f19..ccee95e 100644
--- a/framework/src/main/resources/org/osgi/util/tracker/packageinfo
+++ b/framework/src/main/resources/org/osgi/util/tracker/packageinfo
@@ -1 +1 @@
-version 1.4
+version 1.5