felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rickh...@apache.org
Subject svn commit: r1103907 [6/8] - in /felix/trunk/framework/src/main/java/org: apache/felix/framework/ osgi/framework/ osgi/framework/startlevel/ osgi/framework/wiring/
Date Mon, 16 May 2011 21:30:33 GMT
Modified: felix/trunk/framework/src/main/java/org/osgi/framework/FrameworkUtil.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/osgi/framework/FrameworkUtil.java?rev=1103907&r1=1103906&r2=1103907&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/osgi/framework/FrameworkUtil.java (original)
+++ felix/trunk/framework/src/main/java/org/osgi/framework/FrameworkUtil.java Mon May 16 21:30:32 2011
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2005, 2009). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2005, 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.
@@ -21,12 +21,15 @@ 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;
 
@@ -39,7 +42,7 @@ import javax.security.auth.x500.X500Prin
  * 
  * @since 1.3
  * @ThreadSafe
- * @version $Revision: 7761 $
+ * @version $Id: a902bc156ea997ed244831c7fab0f290a08ac0c1 $
  */
 public class FrameworkUtil {
 	/**
@@ -50,9 +53,9 @@ public class FrameworkUtil {
 	}
 
 	/**
-	 * Creates a <code>Filter</code> object. This <code>Filter</code> object may
-	 * be used to match a <code>ServiceReference</code> object or a
-	 * <code>Dictionary</code> object.
+	 * Creates a {@code Filter} object. This {@code Filter} object may
+	 * be used to match a {@code ServiceReference} object or a
+	 * {@code Dictionary} object.
 	 * 
 	 * <p>
 	 * If the filter cannot be parsed, an {@link InvalidSyntaxException} will be
@@ -64,16 +67,16 @@ public class FrameworkUtil {
 	 * by {@link BundleContext#createFilter(String)}.
 	 * 
 	 * @param filter The filter string.
-	 * @return A <code>Filter</code> object encapsulating the filter string.
-	 * @throws InvalidSyntaxException If <code>filter</code> contains an invalid
+	 * @return A {@code Filter} object encapsulating the filter string.
+	 * @throws InvalidSyntaxException If {@code filter} contains an invalid
 	 *         filter string that cannot be parsed.
-	 * @throws NullPointerException If <code>filter</code> is null.
+	 * @throws NullPointerException If {@code filter} is null.
 	 * 
 	 * @see Filter
 	 */
 	public static Filter createFilter(String filter)
 			throws InvalidSyntaxException {
-		return new org.apache.felix.framework.FilterImpl(filter);
+		return FilterImpl.newInstance(filter);
 	}
 
 	/**
@@ -102,8 +105,8 @@ public class FrameworkUtil {
 	 * wildcard can also replace the first list of RDNs of a DN. The first RDNs
 	 * are the least significant. Such lists of matched RDNs can be empty.
 	 * <p>
-	 * For example, a match pattern with a wildcard that matches all all DNs
-	 * that end with RDNs of o=ACME and c=US would look like this:
+	 * For example, a match pattern with a wildcard that matches all DNs that
+	 * end with RDNs of o=ACME and c=US would look like this:
 	 * 
 	 * <pre>
 	 * *, o=ACME, c=US
@@ -176,34 +179,36 @@ public class FrameworkUtil {
 	 * 
 	 * @param matchPattern The pattern against which to match the DN chain.
 	 * @param dnChain The DN chain to match against the specified pattern. Each
-	 *        element of the chain must be of type <code>String</code> and use
-	 *        the format defined in RFC 2253.
-	 * @return <code>true</code> If the pattern matches the DN chain; otherwise
-	 *         <code>false</code> is returned.
+	 *        element of the chain must be of type {@code String} and use the
+	 *        format defined in <a
+	 *        href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a>.
+	 * @return {@code true} If the pattern matches the DN chain; otherwise
+	 *         {@code false} is returned.
 	 * @throws IllegalArgumentException If the specified match pattern or DN
 	 *         chain is invalid.
 	 * @since 1.5
 	 */
 	public static boolean matchDistinguishedNameChain(String matchPattern,
-			List /* <String> */dnChain) {
+			List<String> dnChain) {
 		return DNChainMatching.match(matchPattern, dnChain);
 	}
 
 	/**
-	 * Return a <code>Bundle</code> for the specified bundle class. The returned
-	 * <code>Bundle</code> is the bundle associated with the bundle class loader
+	 * Return a {@code Bundle} for the specified bundle class. The returned
+	 * {@code Bundle} is the bundle associated with the bundle class loader
 	 * which defined the specified class.
 	 * 
 	 * @param classFromBundle A class defined by a bundle class loader.
-	 * @return A <code>Bundle</code> for the specified bundle class or
-	 *         <code>null</code> if the specified class was not defined by a
+	 * @return A {@code Bundle} for the specified bundle class or
+	 *         {@code null} if the specified class was not defined by a
 	 *         bundle class loader.
 	 * @since 1.5
 	 */
-	public static Bundle getBundle(final Class classFromBundle) {
+	public static Bundle getBundle(final Class< ? > classFromBundle) {
 		// We use doPriv since the caller may not have permission
 		// to call getClassLoader.
-		Object cl = AccessController.doPrivileged(new PrivilegedAction() {
+		Object cl = AccessController
+				.doPrivileged(new PrivilegedAction<Object>() {
 			public Object run() {
 				return classFromBundle.getClassLoader();
 			}
@@ -216,6 +221,1518 @@ public class FrameworkUtil {
 	}
 
 	/**
+	 * 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>
+	 *   &lt;filter&gt; ::= '(' &lt;filtercomp&gt; ')'
+	 *   &lt;filtercomp&gt; ::= &lt;and&gt; | &lt;or&gt; | &lt;not&gt; | &lt;item&gt;
+	 *   &lt;and&gt; ::= '&amp;' &lt;filterlist&gt;
+	 *   &lt;or&gt; ::= '|' &lt;filterlist&gt;
+	 *   &lt;not&gt; ::= '!' &lt;filter&gt;
+	 *   &lt;filterlist&gt; ::= &lt;filter&gt; | &lt;filter&gt; &lt;filterlist&gt;
+	 *   &lt;item&gt; ::= &lt;simple&gt; | &lt;present&gt; | &lt;substring&gt;
+	 *   &lt;simple&gt; ::= &lt;attr&gt; &lt;filtertype&gt; &lt;value&gt;
+	 *   &lt;filtertype&gt; ::= &lt;equal&gt; | &lt;approx&gt; | &lt;greater&gt; | &lt;less&gt;
+	 *   &lt;equal&gt; ::= '='
+	 *   &lt;approx&gt; ::= '&tilde;='
+	 *   &lt;greater&gt; ::= '&gt;='
+	 *   &lt;less&gt; ::= '&lt;='
+	 *   &lt;present&gt; ::= &lt;attr&gt; '=*'
+	 *   &lt;substring&gt; ::= &lt;attr&gt; '=' &lt;initial&gt; &lt;any&gt; &lt;final&gt;
+	 *   &lt;initial&gt; ::= NULL | &lt;value&gt;
+	 *   &lt;any&gt; ::= '*' &lt;starval&gt;
+	 *   &lt;starval&gt; ::= NULL | &lt;value&gt; '*' &lt;starval&gt;
+	 *   &lt;final&gt; ::= NULL | &lt;value&gt;
+	 * </pre>
+	 * 
+	 * {@code &lt;attr&gt;} 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 &lt;value&gt;} is a string representing the value, or part of
+	 * one, of a key in the properties objects of the registered services. If a
+	 * {@code &lt;value&gt;} 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 &lt;substring&gt;} and
+	 * {@code &lt;present&gt;} productions can produce the {@code 'attr=*'}
+	 * construct, this construct is used only to denote a presence filter.
+	 * 
+	 * <p>
+	 * Examples of LDAP filters are:
+	 * 
+	 * <pre>
+	 *   &quot;(cn=Babs Jensen)&quot;
+	 *   &quot;(!(cn=Tim Howes))&quot;
+	 *   &quot;(&amp;(&quot; + Constants.OBJECTCLASS + &quot;=Person)(|(sn=Jensen)(cn=Babs J*)))&quot;
+	 *   &quot;(o=univ*of*mich*)&quot;
+	 * </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(&quot;cn&quot;, new String[] {&quot;a&quot;, &quot;b&quot;, &quot;c&quot;});
+	 * </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>
@@ -229,12 +1746,12 @@ public class FrameworkUtil {
 	 *   cn=ben+ou=research,o=ACME,c=us;ou=Super CA,c=CA
 	 * </pre>
 	 * 
-	 * is made up of two DNs: "<code>cn=ben+ou=research,o=ACME,c=us</code>
-	 * " and " <code>ou=Super CA,c=CA</code>
+	 * is made up of two DNs: "{@code cn=ben+ou=research,o=ACME,c=us}
+	 * " and " {@code ou=Super CA,c=CA}
 	 * ". The first DN is made of of three RDNs: "
-	 * <code>cn=ben+ou=research</code>" and "<code>o=ACME</code>" and "
-	 * <code>c=us</code>". The first RDN has two name value pairs: "
-	 * <code>cn=ben</code>" and "<code>ou=research</code>".
+	 * {@code cn=ben+ou=research}" and "{@code o=ACME}" and "
+	 * {@code c=us}". The first RDN has two name value pairs: "
+	 * {@code cn=ben}" and "{@code ou=research}".
 	 * <p>
 	 * A chain pattern makes use of wildcards ('*' or '-') to match against DNs,
 	 * and wildcards ('*') to match againts DN prefixes, and value. If a DN in a
@@ -246,7 +1763,7 @@ public class FrameworkUtil {
 	 * removed). If a value of a name/value pair is a wildcard ("*"), the value
 	 * will match any value for that name.
 	 */
-	private static class DNChainMatching {
+	static private final class DNChainMatching {
 		private static final String	MINUS_WILDCARD	= "-";
 		private static final String	STAR_WILDCARD	= "*";
 
@@ -257,7 +1774,7 @@ public class FrameworkUtil {
 		 * @param rdnPattern List of name value pattern pairs.
 		 * @return true if the list of name value pairs match the pattern.
 		 */
-		private static boolean rdnmatch(List rdn, List rdnPattern) {
+		private static boolean rdnmatch(List< ? > rdn, List< ? > rdnPattern) {
 			if (rdn.size() != rdnPattern.size()) {
 				return false;
 			}
@@ -281,7 +1798,7 @@ public class FrameworkUtil {
 			return true;
 		}
 
-		private static boolean dnmatch(List dn, List dnPattern) {
+		private static boolean dnmatch(List< ? > dn, List< ? > dnPattern) {
 			int dnStart = 0;
 			int patStart = 0;
 			int patLen = dnPattern.size();
@@ -308,7 +1825,8 @@ public class FrameworkUtil {
 				}
 			}
 			for (int i = 0; i < patLen; i++) {
-				if (!rdnmatch((List) dn.get(i + dnStart), (List) dnPattern
+				if (!rdnmatch((List< ? >) dn.get(i + dnStart),
+						(List< ? >) dnPattern
 						.get(i + patStart))) {
 					return false;
 				}
@@ -329,12 +1847,12 @@ public class FrameworkUtil {
 		 * @return a list of DNs.
 		 * @throws IllegalArgumentException
 		 */
-		private static List parseDNchainPattern(String dnChain) {
+		private static List<Object> parseDNchainPattern(String dnChain) {
 			if (dnChain == null) {
 				throw new IllegalArgumentException(
 						"The DN chain must not be null.");
 			}
-			List parsed = new ArrayList();
+			List<Object> parsed = new ArrayList<Object>();
 			int startIndex = 0;
 			startIndex = skipSpaces(dnChain, startIndex);
 			while (startIndex < dnChain.length()) {
@@ -362,22 +1880,15 @@ public class FrameworkUtil {
 				startIndex = endIndex + 1;
 				startIndex = skipSpaces(dnChain, startIndex);
 			}
-			return parseDNchain(parsed);
-		}
 
-		private static List parseDNchain(List chain) {
-			if (chain == null) {
-				throw new IllegalArgumentException("DN chain must not be null.");
-			}
-			chain = new ArrayList(chain);
 			// Now we parse is a list of strings, lets make List of rdn out
 			// of them
-			for (int i = 0; i < chain.size(); i++) {
-				String dn = (String) chain.get(i);
+			for (int i = 0; i < parsed.size(); i++) {
+				String dn = (String) parsed.get(i);
 				if (dn.equals(STAR_WILDCARD) || dn.equals(MINUS_WILDCARD)) {
 					continue;
 				}
-				List rdns = new ArrayList();
+				List<Object> rdns = new ArrayList<Object>();
 				if (dn.charAt(0) == '*') {
 					if (dn.charAt(1) != ',') {
 						throw new IllegalArgumentException(
@@ -392,12 +1903,32 @@ public class FrameworkUtil {
 				}
 				// Now dn is a nice CANONICAL DN
 				parseDN(dn, rdns);
-				chain.set(i, rdns);
+				parsed.set(i, rdns);
+			}
+			if (parsed.size() == 0) {
+				throw new IllegalArgumentException("empty DN chain");
+			}
+			return parsed;
+		}
+
+		private static List<Object> parseDNchain(List<String> chain) {
+			if (chain == null) {
+				throw new IllegalArgumentException("DN chain must not be null.");
+			}
+			List<Object> result = new ArrayList<Object>(chain.size());
+			// Now we parse is a list of strings, lets make List of rdn out
+			// of them
+			for (String dn : chain) {
+				dn = new X500Principal(dn).getName(X500Principal.CANONICAL);
+				// Now dn is a nice CANONICAL DN
+				List<Object> rdns = new ArrayList<Object>();
+				parseDN(dn, rdns);
+				result.add(rdns);
 			}
-			if (chain.size() == 0) {
+			if (result.size() == 0) {
 				throw new IllegalArgumentException("empty DN chain");
 			}
-			return chain;
+			return result;
 		}
 
 		/**
@@ -420,10 +1951,10 @@ public class FrameworkUtil {
 		 * @param rdn the list to fill in with RDNs extracted from the dn
 		 * @throws IllegalArgumentException if a formatting error is found.
 		 */
-		private static void parseDN(String dn, List rdn) {
+		private static void parseDN(String dn, List<Object> rdn) {
 			int startIndex = 0;
 			char c = '\0';
-			List nameValues = new ArrayList();
+			List<String> nameValues = new ArrayList<String>();
 			while (startIndex < dn.length()) {
 				int endIndex;
 				for (endIndex = startIndex; endIndex < dn.length(); endIndex++) {
@@ -443,7 +1974,7 @@ public class FrameworkUtil {
 				if (c != '+') {
 					rdn.add(nameValues);
 					if (endIndex != dn.length()) {
-						nameValues = new ArrayList();
+						nameValues = new ArrayList<String>();
 					}
 					else {
 						nameValues = null;
@@ -461,7 +1992,7 @@ public class FrameworkUtil {
 		 * This method will return an 'index' which points to a non-wildcard DN
 		 * or the end-of-list.
 		 */
-		private static int skipWildCards(List dnChainPattern,
+		private static int skipWildCards(List<Object> dnChainPattern,
 				int dnChainPatternIndex) {
 			int i;
 			for (i = dnChainPatternIndex; i < dnChainPattern.size(); i++) {
@@ -475,7 +2006,7 @@ public class FrameworkUtil {
 					// otherwise continue skipping over wild cards
 				}
 				else {
-					if (dnPattern instanceof List) {
+					if (dnPattern instanceof List< ? >) {
 						// if its a list then we have our 'non-wildcard' DN
 						break;
 					}
@@ -496,8 +2027,9 @@ public class FrameworkUtil {
 		 * where DNChain is of the format: "DN;DN;DN;" and DNChainPattern is of
 		 * the format: "DNPattern;*;DNPattern" (or combinations of this)
 		 */
-		private static boolean dnChainMatch(List dnChain, int dnChainIndex,
-				List dnChainPattern, int dnChainPatternIndex)
+		private static boolean dnChainMatch(List<Object> dnChain,
+				int dnChainIndex, List<Object> dnChainPattern,
+				int dnChainPatternIndex)
 				throws IllegalArgumentException {
 			if (dnChainIndex >= dnChain.size()) {
 				return false;
@@ -551,12 +2083,12 @@ public class FrameworkUtil {
 				// failure
 			}
 			else {
-				if (dnPattern instanceof List) {
+				if (dnPattern instanceof List< ? >) {
 					// here we have to do a deeper check for each DN in the
 					// pattern until we hit a wild card
 					do {
-						if (!dnmatch((List) dnChain.get(dnChainIndex),
-								(List) dnPattern)) {
+						if (!dnmatch((List< ? >) dnChain.get(dnChainIndex),
+								(List< ? >) dnPattern)) {
 							return false;
 						}
 						// go to the next set of DN's in both chains
@@ -598,7 +2130,7 @@ public class FrameworkUtil {
 									dnChainPattern, dnChainPatternIndex);
 						}
 						else {
-							if (!(dnPattern instanceof List)) {
+							if (!(dnPattern instanceof List< ? >)) {
 								throw new IllegalArgumentException(
 										"expected String or List in DN Pattern");
 							}
@@ -651,9 +2183,9 @@ public class FrameworkUtil {
 		 * @return true if dnChain matches the pattern.
 		 * @throws IllegalArgumentException
 		 */
-		static boolean match(String pattern, List/* <String> */dnChain) {
-			List parsedDNChain;
-			List parsedDNPattern;
+		static boolean match(String pattern, List<String> dnChain) {
+			List<Object> parsedDNChain;
+			List<Object> parsedDNPattern;
 			try {
 				parsedDNChain = parseDNchain(dnChain);
 			}
@@ -675,12 +2207,12 @@ public class FrameworkUtil {
 			return dnChainMatch(parsedDNChain, 0, parsedDNPattern, 0);
 		}
 
-		private static String toString(List dnChain) {
+		private static String toString(List< ? > dnChain) {
 			if (dnChain == null) {
 				return null;
 			}
 			StringBuffer sb = new StringBuffer();
-			for (Iterator iChain = dnChain.iterator(); iChain.hasNext();) {
+			for (Iterator< ? > iChain = dnChain.iterator(); iChain.hasNext();) {
 				sb.append(iChain.next());
 				if (iChain.hasNext()) {
 					sb.append("; ");

Modified: felix/trunk/framework/src/main/java/org/osgi/framework/InvalidSyntaxException.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/osgi/framework/InvalidSyntaxException.java?rev=1103907&r1=1103906&r2=1103907&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/osgi/framework/InvalidSyntaxException.java (original)
+++ felix/trunk/framework/src/main/java/org/osgi/framework/InvalidSyntaxException.java Mon May 16 21:30:32 2011
@@ -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.
@@ -21,14 +21,14 @@ package org.osgi.framework;
  * syntax.
  * 
  * <p>
- * An <code>InvalidSyntaxException</code> object indicates that a filter
+ * An {@code InvalidSyntaxException} object indicates that a filter
  * string parameter has an invalid syntax and cannot be parsed. See
  * {@link Filter} for a description of the filter string syntax.
  * 
  * <p>
  * This exception conforms to the general purpose exception chaining mechanism.
  * 
- * @version $Revision: 6083 $
+ * @version $Id: adb84e3bc0b82b842e4da84542057fdf53e2ca6a $
  */
 
 public class InvalidSyntaxException extends Exception {
@@ -39,10 +39,10 @@ public class InvalidSyntaxException exte
 	private final String	filter;
 
 	/**
-	 * Creates an exception of type <code>InvalidSyntaxException</code>.
+	 * Creates an exception of type {@code InvalidSyntaxException}.
 	 * 
 	 * <p>
-	 * This method creates an <code>InvalidSyntaxException</code> object with
+	 * This method creates an {@code InvalidSyntaxException} object with
 	 * the specified message and the filter string which generated the
 	 * exception.
 	 * 
@@ -55,10 +55,10 @@ public class InvalidSyntaxException exte
 	}
 
 	/**
-	 * Creates an exception of type <code>InvalidSyntaxException</code>.
+	 * Creates an exception of type {@code InvalidSyntaxException}.
 	 * 
 	 * <p>
-	 * This method creates an <code>InvalidSyntaxException</code> object with
+	 * This method creates an {@code InvalidSyntaxException} object with
 	 * the specified message and the filter string which generated the
 	 * exception.
 	 * 
@@ -74,7 +74,7 @@ public class InvalidSyntaxException exte
 
 	/**
 	 * Returns the filter string that generated the
-	 * <code>InvalidSyntaxException</code> object.
+	 * {@code InvalidSyntaxException} object.
 	 * 
 	 * @return The invalid filter string.
 	 * @see BundleContext#getServiceReferences
@@ -85,10 +85,10 @@ public class InvalidSyntaxException exte
 	}
 
 	/**
-	 * Returns the cause of this exception or <code>null</code> if no cause was
+	 * Returns the cause of this exception or {@code null} if no cause was
 	 * set.
 	 * 
-	 * @return The cause of this exception or <code>null</code> if no cause was
+	 * @return The cause of this exception or {@code null} if no cause was
 	 *         set.
 	 * @since 1.3
 	 */

Modified: felix/trunk/framework/src/main/java/org/osgi/framework/PackagePermission.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/osgi/framework/PackagePermission.java?rev=1103907&r1=1103906&r2=1103907&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/osgi/framework/PackagePermission.java (original)
+++ felix/trunk/framework/src/main/java/org/osgi/framework/PackagePermission.java Mon May 16 21:30:32 2011
@@ -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.
@@ -29,11 +29,9 @@ import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Hashtable;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -51,35 +49,35 @@ import java.util.Map;
  * </pre>
  * 
  * <p>
- * <code>PackagePermission</code> has three actions: <code>exportonly</code>,
- * <code>import</code> and <code>export</code>. The <code>export</code> action,
- * which is deprecated, implies the <code>import</code> action.
+ * {@code PackagePermission} has three actions: {@code exportonly},
+ * {@code import} and {@code export}. The {@code export} action,
+ * which is deprecated, implies the {@code import} action.
  * 
  * @ThreadSafe
- * @version $Revision: 7189 $
+ * @version $Id: a286af94405e583f8bedc2ff5d7c818198f8caaf $
  */
 
 public final class PackagePermission extends BasicPermission {
 	static final long						serialVersionUID	= -5107705877071099135L;
 
 	/**
-	 * The action string <code>export</code>. The <code>export</code> action
-	 * implies the <code>import</code> action.
+	 * The action string {@code export}. The {@code export} action
+	 * implies the {@code import} action.
 	 * 
-	 * @deprecated Since 1.5. Use <code>exportonly</code> instead.
+	 * @deprecated Since 1.5. Use {@code exportonly} instead.
 	 */
 	public final static String				EXPORT				= "export";
 
 	/**
-	 * The action string <code>exportonly</code>. The <code>exportonly</code>
-	 * action does not imply the <code>import</code> action.
+	 * The action string {@code exportonly}. The {@code exportonly}
+	 * action does not imply the {@code import} action.
 	 * 
 	 * @since 1.5
 	 */
 	public final static String				EXPORTONLY			= "exportonly";
 
 	/**
-	 * The action string <code>import</code>.
+	 * The action string {@code import}.
 	 */
 	public final static String				IMPORT				= "import";
 
@@ -113,14 +111,14 @@ public final class PackagePermission ext
 	transient Filter						filter;
 
 	/**
-	 * This dictionary holds the properties of the permission, used to match a
-	 * filter in implies. This is not initialized until necessary, and then
-	 * cached in this object.
+	 * This map holds the properties of the permission, used to match a filter
+	 * in implies. This is not initialized until necessary, and then cached in
+	 * this object.
 	 */
-	private transient volatile Dictionary	properties;
+	private transient volatile Map<String, Object>	properties;
 
 	/**
-	 * Creates a new <code>PackagePermission</code> object.
+	 * Creates a new {@code PackagePermission} object.
 	 * 
 	 * <p>
 	 * The name is specified as a normal Java package name: a dot-separated
@@ -138,7 +136,7 @@ public final class PackagePermission ext
 	 * *
 	 * </pre>
 	 * 
-	 * For the <code>import</code> action, the name can also be a filter
+	 * For the {@code import} action, the name can also be a filter
 	 * expression. The filter gives access to the following attributes:
 	 * <ul>
 	 * <li>signer - A Distinguished Name chain used to sign the exporting
@@ -155,19 +153,19 @@ public final class PackagePermission ext
 	 * Package Permissions are granted over all possible versions of a package.
 	 * 
 	 * A bundle that needs to export a package must have the appropriate
-	 * <code>PackagePermission</code> for that package; similarly, a bundle that
+	 * {@code PackagePermission} for that package; similarly, a bundle that
 	 * needs to import a package must have the appropriate
-	 * <code>PackagePermssion</code> for that package.
+	 * {@code PackagePermssion} for that package.
 	 * <p>
 	 * Permission is granted for both classes and resources.
 	 * 
 	 * @param name Package name or filter expression. A filter expression can
-	 *        only be specified if the specified action is <code>import</code>.
-	 * @param actions <code>exportonly</code>,<code>import</code> (canonical
+	 *        only be specified if the specified action is {@code import}.
+	 * @param actions {@code exportonly},{@code import} (canonical
 	 *        order).
 	 * @throws IllegalArgumentException If the specified name is a filter
 	 *         expression and either the specified action is not
-	 *         <code>import</code> or the filter has an invalid syntax.
+	 *         {@code import} or the filter has an invalid syntax.
 	 */
 	public PackagePermission(String name, String actions) {
 		this(name, parseActions(actions));
@@ -179,17 +177,17 @@ public final class PackagePermission ext
 	}
 
 	/**
-	 * Creates a new requested <code>PackagePermission</code> object to be used
-	 * by code that must perform <code>checkPermission</code> for the
-	 * <code>import</code> action. <code>PackagePermission</code> objects
+	 * Creates a new requested {@code PackagePermission} object to be used
+	 * by code that must perform {@code checkPermission} for the
+	 * {@code import} action. {@code PackagePermission} objects
 	 * created with this constructor cannot be added to a
-	 * <code>PackagePermission</code> permission collection.
+	 * {@code PackagePermission} permission collection.
 	 * 
 	 * @param name The name of the requested package to import.
 	 * @param exportingBundle The bundle exporting the requested package.
-	 * @param actions The action <code>import</code>.
+	 * @param actions The action {@code import}.
 	 * @throws IllegalArgumentException If the specified action is not
-	 *         <code>import</code> or the name is a filter expression.
+	 *         {@code import} or the name is a filter expression.
 	 * @since 1.5
 	 */
 	public PackagePermission(String name, Bundle exportingBundle, String actions) {
@@ -345,7 +343,7 @@ public final class PackagePermission ext
 	 * 
 	 * @param filterString The filter string to parse.
 	 * @return a Filter for this bundle. If the specified filterString is not a
-	 *         filter expression, then <code>null</code> is returned.
+	 *         filter expression, then {@code null} is returned.
 	 * @throws IllegalArgumentException If the filter syntax is invalid.
 	 */
 	private static Filter parseFilter(String filterString) {
@@ -370,9 +368,9 @@ public final class PackagePermission ext
 	 * 
 	 * <p>
 	 * This method checks that the package name of the target is implied by the
-	 * package name of this object. The list of <code>PackagePermission</code>
+	 * package name of this object. The list of {@code PackagePermission}
 	 * actions must either match or allow for the list of the target object to
-	 * imply the target <code>PackagePermission</code> action.
+	 * imply the target {@code PackagePermission} action.
 	 * <p>
 	 * The permission to export a package implies the permission to import the
 	 * named package.
@@ -385,8 +383,8 @@ public final class PackagePermission ext
 	 * </pre>
 	 * 
 	 * @param p The requested permission.
-	 * @return <code>true</code> if the specified permission is implied by this
-	 *         object; <code>false</code> otherwise.
+	 * @return {@code true} if the specified permission is implied by this
+	 *         object; {@code false} otherwise.
 	 */
 	public boolean implies(Permission p) {
 		if (!(p instanceof PackagePermission)) {
@@ -411,8 +409,8 @@ public final class PackagePermission ext
 	 *        validated as a proper argument. The requested PackagePermission
 	 *        must not have a filter expression.
 	 * @param effective The effective actions with which to start.
-	 * @return <code>true</code> if the specified permission is implied by this
-	 *         object; <code>false</code> otherwise.
+	 * @return {@code true} if the specified permission is implied by this
+	 *         object; {@code false} otherwise.
 	 */
 	boolean implies0(PackagePermission requested, int effective) {
 		/* check actions first - much faster */
@@ -426,19 +424,19 @@ public final class PackagePermission ext
 		if (f == null) {
 			return super.implies(requested);
 		}
-		return f.matchCase(requested.getProperties());
+		return f.matches(requested.getProperties());
 	}
 
 	/**
 	 * Returns the canonical string representation of the
-	 * <code>PackagePermission</code> actions.
+	 * {@code PackagePermission} actions.
 	 * 
 	 * <p>
-	 * Always returns present <code>PackagePermission</code> actions in the
-	 * following order: <code>EXPORTONLY</code>,<code>IMPORT</code>.
+	 * Always returns present {@code PackagePermission} actions in the
+	 * following order: {@code EXPORTONLY},{@code IMPORT}.
 	 * 
 	 * @return Canonical string representation of the
-	 *         <code>PackagePermission</code> actions.
+	 *         {@code PackagePermission} actions.
 	 */
 	public String getActions() {
 		String result = actions;
@@ -464,28 +462,28 @@ public final class PackagePermission ext
 	}
 
 	/**
-	 * Returns a new <code>PermissionCollection</code> object suitable for
-	 * storing <code>PackagePermission</code> objects.
+	 * Returns a new {@code PermissionCollection} object suitable for
+	 * storing {@code PackagePermission} objects.
 	 * 
-	 * @return A new <code>PermissionCollection</code> object.
+	 * @return A new {@code PermissionCollection} object.
 	 */
 	public PermissionCollection newPermissionCollection() {
 		return new PackagePermissionCollection();
 	}
 
 	/**
-	 * Determines the equality of two <code>PackagePermission</code> objects.
+	 * Determines the equality of two {@code PackagePermission} objects.
 	 * 
 	 * This method checks that specified package has the same package name and
-	 * <code>PackagePermission</code> actions as this
-	 * <code>PackagePermission</code> object.
+	 * {@code PackagePermission} actions as this
+	 * {@code PackagePermission} object.
 	 * 
 	 * @param obj The object to test for equality with this
-	 *        <code>PackagePermission</code> object.
-	 * @return <code>true</code> if <code>obj</code> is a
-	 *         <code>PackagePermission</code>, and has the same package name and
-	 *         actions as this <code>PackagePermission</code> object;
-	 *         <code>false</code> otherwise.
+	 *        {@code PackagePermission} object.
+	 * @return {@code true} if {@code obj} is a
+	 *         {@code PackagePermission}, and has the same package name and
+	 *         actions as this {@code PackagePermission} object;
+	 *         {@code false} otherwise.
 	 */
 	public boolean equals(Object obj) {
 		if (obj == this) {
@@ -547,42 +545,42 @@ public final class PackagePermission ext
 	}
 
 	/**
-	 * Called by <code><@link PackagePermission#implies(Permission)></code>.
+	 * Called by {@code <@link PackagePermission#implies(Permission)>}. This
+	 * method is only called on a requested permission which cannot have a
+	 * filter set.
 	 * 
-	 * @return a dictionary of properties for this permission.
+	 * @return a map of properties for this permission.
 	 */
-	private Dictionary getProperties() {
-		Dictionary result = properties;
+	private Map<String, Object> getProperties() {
+		Map<String, Object> result = properties;
 		if (result != null) {
 			return result;
 		}
-		final Dictionary dict = new Hashtable(5);
-		if (filter == null) {
-			dict.put("package.name", getName());
-		}
+		final Map<String, Object> map = new HashMap<String, Object>(5);
+		map.put("package.name", getName());
 		if (bundle != null) {
-			AccessController.doPrivileged(new PrivilegedAction() {
+			AccessController.doPrivileged(new PrivilegedAction<Object>() {
 				public Object run() {
-					dict.put("id", new Long(bundle.getBundleId()));
-					dict.put("location", bundle.getLocation());
+					map.put("id", new Long(bundle.getBundleId()));
+					map.put("location", bundle.getLocation());
 					String name = bundle.getSymbolicName();
 					if (name != null) {
-						dict.put("name", name);
+						map.put("name", name);
 					}
 					SignerProperty signer = new SignerProperty(bundle);
 					if (signer.isBundleSigned()) {
-						dict.put("signer", signer);
+						map.put("signer", signer);
 					}
 					return null;
 				}
 			});
 		}
-		return properties = dict;
+		return properties = map;
 	}
 }
 
 /**
- * Stores a set of <code>PackagePermission</code> permissions.
+ * Stores a set of {@code PackagePermission} permissions.
  * 
  * @see java.security.Permission
  * @see java.security.Permissions
@@ -596,7 +594,7 @@ final class PackagePermissionCollection 
 	 * 
 	 * @GuardedBy this
 	 */
-	private transient Map	permissions;
+	private transient Map<String, PackagePermission>	permissions;
 
 	/**
 	 * Boolean saying if "*" is in the collection.
@@ -612,25 +610,25 @@ final class PackagePermissionCollection 
 	 * @serial
 	 * @GuardedBy this
 	 */
-	private Map				filterPermissions;
+	private Map<String, PackagePermission>				filterPermissions;
 
 	/**
 	 * Create an empty PackagePermissions object.
 	 */
 	public PackagePermissionCollection() {
-		permissions = new HashMap();
+		permissions = new HashMap<String, PackagePermission>();
 		all_allowed = false;
 	}
 
 	/**
 	 * Adds a permission to this permission collection.
 	 * 
-	 * @param permission The <code>PackagePermission</code> object to add.
+	 * @param permission The {@code PackagePermission} object to add.
 	 * @throws IllegalArgumentException If the specified permission is not a
-	 *         <code>PackagePermission</code> instance or was constructed with a
+	 *         {@code PackagePermission} instance or was constructed with a
 	 *         Bundle object.
 	 * @throws SecurityException If this
-	 *         <code>PackagePermissionCollection</code> object has been marked
+	 *         {@code PackagePermissionCollection} object has been marked
 	 *         read-only.
 	 */
 	public void add(final Permission permission) {
@@ -653,18 +651,18 @@ final class PackagePermissionCollection 
 		final Filter f = pp.filter;
 		synchronized (this) {
 			/* select the bucket for the permission */
-			Map pc;
+			Map<String, PackagePermission> pc;
 			if (f != null) {
 				pc = filterPermissions;
 				if (pc == null) {
-					filterPermissions = pc = new HashMap();
+					filterPermissions = pc = new HashMap<String, PackagePermission>();
 				}
 			}
 			else {
 				pc = permissions;
 			}
 			
-			final PackagePermission existing = (PackagePermission) pc.get(name);
+			final PackagePermission existing = pc.get(name);
 			if (existing != null) {
 				final int oldMask = existing.action_mask;
 				final int newMask = pp.action_mask;
@@ -689,12 +687,12 @@ final class PackagePermissionCollection 
 
 	/**
 	 * Determines if the specified permissions implies the permissions expressed
-	 * in <code>permission</code>.
+	 * in {@code permission}.
 	 * 
 	 * @param permission The Permission object to compare with this
-	 *        <code>PackagePermission</code> object.
-	 * @return <code>true</code> if <code>permission</code> is a proper subset
-	 *         of a permission in the set; <code>false</code> otherwise.
+	 *        {@code PackagePermission} object.
+	 * @return {@code true} if {@code permission} is a proper subset
+	 *         of a permission in the set; {@code false} otherwise.
 	 */
 	public boolean implies(final Permission permission) {
 		if (!(permission instanceof PackagePermission)) {
@@ -709,13 +707,13 @@ final class PackagePermissionCollection 
 		final int desired = requested.action_mask;
 		int effective = PackagePermission.ACTION_NONE;
 
-		Collection perms;
+		Collection<PackagePermission> perms;
 		synchronized (this) {
-			Map pc = permissions;
+			Map<String, PackagePermission> pc = permissions;
 			PackagePermission pp;
 			/* short circuit if the "*" Permission was added */
 			if (all_allowed) {
-				pp = (PackagePermission) pc.get("*");
+				pp = pc.get("*");
 				if (pp != null) {
 					effective |= pp.action_mask;
 					if ((effective & desired) == desired) {
@@ -727,7 +725,7 @@ final class PackagePermissionCollection 
 			 * strategy: Check for full match first. Then work our way up the
 			 * name looking for matches on a.b.*
 			 */
-			pp = (PackagePermission) pc.get(requestedName);
+			pp = pc.get(requestedName);
 			if (pp != null) {
 				/* we have a direct hit! */
 				effective |= pp.action_mask;
@@ -740,7 +738,7 @@ final class PackagePermissionCollection 
 			int offset = requestedName.length() - 1;
 			while ((last = requestedName.lastIndexOf(".", offset)) != -1) {
 				requestedName = requestedName.substring(0, last + 1) + "*";
-				pp = (PackagePermission) pc.get(requestedName);
+				pp = pc.get(requestedName);
 				if (pp != null) {
 					effective |= pp.action_mask;
 					if ((effective & desired) == desired) {
@@ -760,9 +758,8 @@ final class PackagePermissionCollection 
 			perms = pc.values();
 		}
 		/* iterate one by one over filteredPermissions */
-		for (Iterator iter = perms.iterator(); iter.hasNext();) {
-			if (((PackagePermission) iter.next())
-					.implies0(requested, effective)) {
+		for (PackagePermission perm : perms) {
+			if (perm.implies0(requested, effective)) {
 				return true;
 			}
 		}
@@ -770,14 +767,14 @@ final class PackagePermissionCollection 
 	}
 
 	/**
-	 * Returns an enumeration of all <code>PackagePermission</code> objects in
+	 * Returns an enumeration of all {@code PackagePermission} objects in
 	 * the container.
 	 * 
-	 * @return Enumeration of all <code>PackagePermission</code> objects.
+	 * @return Enumeration of all {@code PackagePermission} objects.
 	 */
-	public synchronized Enumeration elements() {
-		List all = new ArrayList(permissions.values());
-		Map pc = filterPermissions;
+	public synchronized Enumeration<Permission> elements() {
+		List<Permission> all = new ArrayList<Permission>(permissions.values());
+		Map<String, PackagePermission> pc = filterPermissions;
 		if (pc != null) {
 			all.addAll(pc.values());
 		}
@@ -792,7 +789,8 @@ final class PackagePermissionCollection 
 
 	private synchronized void writeObject(ObjectOutputStream out)
 			throws IOException {
-		Hashtable hashtable = new Hashtable(permissions);
+		Hashtable<String, PackagePermission> hashtable = new Hashtable<String, PackagePermission>(
+				permissions);
 		ObjectOutputStream.PutField pfields = out.putFields();
 		pfields.put("permissions", hashtable);
 		pfields.put("all_allowed", all_allowed);
@@ -803,9 +801,12 @@ final class PackagePermissionCollection 
 	private synchronized void readObject(java.io.ObjectInputStream in)
 			throws IOException, ClassNotFoundException {
 		ObjectInputStream.GetField gfields = in.readFields();
-		Hashtable hashtable = (Hashtable) gfields.get("permissions", null);
-		permissions = new HashMap(hashtable);
+		Hashtable<String, PackagePermission> hashtable = (Hashtable<String, PackagePermission>) gfields
+				.get("permissions", null);
+		permissions = new HashMap<String, PackagePermission>(hashtable);
 		all_allowed = gfields.get("all_allowed", false);
-		filterPermissions = (HashMap) gfields.get("filterPermissions", null);
+		HashMap<String, PackagePermission> fp = (HashMap<String, PackagePermission>) gfields
+				.get("filterPermissions", null);
+		filterPermissions = fp;
 	}
 }

Modified: felix/trunk/framework/src/main/java/org/osgi/framework/ServiceEvent.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/osgi/framework/ServiceEvent.java?rev=1103907&r1=1103906&r2=1103907&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/osgi/framework/ServiceEvent.java (original)
+++ felix/trunk/framework/src/main/java/org/osgi/framework/ServiceEvent.java Mon May 16 21:30:32 2011
@@ -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.
@@ -22,8 +22,8 @@ import java.util.EventObject;
 /**
  * An event from the Framework describing a service lifecycle change.
  * <p>
- * <code>ServiceEvent</code> objects are delivered to
- * <code>ServiceListener</code>s and <code>AllServiceListener</code>s when a
+ * {@code ServiceEvent} objects are delivered to
+ * {@code ServiceListener}s and {@code AllServiceListener}s when a
  * change occurs in this service's lifecycle. A type code is used to identify
  * the event type for future extendability.
  * 
@@ -33,7 +33,7 @@ import java.util.EventObject;
  * @Immutable
  * @see ServiceListener
  * @see AllServiceListener
- * @version $Revision: 6542 $
+ * @version $Id: 2b9458d90004411b6ca0cb4b361bc282b04c85eb $
  */
 
 public class ServiceEvent extends EventObject {
@@ -41,7 +41,7 @@ public class ServiceEvent extends EventO
 	/**
 	 * Reference to the service that had a change occur in its lifecycle.
 	 */
-	private final ServiceReference	reference;
+	private final ServiceReference< ? >	reference;
 
 	/**
 	 * Type of service lifecycle change.
@@ -75,7 +75,7 @@ public class ServiceEvent extends EventO
 	 * has completed unregistering.
 	 * 
 	 * <p>
-	 * If a bundle is using a service that is <code>UNREGISTERING</code>, the
+	 * If a bundle is using a service that is {@code UNREGISTERING}, the
 	 * bundle should release its use of the service when it receives this event.
 	 * If the bundle does not release its use of the service when it receives
 	 * this event, the Framework will automatically release the bundle's use of
@@ -92,7 +92,7 @@ public class ServiceEvent extends EventO
 	 * <p>
 	 * This event is synchronously delivered <strong>after</strong> the service
 	 * properties have been modified. This event is only delivered to listeners
-	 * which were added with a non-<code>null</code> filter where the filter
+	 * which were added with a non-{@code null} filter where the filter
 	 * matched the service properties prior to the modification but the filter
 	 * does not match the modified service properties.
 	 * 
@@ -105,10 +105,10 @@ public class ServiceEvent extends EventO
 	 * Creates a new service event object.
 	 * 
 	 * @param type The event type.
-	 * @param reference A <code>ServiceReference</code> object to the service
+	 * @param reference A {@code ServiceReference} object to the service
 	 * 	that had a lifecycle change.
 	 */
-	public ServiceEvent(int type, ServiceReference reference) {
+	public ServiceEvent(int type, ServiceReference< ? > reference) {
 		super(reference);
 		this.reference = reference;
 		this.type = type;
@@ -122,7 +122,7 @@ public class ServiceEvent extends EventO
 	 * 
 	 * @return Reference to the service that had a lifecycle change.
 	 */
-	public ServiceReference getServiceReference() {
+	public ServiceReference< ? > getServiceReference() {
 		return reference;
 	}
 

Modified: felix/trunk/framework/src/main/java/org/osgi/framework/ServiceException.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/osgi/framework/ServiceException.java?rev=1103907&r1=1103906&r2=1103907&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/osgi/framework/ServiceException.java (original)
+++ felix/trunk/framework/src/main/java/org/osgi/framework/ServiceException.java Mon May 16 21:30:32 2011
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) OSGi Alliance (2007, 2009). 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,18 +20,18 @@ package org.osgi.framework;
  * A service exception used to indicate that a service problem occurred.
  * 
  * <p>
- * A <code>ServiceException</code> object is created by the Framework or
+ * A {@code ServiceException} object is created by the Framework or
  * service implementation to denote an exception condition in the service. A
  * type code is used to identify the exception type for future extendability.
  * Service implementations may also create subclasses of
- * <code>ServiceException</code>. When subclassing, the subclass should set
+ * {@code ServiceException}. When subclassing, the subclass should set
  * the type to {@link #SUBCLASSED} to indicate that
- * <code>ServiceException</code> has been subclassed.
+ * {@code ServiceException} has been subclassed.
  * 
  * <p>
  * This exception conforms to the general purpose exception chaining mechanism.
  * 
- * @version $Revision: 6518 $
+ * @version $Id: 453b6021eed4543f754e20696b9f8b33a7e121ee $
  * @since 1.5
  */
 
@@ -68,9 +68,16 @@ public class ServiceException extends Ru
 	 * An error occurred invoking a remote service.
 	 */
 	public static final int REMOTE 				= 5;
+	/**
+	 * The service factory resulted in a recursive call to itself for the
+	 * requesting bundle.
+	 * 
+	 * @since 1.6
+	 */
+	public static final int	FACTORY_RECURSION	= 6;
 
 	/**
-	 * Creates a <code>ServiceException</code> with the specified message and
+	 * Creates a {@code ServiceException} with the specified message and
 	 * exception cause.
 	 * 
 	 * @param msg The associated message.
@@ -81,7 +88,7 @@ public class ServiceException extends Ru
 	}
 
 	/**
-	 * Creates a <code>ServiceException</code> with the specified message.
+	 * Creates a {@code ServiceException} with the specified message.
 	 * 
 	 * @param msg The message.
 	 */
@@ -90,7 +97,7 @@ public class ServiceException extends Ru
 	}
 
 	/**
-	 * Creates a <code>ServiceException</code> with the specified message,
+	 * Creates a {@code ServiceException} with the specified message,
 	 * type and exception cause.
 	 * 
 	 * @param msg The associated message.
@@ -103,7 +110,7 @@ public class ServiceException extends Ru
 	}
 
 	/**
-	 * Creates a <code>ServiceException</code> with the specified message and
+	 * Creates a {@code ServiceException} with the specified message and
 	 * type.
 	 * 
 	 * @param msg The message.
@@ -115,7 +122,7 @@ public class ServiceException extends Ru
 	}
 
 	/**
-	 * Returns the type for this exception or <code>UNSPECIFIED</code> if the
+	 * Returns the type for this exception or {@code UNSPECIFIED} if the
 	 * type was unspecified or unknown.
 	 * 
 	 * @return The type of this exception.



Mime
View raw message