More OSGi API updates. (FELIX-1205)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@807651 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.osgi.core/src/main/java/org/osgi/framework/AdminPermission.java b/org.osgi.core/src/main/java/org/osgi/framework/AdminPermission.java
index c55fc7b..1811791 100644
--- a/org.osgi.core/src/main/java/org/osgi/framework/AdminPermission.java
+++ b/org.osgi.core/src/main/java/org/osgi/framework/AdminPermission.java
@@ -87,7 +87,7 @@
  * Filter attribute names are processed in a case sensitive manner.
  * 
  * @ThreadSafe
- * @version $Revision: 6867 $
+ * @version $Revision: 7743 $
  */
 
 public final class AdminPermission extends BasicPermission {
@@ -213,6 +213,12 @@
 	private transient volatile Dictionary	properties;
 
 	/**
+	 * ThreadLocal used to determine if we have recursively called
+	 * getProperties.
+	 */
+	private static final ThreadLocal		recurse						= new ThreadLocal();
+
+	/**
 	 * Creates a new <code>AdminPermission</code> object that matches all
 	 * bundles and has all actions. Equivalent to AdminPermission("*","*");
 	 */
@@ -647,7 +653,17 @@
 		if (requested.bundle == null) {
 			return false;
 		}
-		return f.matchCase(requested.getProperties());
+		Dictionary requestedProperties = requested.getProperties();
+		if (requestedProperties == null) {
+			/*
+			 * If the requested properties are null, then we have detected a
+			 * recursion getting the bundle location. So we return true to
+			 * permit the bundle location request in the AdminPermission check
+			 * up the stack to succeed.
+			 */
+			return true;
+		}
+		return f.matchCase(requestedProperties);
 	}
 
 	/**
@@ -808,10 +824,10 @@
 	}
 
 	/**
-	 * Called by <code><@link AdminPermission#implies(Permission)></code> on an
-	 * AdminPermission which was constructed with a Bundle. This method loads a
-	 * dictionary with the filter-matchable properties of this bundle. The
-	 * dictionary is cached so this lookup only happens once.
+	 * Called by <code>implies0</code> on an AdminPermission which was
+	 * constructed with a Bundle. This method loads a dictionary with the
+	 * filter-matchable properties of this bundle. The dictionary is cached so
+	 * this lookup only happens once.
 	 * 
 	 * This method should only be called on an AdminPermission which was
 	 * constructed with a bundle
@@ -823,23 +839,38 @@
 		if (result != null) {
 			return result;
 		}
-		final Dictionary dict = new Hashtable(4);
-		AccessController.doPrivileged(new PrivilegedAction() {
-			public Object run() {
-				dict.put("id", new Long(bundle.getBundleId()));
-				dict.put("location", bundle.getLocation());
-				String name = bundle.getSymbolicName();
-				if (name != null) {
-					dict.put("name", name);
+		/*
+		 * We may have recursed here due to the Bundle.getLocation call in the
+		 * doPrivileged below. If this is the case, return null to allow implies
+		 * to return true.
+		 */
+		final Object mark = recurse.get();
+		if (mark == bundle) {
+			return null;
+		}
+		recurse.set(bundle);
+		try {
+			final Dictionary dict = new Hashtable(4);
+			AccessController.doPrivileged(new PrivilegedAction() {
+				public Object run() {
+					dict.put("id", new Long(bundle.getBundleId()));
+					dict.put("location", bundle.getLocation());
+					String name = bundle.getSymbolicName();
+					if (name != null) {
+						dict.put("name", name);
+					}
+					SignerProperty signer = new SignerProperty(bundle);
+					if (signer.isBundleSigned()) {
+						dict.put("signer", signer);
+					}
+					return null;
 				}
-				SignerProperty signer = new SignerProperty(bundle);
-				if (signer.isBundleSigned()) {
-					dict.put("signer", signer); 
-				}
-				return null;
-			}
-		});
-		return properties = dict;
+			});
+			return properties = dict;
+		}
+		finally {
+			recurse.set(null);
+		}
 	}
 }
 
diff --git a/org.osgi.core/src/main/java/org/osgi/framework/FrameworkUtil.java b/org.osgi.core/src/main/java/org/osgi/framework/FrameworkUtil.java
index 13391ca..b565b86 100644
--- a/org.osgi.core/src/main/java/org/osgi/framework/FrameworkUtil.java
+++ b/org.osgi.core/src/main/java/org/osgi/framework/FrameworkUtil.java
@@ -39,7 +39,7 @@
  * 
  * @since 1.3
  * @ThreadSafe
- * @version $Revision: 6888 $
+ * @version $Revision: 7761 $
  */
 public class FrameworkUtil {
 	/**
@@ -186,7 +186,7 @@
 	 */
 	public static boolean matchDistinguishedNameChain(String matchPattern,
 			List /* <String> */dnChain) {
-		return DNChainMatching.match(matchPattern, new ArrayList(dnChain));
+		return DNChainMatching.match(matchPattern, dnChain);
 	}
 
 	/**
@@ -1704,11 +1704,11 @@
 		/**
 		 * Check the name/value pairs of the rdn against the pattern.
 		 * 
-		 * @param rdn ArrayList of name value pairs for a given RDN.
-		 * @param rdnPattern ArrayList of name value pattern pairs.
+		 * @param rdn List of name value pairs for a given RDN.
+		 * @param rdnPattern List of name value pattern pairs.
 		 * @return true if the list of name value pairs match the pattern.
 		 */
-		private static boolean rdnmatch(ArrayList rdn, ArrayList rdnPattern) {
+		private static boolean rdnmatch(List rdn, List rdnPattern) {
 			if (rdn.size() != rdnPattern.size()) {
 				return false;
 			}
@@ -1732,7 +1732,7 @@
 			return true;
 		}
 
-		private static boolean dnmatch(ArrayList dn, ArrayList dnPattern) {
+		private static boolean dnmatch(List dn, List dnPattern) {
 			int dnStart = 0;
 			int patStart = 0;
 			int patLen = dnPattern.size();
@@ -1750,8 +1750,7 @@
 				if (dn.size() > patLen) {
 					if (!dnPattern.get(0).equals(STAR_WILDCARD)) {
 						// If the number of rdns do not match we must have a
-						// prefix
-						// map
+						// prefix map
 						return false;
 					}
 					// The rdnPattern and rdn must have the same number of
@@ -1760,8 +1759,8 @@
 				}
 			}
 			for (int i = 0; i < patLen; i++) {
-				if (!rdnmatch((ArrayList) dn.get(i + dnStart),
-						(ArrayList) dnPattern.get(i + patStart))) {
+				if (!rdnmatch((List) dn.get(i + dnStart), (List) dnPattern
+						.get(i + patStart))) {
 					return false;
 				}
 			}
@@ -1769,24 +1768,24 @@
 		}
 
 		/**
-		 * Parses a distinguished name chain pattern and returns an ArrayList
-		 * where each element represents a distinguished name (DN) in the chain
-		 * of DNs. Each element will be either a String, if the element
-		 * represents a wildcard ("*" or "-"), or an ArrayList representing an
-		 * RDN. Each element in the RDN ArrayList will be a String, if the
-		 * element represents a wildcard ("*"), or an ArrayList of Strings, each
-		 * String representing a name/value pair in the RDN.
+		 * Parses a distinguished name chain pattern and returns a List where
+		 * each element represents a distinguished name (DN) in the chain of
+		 * DNs. Each element will be either a String, if the element represents
+		 * a wildcard ("*" or "-"), or a List representing an RDN. Each element
+		 * in the RDN List will be a String, if the element represents a
+		 * wildcard ("*"), or a List of Strings, each String representing a
+		 * name/value pair in the RDN.
 		 * 
 		 * @param dnChain
 		 * @return a list of DNs.
 		 * @throws IllegalArgumentException
 		 */
-		private static ArrayList parseDNchainPattern(String dnChain) {
+		private static List parseDNchainPattern(String dnChain) {
 			if (dnChain == null) {
 				throw new IllegalArgumentException(
 						"The DN chain must not be null.");
 			}
-			ArrayList parsed = new ArrayList();
+			List parsed = new ArrayList();
 			int startIndex = 0;
 			startIndex = skipSpaces(dnChain, startIndex);
 			while (startIndex < dnChain.length()) {
@@ -1814,23 +1813,22 @@
 				startIndex = endIndex + 1;
 				startIndex = skipSpaces(dnChain, startIndex);
 			}
-			parseDNchain(parsed);
-			return parsed;
+			return parseDNchain(parsed);
 		}
 
 		private static List parseDNchain(List chain) {
 			if (chain == null) {
 				throw new IllegalArgumentException("DN chain must not be null.");
 			}
-			// Now we parse is a list of strings, lets make ArrayList of rdn out
-			// of
-			// them
+			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);
 				if (dn.equals(STAR_WILDCARD) || dn.equals(MINUS_WILDCARD)) {
 					continue;
 				}
-				ArrayList rdns = new ArrayList();
+				List rdns = new ArrayList();
 				if (dn.charAt(0) == '*') {
 					if (dn.charAt(1) != ',') {
 						throw new IllegalArgumentException(
@@ -1870,13 +1868,13 @@
 		 * rdnArray with the extracted RDNs.
 		 * 
 		 * @param dn the distinguished name in canonical form.
-		 * @param rdnArray the array to fill in with RDNs extracted from the dn
+		 * @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, ArrayList rdnArray) {
+		private static void parseDN(String dn, List rdn) {
 			int startIndex = 0;
 			char c = '\0';
-			ArrayList nameValues = new ArrayList();
+			List nameValues = new ArrayList();
 			while (startIndex < dn.length()) {
 				int endIndex;
 				for (endIndex = startIndex; endIndex < dn.length(); endIndex++) {
@@ -1894,7 +1892,7 @@
 				}
 				nameValues.add(dn.substring(startIndex, endIndex));
 				if (c != '+') {
-					rdnArray.add(nameValues);
+					rdn.add(nameValues);
 					if (endIndex != dn.length()) {
 						nameValues = new ArrayList();
 					}
@@ -1912,7 +1910,7 @@
 
 		/**
 		 * This method will return an 'index' which points to a non-wildcard DN
-		 * or the end-of-arraylist.
+		 * or the end-of-list.
 		 */
 		private static int skipWildCards(List dnChainPattern,
 				int dnChainPatternIndex) {
@@ -1928,22 +1926,19 @@
 					// otherwise continue skipping over wild cards
 				}
 				else {
-					if (dnPattern instanceof ArrayList) {
-						// if its an arraylist then we have our 'non-wildcard'
-						// DN
+					if (dnPattern instanceof List) {
+						// if its a list then we have our 'non-wildcard' DN
 						break;
 					}
 					else {
 						// unknown member of the DNChainPattern
 						throw new IllegalArgumentException(
-								"expected String or Arraylist in DN Pattern");
+								"expected String or List in DN Pattern");
 					}
 				}
 			}
-			// i either points to end-of-arraylist, or to the first
-			// non-wildcard
-			// pattern
-			// after dnChainPatternIndex
+			// i either points to end-of-list, or to the first
+			// non-wildcard pattern after dnChainPatternIndex
 			return i;
 		}
 
@@ -1986,9 +1981,8 @@
 				}
 				//
 				// we will now recursively call to see if the rest of the
-				// DNChainPattern
-				// matches increasingly smaller portions of the rest of the
-				// DNChain
+				// DNChainPattern matches increasingly smaller portions of the
+				// rest of the DNChain
 				//
 				if (dnPattern.equals(STAR_WILDCARD)) {
 					// '*' option: only wildcard on 0 or 1
@@ -2008,13 +2002,12 @@
 				// failure
 			}
 			else {
-				if (dnPattern instanceof ArrayList) {
+				if (dnPattern instanceof List) {
 					// here we have to do a deeper check for each DN in the
-					// pattern
-					// until we hit a wild card
+					// pattern until we hit a wild card
 					do {
-						if (!dnmatch((ArrayList) dnChain.get(dnChainIndex),
-								(ArrayList) dnPattern)) {
+						if (!dnmatch((List) dnChain.get(dnChainIndex),
+								(List) dnPattern)) {
 							return false;
 						}
 						// go to the next set of DN's in both chains
@@ -2027,24 +2020,18 @@
 							return true;
 						}
 						// if the DN Chain is finished, but the pattern isn't
-						// finished
-						// then if the rest of the pattern is not wildcard then
-						// we
-						// are
-						// done
+						// finished then if the rest of the pattern is not
+						// wildcard then we are done
 						if (dnChainIndex >= dnChain.size()) {
 							dnChainPatternIndex = skipWildCards(dnChainPattern,
 									dnChainPatternIndex);
 							// return TRUE iff the pattern index moved past the
-							// array-size
-							// (implying that the rest of the pattern is all
-							// wildcards)
+							// list-size (implying that the rest of the pattern
+							// is all wildcards)
 							return dnChainPatternIndex >= dnChainPattern.size();
 						}
 						// if the pattern finished, but the chain continues then
-						// we
-						// have
-						// a mis-match
+						// we have a mis-match
 						if (dnChainPatternIndex >= dnChainPattern.size()) {
 							return false;
 						}
@@ -2062,23 +2049,20 @@
 									dnChainPattern, dnChainPatternIndex);
 						}
 						else {
-							if (!(dnPattern instanceof ArrayList)) {
+							if (!(dnPattern instanceof List)) {
 								throw new IllegalArgumentException(
-										"expected String or Arraylist in DN Pattern");
+										"expected String or List in DN Pattern");
 							}
 						}
 						// if we are here, then we will just continue to the
-						// match
-						// the
-						// next set of DN's from the DNChain, and the
-						// DNChainPattern
-						// since both are array-lists
+						// match the next set of DN's from the DNChain, and the
+						// DNChainPattern since both are lists
 					} while (true);
 					// should never reach here?
 				}
 				else {
 					throw new IllegalArgumentException(
-							"expected String or Arraylist in DN Pattern");
+							"expected String or List in DN Pattern");
 				}
 			}
 			// if we get here, the the default return is 'mis-match'
@@ -2124,16 +2108,20 @@
 			try {
 				parsedDNChain = parseDNchain(dnChain);
 			}
-			catch (IllegalArgumentException e) {
-				throw (IllegalArgumentException) new IllegalArgumentException(
-						"Invalid DN chain: " + toString(dnChain)).initCause(e);
+			catch (RuntimeException e) {
+				IllegalArgumentException iae = new IllegalArgumentException(
+						"Invalid DN chain: " + toString(dnChain));
+				iae.initCause(e);
+				throw iae;
 			}
 			try {
 				parsedDNPattern = parseDNchainPattern(pattern);
 			}
-			catch (IllegalArgumentException e) {
-				throw (IllegalArgumentException) new IllegalArgumentException(
-						"Invalid match pattern: " + pattern).initCause(e);
+			catch (RuntimeException e) {
+				IllegalArgumentException iae = new IllegalArgumentException(
+						"Invalid match pattern: " + pattern);
+				iae.initCause(e);
+				throw iae;
 			}
 			return dnChainMatch(parsedDNChain, 0, parsedDNPattern, 0);
 		}
diff --git a/org.osgi.core/src/main/java/org/osgi/framework/PackagePermission.java b/org.osgi.core/src/main/java/org/osgi/framework/PackagePermission.java
index fc319e8..da2f540 100644
--- a/org.osgi.core/src/main/java/org/osgi/framework/PackagePermission.java
+++ b/org.osgi.core/src/main/java/org/osgi/framework/PackagePermission.java
@@ -56,7 +56,7 @@
  * which is deprecated, implies the <code>import</code> action.
  * 
  * @ThreadSafe
- * @version $Revision: 6530 $
+ * @version $Revision: 7189 $
  */
 
 public final class PackagePermission extends BasicPermission {
@@ -165,9 +165,9 @@
 	 *        only be specified if the specified action is <code>import</code>.
 	 * @param actions <code>exportonly</code>,<code>import</code> (canonical
 	 *        order).
-	 * @throw 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.
+	 * @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.
 	 */
 	public PackagePermission(String name, String actions) {
 		this(name, parseActions(actions));
@@ -188,8 +188,8 @@
 	 * @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>.
-	 * @throw IllegalArgumentException If the specified action is not
-	 *        <code>import</code> or the name is a filter expression.
+	 * @throws IllegalArgumentException If the specified action is not
+	 *         <code>import</code> or the name is a filter expression.
 	 * @since 1.5
 	 */
 	public PackagePermission(String name, Bundle exportingBundle, String actions) {
diff --git a/org.osgi.core/src/main/java/org/osgi/framework/ServicePermission.java b/org.osgi.core/src/main/java/org/osgi/framework/ServicePermission.java
index d1fb70f..d2f3c31 100644
--- a/org.osgi.core/src/main/java/org/osgi/framework/ServicePermission.java
+++ b/org.osgi.core/src/main/java/org/osgi/framework/ServicePermission.java
@@ -51,7 +51,7 @@
  * <code>ServicePermission</code> to get the specific service.
  * 
  * @ThreadSafe
- * @version $Revision: 6530 $
+ * @version $Revision: 7189 $
  */
 
 public final class ServicePermission extends BasicPermission {
@@ -166,9 +166,9 @@
 	 * 
 	 * @param name The service class name
 	 * @param actions <code>get</code>,<code>register</code> (canonical order)
-	 * @throw IllegalArgumentException If the specified name is a filter
-	 *        expression and either the specified action is not <code>get</code>
-	 *        or the filter has an invalid syntax.
+	 * @throws IllegalArgumentException If the specified name is a filter
+	 *         expression and either the specified action is not
+	 *         <code>get</code> or the filter has an invalid syntax.
 	 */
 	public ServicePermission(String name, String actions) {
 		this(name, parseActions(actions));
@@ -188,8 +188,8 @@
 	 * 
 	 * @param reference The requested service.
 	 * @param actions The action <code>get</code>.
-	 * @throw IllegalArgumentException If the specified action is not
-	 *        <code>get</code> or reference is <code>null</code>.
+	 * @throws IllegalArgumentException If the specified action is not
+	 *         <code>get</code> or reference is <code>null</code>.
 	 * @since 1.5
 	 */
 	public ServicePermission(ServiceReference reference, String actions) {
diff --git a/org.osgi.core/src/main/java/org/osgi/framework/hooks/service/EventHook.java b/org.osgi.core/src/main/java/org/osgi/framework/hooks/service/EventHook.java
index fe21fba..1249493 100644
--- a/org.osgi.core/src/main/java/org/osgi/framework/hooks/service/EventHook.java
+++ b/org.osgi.core/src/main/java/org/osgi/framework/hooks/service/EventHook.java
@@ -28,7 +28,7 @@
  * (register, modify, and unregister service) operations.
  * 
  * @ThreadSafe
- * @version $Revision: 6860 $
+ * @version $Revision: 6967 $
  */
 
 public interface EventHook {
@@ -50,5 +50,5 @@
 	 *        synchronized.
 	 */
 	void event(ServiceEvent event,
-			Collection/* <? extends BundleContext> */contexts);
+			Collection/* <BundleContext> */contexts);
 }
diff --git a/org.osgi.core/src/main/java/org/osgi/framework/hooks/service/FindHook.java b/org.osgi.core/src/main/java/org/osgi/framework/hooks/service/FindHook.java
index 02044f3..0de1f0b 100644
--- a/org.osgi.core/src/main/java/org/osgi/framework/hooks/service/FindHook.java
+++ b/org.osgi.core/src/main/java/org/osgi/framework/hooks/service/FindHook.java
@@ -28,7 +28,7 @@
  * (get service references) operations.
  * 
  * @ThreadSafe
- * @version $Revision: 6860 $
+ * @version $Revision: 6967 $
  */
 
 public interface FindHook {
@@ -59,5 +59,5 @@
 	 */
 	void find(BundleContext context, String name, String filter,
 			boolean allServices,
-			Collection/* <? extends ServiceReference> */references);
+			Collection/* <ServiceReference> */references);
 }
diff --git a/org.osgi.core/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java b/org.osgi.core/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java
index 7ee855b..5934c0c 100644
--- a/org.osgi.core/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java
+++ b/org.osgi.core/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java
@@ -28,7 +28,7 @@
  * addition and removal.
  * 
  * @ThreadSafe
- * @version $Revision: 6906 $
+ * @version $Revision: 6967 $
  */
 
 public interface ListenerHook {
@@ -46,7 +46,7 @@
 	 *        result in an <code>UnsupportedOperationException</code>. The
 	 *        collection is not synchronized.
 	 */
-	void added(Collection/* <? extends ListenerInfo> */listeners);
+	void added(Collection/* <ListenerInfo> */listeners);
 
 	/**
 	 * Removed listeners hook method. This method is called to provide the hook
@@ -60,7 +60,7 @@
 	 *        will result in an <code>UnsupportedOperationException</code>. The
 	 *        collection is not synchronized.
 	 */
-	void removed(Collection/* <? extends ListenerInfo> */listeners);
+	void removed(Collection/* <ListenerInfo> */listeners);
 
 	/**
 	 * Information about a Service Listener. This interface describes the bundle