You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2012/05/11 22:19:07 UTC
svn commit: r1337360 [3/7] - in /felix/trunk/framework: ./
src/main/java/org/apache/felix/framework/
src/main/java/org/apache/felix/framework/resolver/
src/main/java/org/apache/felix/framework/wiring/
src/main/java/org/osgi/framework/ src/main/java/org...
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=1337360&r1=1337359&r2=1337360&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 Fri May 11 20:19:02 2012
@@ -1,6 +1,6 @@
/*
- * Copyright (c) OSGi Alliance (2005, 2010). All Rights Reserved.
- *
+ * Copyright (c) OSGi Alliance (2005, 2012). All Rights Reserved.
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -14,201 +14,1658 @@
* limitations under the License.
*/
-package org.osgi.framework;
+package org.osgi.framework;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+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;
+
+/**
+ * Framework Utility class.
+ *
+ * <p>
+ * This class contains utility methods which access Framework functions that may
+ * be useful to bundles.
+ *
+ * @since 1.3
+ * @ThreadSafe
+ * @version $Id: 1f46ea2bbbe2a1242fdaf0877709fb9c02eefae1 $
+ */
+public class FrameworkUtil {
+ /**
+ * FrameworkUtil objects may not be constructed.
+ */
+ private FrameworkUtil() {
+ // private empty constructor to prevent construction
+ }
+
+ /**
+ * 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
+ * thrown with a human readable message where the filter became unparsable.
+ *
+ * <p>
+ * This method returns a Filter implementation which may not perform as well
+ * as the framework implementation-specific Filter implementation returned
+ * by {@link BundleContext#createFilter(String)}.
+ *
+ * @param filter The filter string.
+ * @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} is null.
+ *
+ * @see Filter
+ */
+ public static Filter createFilter(String filter) throws InvalidSyntaxException {
+ return FilterImpl.newInstance(filter);
+ }
+
+ /**
+ * Match a Distinguished Name (DN) chain against a pattern. DNs can be
+ * matched using wildcards. A wildcard ({@code '*'} \u002A) replaces all
+ * possible values. Due to the structure of the DN, the comparison is more
+ * complicated than string-based wildcard matching.
+ * <p>
+ * A wildcard can stand for zero or more DNs in a chain, a number of
+ * relative distinguished names (RDNs) within a DN, or the value of a single
+ * RDN. The DNs in the chain and the matching pattern are canonicalized
+ * before processing. This means, among other things, that spaces must be
+ * ignored, except in values.
+ * <p>
+ * The format of a wildcard match pattern is:
+ *
+ * <pre>
+ * matchPattern ::= dn-match ( ';' dn-match ) *
+ * dn-match ::= ( '*' | rdn-match ) ( ',' rdn-match ) * | '-'
+ * rdn-match ::= name '=' value-match
+ * value-match ::= '*' | value-star
+ * value-star ::= < value, requires escaped '*' and '-' >
+ * </pre>
+ * <p>
+ * The most simple case is a single wildcard; it must match any DN. A
+ * 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 DNs that
+ * end with RDNs of o=ACME and c=US would look like this:
+ *
+ * <pre>
+ * *, o=ACME, c=US
+ * </pre>
+ *
+ * This match pattern would match the following DNs:
+ *
+ * <pre>
+ * cn = Bugs Bunny, o = ACME, c = US
+ * ou = Carrots, cn=Daffy Duck, o=ACME, c=US
+ * street = 9C\, Avenue St. Drézéry, o=ACME, c=US
+ * dc=www, dc=acme, dc=com, o=ACME, c=US
+ * o=ACME, c=US
+ * </pre>
+ *
+ * The following DNs would not match:
+ *
+ * <pre>
+ * street = 9C\, Avenue St. Drézéry, o=ACME, c=FR
+ * dc=www, dc=acme, dc=com, c=US
+ * </pre>
+ *
+ * If a wildcard is used for a value of an RDN, the value must be exactly *.
+ * The wildcard must match any value, and no substring matching must be
+ * done. For example:
+ *
+ * <pre>
+ * cn=*,o=ACME,c=*
+ * </pre>
+ *
+ * This match pattern with wildcard must match the following DNs:
+ *
+ * <pre>
+ * cn=Bugs Bunny,o=ACME,c=US
+ * cn = Daffy Duck , o = ACME , c = US
+ * cn=Road Runner, o=ACME, c=NL
+ * </pre>
+ *
+ * But not:
+ *
+ * <pre>
+ * o=ACME, c=NL
+ * dc=acme.com, cn=Bugs Bunny, o=ACME, c=US
+ * </pre>
+ *
+ * <p>
+ * A match pattern may contain a chain of DN match patterns. The semicolon(
+ * {@code ';'} \u003B) must be used to separate DN match patterns in a
+ * chain. Wildcards can also be used to match against a complete DN within a
+ * chain.
+ * <p>
+ * The following example matches a certificate signed by Tweety Inc. in the
+ * US.
+ * </p>
+ *
+ * <pre>
+ * * ; ou=S & V, o=Tweety Inc., c=US
+ * </pre>
+ * <p>
+ * The wildcard ('*') matches zero or one DN in the chain, however,
+ * sometimes it is necessary to match a longer chain. The minus sign (
+ * {@code '-'} \u002D) represents zero or more DNs, whereas the asterisk
+ * only represents a single DN. For example, to match a DN where the Tweety
+ * Inc. is in the DN chain, use the following expression:
+ * </p>
+ *
+ * <pre>
+ * - ; *, o=Tweety Inc., c=US
+ * </pre>
+ *
+ * @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} 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) {
+ return DNChainMatching.match(matchPattern, dnChain);
+ }
+
+ /**
+ * 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} 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) {
+ // We use doPriv since the caller may not have permission
+ // to call getClassLoader.
+ Object cl = AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ return classFromBundle.getClassLoader();
+ }
+ });
+
+ if (cl instanceof BundleReference) {
+ return ((BundleReference) cl).getBundle();
+ }
+ return null;
+ }
+
+ /**
+ * RFC 1960-based Filter. Filter objects can be created by calling the
+ * constructor with the desired filter string. A Filter object can be called
+ * numerous times to determine if the match argument matches the filter
+ * string that was used to create the Filter object.
+ *
+ * <p>
+ * The syntax of a filter string is the string representation of LDAP search
+ * filters as defined in RFC 1960: <i>A String Representation of LDAP Search
+ * Filters</i> (available at http://www.ietf.org/rfc/rfc1960.txt). It should
+ * be noted that RFC 2254: <i>A String Representation of LDAP Search
+ * Filters</i> (available at http://www.ietf.org/rfc/rfc2254.txt) supersedes
+ * RFC 1960 but only adds extensible matching and is not applicable for this
+ * API.
+ *
+ * <p>
+ * The string representation of an LDAP search filter is defined by the
+ * following grammar. It uses a prefix format.
+ *
+ * <pre>
+ * <filter> ::= '(' <filtercomp> ')'
+ * <filtercomp> ::= <and> | <or> | <not> | <item>
+ * <and> ::= '&' <filterlist>
+ * <or> ::= '|' <filterlist>
+ * <not> ::= '!' <filter>
+ * <filterlist> ::= <filter> | <filter> <filterlist>
+ * <item> ::= <simple> | <present> | <substring>
+ * <simple> ::= <attr> <filtertype> <value>
+ * <filtertype> ::= <equal> | <approx> | <greater> | <less>
+ * <equal> ::= '='
+ * <approx> ::= '˜='
+ * <greater> ::= '>='
+ * <less> ::= '<='
+ * <present> ::= <attr> '=*'
+ * <substring> ::= <attr> '=' <initial> <any> <final>
+ * <initial> ::= NULL | <value>
+ * <any> ::= '*' <starval>
+ * <starval> ::= NULL | <value> '*' <starval>
+ * <final> ::= NULL | <value>
+ * </pre>
+ *
+ * {@code <attr>} is a string representing an attribute, or key, in
+ * the properties objects of the registered services. Attribute names are
+ * not case sensitive; that is cn and CN both refer to the same attribute.
+ * {@code <value>} is a string representing the value, or part of one,
+ * of a key in the properties objects of the registered services. If a
+ * {@code <value>} must contain one of the characters ' {@code *}' or
+ * '{@code (}' or '{@code )}', these characters should be escaped by
+ * preceding them with the backslash '{@code \}' character. Note that
+ * although both the {@code <substring>} and {@code <present>}
+ * productions can produce the {@code 'attr=*'} construct, this construct is
+ * used only to denote a presence filter.
+ *
+ * <p>
+ * Examples of LDAP filters are:
+ *
+ * <pre>
+ * "(cn=Babs Jensen)"
+ * "(!(cn=Tim Howes))"
+ * "(&(" + Constants.OBJECTCLASS + "=Person)(|(sn=Jensen)(cn=Babs J*)))"
+ * "(o=univ*of*mich*)"
+ * </pre>
+ *
+ * <p>
+ * The approximate match ({@code ~=}) is implementation specific but should
+ * at least ignore case and white space differences. Optional are codes like
+ * soundex or other smart "closeness" comparisons.
+ *
+ * <p>
+ * Comparison of values is not straightforward. Strings are compared
+ * differently than numbers and it is possible for a key to have multiple
+ * values. Note that that keys in the match argument must always be strings.
+ * The comparison is defined by the object type of the key's value. The
+ * following rules apply for comparison:
+ *
+ * <blockquote>
+ * <TABLE BORDER=0>
+ * <TR>
+ * <TD><b>Property Value Type </b></TD>
+ * <TD><b>Comparison Type</b></TD>
+ * </TR>
+ * <TR>
+ * <TD>String</TD>
+ * <TD>String comparison</TD>
+ * </TR>
+ * <TR valign=top>
+ * <TD>Integer, Long, Float, Double, Byte, Short, BigInteger, BigDecimal</TD>
+ * <TD>numerical comparison</TD>
+ * </TR>
+ * <TR>
+ * <TD>Character</TD>
+ * <TD>character comparison</TD>
+ * </TR>
+ * <TR>
+ * <TD>Boolean</TD>
+ * <TD>equality comparisons only</TD>
+ * </TR>
+ * <TR>
+ * <TD>[] (array)</TD>
+ * <TD>recursively applied to values</TD>
+ * </TR>
+ * <TR>
+ * <TD>Collection</TD>
+ * <TD>recursively applied to values</TD>
+ * </TR>
+ * </TABLE>
+ * Note: arrays of primitives are also supported. </blockquote>
+ *
+ * A filter matches a key that has multiple values if it matches at least
+ * one of those values. For example,
+ *
+ * <pre>
+ * Dictionary d = new Hashtable();
+ * d.put("cn", new String[] {"a", "b", "c"});
+ * </pre>
+ *
+ * d will match {@code (cn=a)} and also {@code (cn=b)}
+ *
+ * <p>
+ * A filter component that references a key having an unrecognizable data
+ * type will evaluate to {@code false} .
+ */
+ static private final class FilterImpl implements Filter {
+ /* filter operators */
+ private static final int EQUAL = 1;
+ private static final int APPROX = 2;
+ private static final int GREATER = 3;
+ private static final int LESS = 4;
+ private static final int PRESENT = 5;
+ private static final int SUBSTRING = 6;
+ private static final int AND = 7;
+ private static final int OR = 8;
+ private static final int NOT = 9;
+
+ /** filter operation */
+ private final int op;
+ /** filter attribute or null if operation AND, OR or NOT */
+ private final String attr;
+ /** filter operands */
+ private final Object value;
+
+ /* normalized filter string for Filter object */
+ private transient String filterString;
+
+ /**
+ * Constructs a {@link FilterImpl} object. This filter object may be
+ * used to match a {@link ServiceReference} or a Dictionary.
+ *
+ * <p>
+ * If the filter cannot be parsed, an {@link InvalidSyntaxException}
+ * will be thrown with a human readable message where the filter became
+ * unparsable.
+ *
+ * @param filterString the filter string.
+ * @throws InvalidSyntaxException If the filter parameter contains an
+ * invalid filter string that cannot be parsed.
+ */
+ static FilterImpl newInstance(String filterString) throws InvalidSyntaxException {
+ return new Parser(filterString).parse();
+ }
+
+ FilterImpl(int operation, String attr, Object value) {
+ this.op = operation;
+ this.attr = attr;
+ this.value = value;
+ filterString = null;
+ }
+
+ /**
+ * Filter using a service's properties.
+ * <p>
+ * This {@code Filter} is executed using the keys and values of the
+ * referenced service's properties. The keys are looked up in a case
+ * insensitive manner.
+ *
+ * @param reference The reference to the service whose properties are
+ * used in the match.
+ * @return {@code true} if the service's properties match this
+ * {@code Filter}; {@code false} otherwise.
+ */
+ public boolean match(ServiceReference<?> reference) {
+ return matches(new ServiceReferenceMap(reference));
+ }
+
+ /**
+ * Filter using a {@code Dictionary} with case insensitive key lookup.
+ * This {@code Filter} is executed using the specified
+ * {@code Dictionary}'s keys and values. The keys are looked up in a
+ * case insensitive manner.
+ *
+ * @param dictionary The {@code Dictionary} whose key/value pairs are
+ * used in the match.
+ * @return {@code true} if the {@code Dictionary}'s values match this
+ * filter; {@code false} otherwise.
+ * @throws IllegalArgumentException If {@code dictionary} contains case
+ * variants of the same key name.
+ */
+ public boolean match(Dictionary<String, ?> dictionary) {
+ return matches(new CaseInsensitiveMap(dictionary));
+ }
+
+ /**
+ * Filter using a {@code Dictionary}. This {@code Filter} is executed
+ * using the specified {@code Dictionary}'s keys and values. The keys
+ * are looked up in a normal manner respecting case.
+ *
+ * @param dictionary The {@code Dictionary} whose key/value pairs are
+ * used in the match.
+ * @return {@code true} if the {@code Dictionary}'s values match this
+ * filter; {@code false} otherwise.
+ * @since 1.3
+ */
+ public boolean matchCase(Dictionary<String, ?> dictionary) {
+ switch (op) {
+ case AND : {
+ FilterImpl[] filters = (FilterImpl[]) value;
+ for (FilterImpl f : filters) {
+ if (!f.matchCase(dictionary)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ case OR : {
+ FilterImpl[] filters = (FilterImpl[]) value;
+ for (FilterImpl f : filters) {
+ if (f.matchCase(dictionary)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ case NOT : {
+ FilterImpl filter = (FilterImpl) value;
+ return !filter.matchCase(dictionary);
+ }
+
+ case SUBSTRING :
+ case EQUAL :
+ case GREATER :
+ case LESS :
+ case APPROX : {
+ Object prop = (dictionary == null) ? null : dictionary.get(attr);
+ return compare(op, prop, value);
+ }
+
+ case PRESENT : {
+ Object prop = (dictionary == null) ? null : dictionary.get(attr);
+ return prop != null;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Filter using a {@code Map}. This {@code Filter} is executed using the
+ * specified {@code Map}'s keys and values. The keys are looked up in a
+ * normal manner respecting case.
+ *
+ * @param map The {@code Map} whose key/value pairs are used in the
+ * match. Maps with {@code null} key or values are not supported.
+ * A {@code null} value is considered not present to the filter.
+ * @return {@code true} if the {@code Map}'s values match this filter;
+ * {@code false} otherwise.
+ * @since 1.6
+ */
+ public boolean matches(Map<String, ?> map) {
+ switch (op) {
+ case AND : {
+ FilterImpl[] filters = (FilterImpl[]) value;
+ for (FilterImpl f : filters) {
+ if (!f.matches(map)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ case OR : {
+ FilterImpl[] filters = (FilterImpl[]) value;
+ for (FilterImpl f : filters) {
+ if (f.matches(map)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ case NOT : {
+ FilterImpl filter = (FilterImpl) value;
+ return !filter.matches(map);
+ }
+
+ case SUBSTRING :
+ case EQUAL :
+ case GREATER :
+ case LESS :
+ case APPROX : {
+ Object prop = (map == null) ? null : map.get(attr);
+ return compare(op, prop, value);
+ }
+
+ case PRESENT : {
+ Object prop = (map == null) ? null : map.get(attr);
+ return prop != null;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns this {@code Filter}'s filter string.
+ * <p>
+ * The filter string is normalized by removing whitespace which does not
+ * affect the meaning of the filter.
+ *
+ * @return This {@code Filter}'s filter string.
+ */
+ public String toString() {
+ String result = filterString;
+ if (result == null) {
+ filterString = result = normalize().toString();
+ }
+ return result;
+ }
+
+ /**
+ * Returns this {@code Filter}'s normalized filter string.
+ * <p>
+ * The filter string is normalized by removing whitespace which does not
+ * affect the meaning of the filter.
+ *
+ * @return This {@code Filter}'s filter string.
+ */
+ private StringBuffer normalize() {
+ StringBuffer sb = new StringBuffer();
+ sb.append('(');
+
+ switch (op) {
+ case AND : {
+ sb.append('&');
+
+ FilterImpl[] filters = (FilterImpl[]) value;
+ for (FilterImpl f : filters) {
+ sb.append(f.normalize());
+ }
+
+ break;
+ }
+
+ case OR : {
+ sb.append('|');
+
+ FilterImpl[] filters = (FilterImpl[]) value;
+ for (FilterImpl f : filters) {
+ sb.append(f.normalize());
+ }
+
+ break;
+ }
+
+ case NOT : {
+ sb.append('!');
+ FilterImpl filter = (FilterImpl) value;
+ sb.append(filter.normalize());
+
+ break;
+ }
+
+ case SUBSTRING : {
+ sb.append(attr);
+ sb.append('=');
+
+ String[] substrings = (String[]) value;
+
+ for (String substr : substrings) {
+ if (substr == null) /* * */{
+ sb.append('*');
+ } else /* xxx */{
+ sb.append(encodeValue(substr));
+ }
+ }
+
+ break;
+ }
+ case EQUAL : {
+ sb.append(attr);
+ sb.append('=');
+ sb.append(encodeValue((String) value));
+
+ break;
+ }
+ case GREATER : {
+ sb.append(attr);
+ sb.append(">=");
+ sb.append(encodeValue((String) value));
+
+ break;
+ }
+ case LESS : {
+ sb.append(attr);
+ sb.append("<=");
+ sb.append(encodeValue((String) value));
+
+ break;
+ }
+ case APPROX : {
+ sb.append(attr);
+ sb.append("~=");
+ sb.append(encodeValue(approxString((String) value)));
+
+ break;
+ }
+
+ case PRESENT : {
+ sb.append(attr);
+ sb.append("=*");
+
+ break;
+ }
+ }
+
+ sb.append(')');
+
+ return sb;
+ }
+
+ /**
+ * Compares this {@code Filter} to another {@code Filter}.
+ *
+ * <p>
+ * This implementation returns the result of calling
+ * {@code this.toString().equals(obj.toString()}.
+ *
+ * @param obj The object to compare against this {@code Filter}.
+ * @return If the other object is a {@code Filter} object, then returns
+ * the result of calling
+ * {@code this.toString().equals(obj.toString()}; {@code false}
+ * otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (!(obj instanceof Filter)) {
+ return false;
+ }
+
+ return this.toString().equals(obj.toString());
+ }
+
+ /**
+ * Returns the hashCode for this {@code Filter}.
+ *
+ * <p>
+ * This implementation returns the result of calling
+ * {@code this.toString().hashCode()}.
+ *
+ * @return The hashCode of this {@code Filter}.
+ */
+ public int hashCode() {
+ return this.toString().hashCode();
+ }
+
+ /**
+ * Encode the value string such that '(', '*', ')' and '\' are escaped.
+ *
+ * @param value unencoded value string.
+ * @return encoded value string.
+ */
+ private static String encodeValue(String value) {
+ boolean encoded = false;
+ int inlen = value.length();
+ int outlen = inlen << 1; /* inlen 2 */
+
+ char[] output = new char[outlen];
+ value.getChars(0, inlen, output, inlen);
+
+ int cursor = 0;
+ for (int i = inlen; i < outlen; i++) {
+ char c = output[i];
+
+ switch (c) {
+ case '(' :
+ case '*' :
+ case ')' :
+ case '\\' : {
+ output[cursor] = '\\';
+ cursor++;
+ encoded = true;
+
+ break;
+ }
+ }
+
+ output[cursor] = c;
+ cursor++;
+ }
+
+ return encoded ? new String(output, 0, cursor) : value;
+ }
+
+ private boolean compare(int operation, Object value1, Object value2) {
+ if (value1 == null) {
+ return false;
+ }
+ if (value1 instanceof String) {
+ return compare_String(operation, (String) value1, value2);
+ }
+
+ Class<?> clazz = value1.getClass();
+ if (clazz.isArray()) {
+ Class<?> type = clazz.getComponentType();
+ if (type.isPrimitive()) {
+ return compare_PrimitiveArray(operation, type, value1, value2);
+ }
+ return compare_ObjectArray(operation, (Object[]) value1, value2);
+ }
+ if (value1 instanceof Collection<?>) {
+ return compare_Collection(operation, (Collection<?>) value1, value2);
+ }
+ if (value1 instanceof Integer) {
+ return compare_Integer(operation, ((Integer) value1).intValue(), value2);
+ }
+ if (value1 instanceof Long) {
+ return compare_Long(operation, ((Long) value1).longValue(), value2);
+ }
+ if (value1 instanceof Byte) {
+ return compare_Byte(operation, ((Byte) value1).byteValue(), value2);
+ }
+ if (value1 instanceof Short) {
+ return compare_Short(operation, ((Short) value1).shortValue(), value2);
+ }
+ if (value1 instanceof Character) {
+ return compare_Character(operation, ((Character) value1).charValue(), value2);
+ }
+ if (value1 instanceof Float) {
+ return compare_Float(operation, ((Float) value1).floatValue(), value2);
+ }
+ if (value1 instanceof Double) {
+ return compare_Double(operation, ((Double) value1).doubleValue(), value2);
+ }
+ if (value1 instanceof Boolean) {
+ return compare_Boolean(operation, ((Boolean) value1).booleanValue(), value2);
+ }
+ if (value1 instanceof Comparable<?>) {
+ Comparable<Object> comparable = (Comparable<Object>) value1;
+ return compare_Comparable(operation, comparable, value2);
+ }
+ return compare_Unknown(operation, value1, value2);
+ }
+
+ private boolean compare_Collection(int operation, Collection<?> collection, Object value2) {
+ for (Object value1 : collection) {
+ if (compare(operation, value1, value2)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean compare_ObjectArray(int operation, Object[] array, Object value2) {
+ for (Object value1 : array) {
+ if (compare(operation, value1, value2)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean compare_PrimitiveArray(int operation, Class<?> type, Object primarray, Object value2) {
+ if (Integer.TYPE.isAssignableFrom(type)) {
+ int[] array = (int[]) primarray;
+ for (int value1 : array) {
+ if (compare_Integer(operation, value1, value2)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ if (Long.TYPE.isAssignableFrom(type)) {
+ long[] array = (long[]) primarray;
+ for (long value1 : array) {
+ if (compare_Long(operation, value1, value2)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ if (Byte.TYPE.isAssignableFrom(type)) {
+ byte[] array = (byte[]) primarray;
+ for (byte value1 : array) {
+ if (compare_Byte(operation, value1, value2)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ if (Short.TYPE.isAssignableFrom(type)) {
+ short[] array = (short[]) primarray;
+ for (short value1 : array) {
+ if (compare_Short(operation, value1, value2)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ if (Character.TYPE.isAssignableFrom(type)) {
+ char[] array = (char[]) primarray;
+ for (char value1 : array) {
+ if (compare_Character(operation, value1, value2)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ if (Float.TYPE.isAssignableFrom(type)) {
+ float[] array = (float[]) primarray;
+ for (float value1 : array) {
+ if (compare_Float(operation, value1, value2)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ if (Double.TYPE.isAssignableFrom(type)) {
+ double[] array = (double[]) primarray;
+ for (double value1 : array) {
+ if (compare_Double(operation, value1, value2)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ if (Boolean.TYPE.isAssignableFrom(type)) {
+ boolean[] array = (boolean[]) primarray;
+ for (boolean value1 : array) {
+ if (compare_Boolean(operation, value1, value2)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return false;
+ }
+
+ private boolean compare_String(int operation, String string, Object value2) {
+ switch (operation) {
+ case SUBSTRING : {
+ String[] substrings = (String[]) value2;
+ int pos = 0;
+ for (int i = 0, size = substrings.length; i < size; i++) {
+ String substr = substrings[i];
+
+ if (i + 1 < size) /* if this is not that last substr */{
+ if (substr == null) /* * */{
+ String substr2 = substrings[i + 1];
+
+ if (substr2 == null) /* ** */
+ continue; /* ignore first star */
+ /* xxx */
+ int index = string.indexOf(substr2, pos);
+ if (index == -1) {
+ return false;
+ }
+
+ pos = index + substr2.length();
+ if (i + 2 < size) // if there are more
+ // substrings, increment
+ // over the string we just
+ // matched; otherwise need
+ // to do the last substr
+ // check
+ i++;
+ } else /* xxx */{
+ int len = substr.length();
+ if (string.regionMatches(pos, substr, 0, len)) {
+ pos += len;
+ } else {
+ return false;
+ }
+ }
+ } else /* last substr */{
+ if (substr == null) /* * */{
+ return true;
+ }
+ /* xxx */
+ return string.endsWith(substr);
+ }
+ }
+
+ return true;
+ }
+ case EQUAL : {
+ return string.equals(value2);
+ }
+ case APPROX : {
+ string = approxString(string);
+ String string2 = approxString((String) value2);
+
+ return string.equalsIgnoreCase(string2);
+ }
+ case GREATER : {
+ return string.compareTo((String) value2) >= 0;
+ }
+ case LESS : {
+ return string.compareTo((String) value2) <= 0;
+ }
+ }
+ return false;
+ }
+
+ private boolean compare_Integer(int operation, int intval, Object value2) {
+ if (operation == SUBSTRING) {
+ return false;
+ }
+ int intval2;
+ try {
+ intval2 = Integer.parseInt(((String) value2).trim());
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ switch (operation) {
+ case APPROX :
+ case EQUAL : {
+ return intval == intval2;
+ }
+ case GREATER : {
+ return intval >= intval2;
+ }
+ case LESS : {
+ return intval <= intval2;
+ }
+ }
+ return false;
+ }
+
+ private boolean compare_Long(int operation, long longval, Object value2) {
+ if (operation == SUBSTRING) {
+ return false;
+ }
+ long longval2;
+ try {
+ longval2 = Long.parseLong(((String) value2).trim());
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+
+ switch (operation) {
+ case APPROX :
+ case EQUAL : {
+ return longval == longval2;
+ }
+ case GREATER : {
+ return longval >= longval2;
+ }
+ case LESS : {
+ return longval <= longval2;
+ }
+ }
+ return false;
+ }
+
+ private boolean compare_Byte(int operation, byte byteval, Object value2) {
+ if (operation == SUBSTRING) {
+ return false;
+ }
+ byte byteval2;
+ try {
+ byteval2 = Byte.parseByte(((String) value2).trim());
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+
+ switch (operation) {
+ case APPROX :
+ case EQUAL : {
+ return byteval == byteval2;
+ }
+ case GREATER : {
+ return byteval >= byteval2;
+ }
+ case LESS : {
+ return byteval <= byteval2;
+ }
+ }
+ return false;
+ }
+
+ private boolean compare_Short(int operation, short shortval, Object value2) {
+ if (operation == SUBSTRING) {
+ return false;
+ }
+ short shortval2;
+ try {
+ shortval2 = Short.parseShort(((String) value2).trim());
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+
+ switch (operation) {
+ case APPROX :
+ case EQUAL : {
+ return shortval == shortval2;
+ }
+ case GREATER : {
+ return shortval >= shortval2;
+ }
+ case LESS : {
+ return shortval <= shortval2;
+ }
+ }
+ return false;
+ }
+
+ private boolean compare_Character(int operation, char charval, Object value2) {
+ if (operation == SUBSTRING) {
+ return false;
+ }
+ char charval2;
+ try {
+ charval2 = ((String) value2).charAt(0);
+ } catch (IndexOutOfBoundsException e) {
+ return false;
+ }
+
+ switch (operation) {
+ case EQUAL : {
+ return charval == charval2;
+ }
+ case APPROX : {
+ return (charval == charval2) || (Character.toUpperCase(charval) == Character.toUpperCase(charval2)) || (Character.toLowerCase(charval) == Character.toLowerCase(charval2));
+ }
+ case GREATER : {
+ return charval >= charval2;
+ }
+ case LESS : {
+ return charval <= charval2;
+ }
+ }
+ return false;
+ }
+
+ private boolean compare_Boolean(int operation, boolean boolval, Object value2) {
+ if (operation == SUBSTRING) {
+ return false;
+ }
+ boolean boolval2 = Boolean.valueOf(((String) value2).trim()).booleanValue();
+ switch (operation) {
+ case APPROX :
+ case EQUAL :
+ case GREATER :
+ case LESS : {
+ return boolval == boolval2;
+ }
+ }
+ return false;
+ }
+
+ private boolean compare_Float(int operation, float floatval, Object value2) {
+ if (operation == SUBSTRING) {
+ return false;
+ }
+ float floatval2;
+ try {
+ floatval2 = Float.parseFloat(((String) value2).trim());
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+
+ switch (operation) {
+ case APPROX :
+ case EQUAL : {
+ return Float.compare(floatval, floatval2) == 0;
+ }
+ case GREATER : {
+ return Float.compare(floatval, floatval2) >= 0;
+ }
+ case LESS : {
+ return Float.compare(floatval, floatval2) <= 0;
+ }
+ }
+ return false;
+ }
+
+ private boolean compare_Double(int operation, double doubleval, Object value2) {
+ if (operation == SUBSTRING) {
+ return false;
+ }
+ double doubleval2;
+ try {
+ doubleval2 = Double.parseDouble(((String) value2).trim());
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+
+ switch (operation) {
+ case APPROX :
+ case EQUAL : {
+ return Double.compare(doubleval, doubleval2) == 0;
+ }
+ case GREATER : {
+ return Double.compare(doubleval, doubleval2) >= 0;
+ }
+ case LESS : {
+ return Double.compare(doubleval, doubleval2) <= 0;
+ }
+ }
+ return false;
+ }
+
+ private static Object valueOf(Class<?> target, String value2) {
+ do {
+ Method method;
+ try {
+ method = target.getMethod("valueOf", String.class);
+ } catch (NoSuchMethodException e) {
+ break;
+ }
+ if (Modifier.isStatic(method.getModifiers()) && target.isAssignableFrom(method.getReturnType())) {
+ setAccessible(method);
+ try {
+ return method.invoke(null, value2.trim());
+ } catch (IllegalAccessException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ return null;
+ }
+ }
+ } while (false);
+
+ do {
+ Constructor<?> constructor;
+ try {
+ constructor = target.getConstructor(String.class);
+ } catch (NoSuchMethodException e) {
+ break;
+ }
+ setAccessible(constructor);
+ try {
+ return constructor.newInstance(value2.trim());
+ } catch (IllegalAccessException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ return null;
+ } catch (InstantiationException e) {
+ return null;
+ }
+ } while (false);
+
+ return null;
+ }
+
+ private static void setAccessible(AccessibleObject accessible) {
+ if (!accessible.isAccessible()) {
+ AccessController.doPrivileged(new SetAccessibleAction(accessible));
+ }
+ }
+
+ private boolean compare_Comparable(int operation, Comparable<Object> value1, Object value2) {
+ if (operation == SUBSTRING) {
+ return false;
+ }
+ value2 = valueOf(value1.getClass(), (String) value2);
+ if (value2 == null) {
+ 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;
+ }
+ value2 = valueOf(value1.getClass(), (String) value2);
+ if (value2 == null) {
+ 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);
+ }
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
+ private String parse_attr() throws InvalidSyntaxException {
+ skipWhiteSpace();
-import javax.security.auth.x500.X500Principal;
+ int begin = pos;
+ int end = pos;
-/**
- * Framework Utility class.
- *
- * <p>
- * This class contains utility methods which access Framework functions that may
- * be useful to bundles.
- *
- * @since 1.3
- * @ThreadSafe
- * @version $Id: a902bc156ea997ed244831c7fab0f290a08ac0c1 $
- */
-public class FrameworkUtil {
- /**
- * FrameworkUtil objects may not be constructed.
- */
- private FrameworkUtil() {
- // private empty constructor to prevent construction
- }
+ char c = filterChars[pos];
- /**
- * 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
- * thrown with a human readable message where the filter became unparsable.
- *
- * <p>
- * This method returns a Filter implementation which may not perform as well
- * as the framework implementation-specific Filter implementation returned
- * by {@link BundleContext#createFilter(String)}.
- *
- * @param filter The filter string.
- * @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} is null.
- *
- * @see Filter
- */
- public static Filter createFilter(String filter)
- throws InvalidSyntaxException {
- return new org.apache.felix.framework.FilterImpl(filter);
+ 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++;
+ }
+ }
+ }
}
/**
- * Match a Distinguished Name (DN) chain against a pattern. DNs can be
- * matched using wildcards. A wildcard ('*' \u002A) replaces all
- * possible values. Due to the structure of the DN, the comparison is more
- * complicated than string-based wildcard matching.
- * <p>
- * A wildcard can stand for zero or more DNs in a chain, a number of
- * relative distinguished names (RDNs) within a DN, or the value of a single
- * RDN. The DNs in the chain and the matching pattern are canonicalized
- * before processing. This means, among other things, that spaces must be
- * ignored, except in values.
- * <p>
- * The format of a wildcard match pattern is:
- *
- * <pre>
- * matchPattern ::= dn-match ( ';' dn-match ) *
- * dn-match ::= ( '*' | rdn-match ) ( ',' rdn-match ) * | '-'
- * rdn-match ::= name '=' value-match
- * value-match ::= '*' | value-star
- * value-star ::= < value, requires escaped '*' and '-' >
- * </pre>
- * <p>
- * The most simple case is a single wildcard; it must match any DN. A
- * 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 DNs that
- * end with RDNs of o=ACME and c=US would look like this:
- *
- * <pre>
- * *, o=ACME, c=US
- * </pre>
- *
- * This match pattern would match the following DNs:
- *
- * <pre>
- * cn = Bugs Bunny, o = ACME, c = US
- * ou = Carrots, cn=Daffy Duck, o=ACME, c=US
- * street = 9C\, Avenue St. Drézéry, o=ACME, c=US
- * dc=www, dc=acme, dc=com, o=ACME, c=US
- * o=ACME, c=US
- * </pre>
- *
- * The following DNs would not match:
- *
- * <pre>
- * street = 9C\, Avenue St. Drézéry, o=ACME, c=FR
- * dc=www, dc=acme, dc=com, c=US
- * </pre>
- *
- * If a wildcard is used for a value of an RDN, the value must be exactly *.
- * The wildcard must match any value, and no substring matching must be
- * done. For example:
- *
- * <pre>
- * cn=*,o=ACME,c=*
- * </pre>
- *
- * This match pattern with wildcard must match the following DNs:
- *
- * <pre>
- * cn=Bugs Bunny,o=ACME,c=US
- * cn = Daffy Duck , o = ACME , c = US
- * cn=Road Runner, o=ACME, c=NL
- * </pre>
- *
- * But not:
- *
- * <pre>
- * o=ACME, c=NL
- * dc=acme.com, cn=Bugs Bunny, o=ACME, c=US
- * </pre>
- *
- * <p>
- * A match pattern may contain a chain of DN match patterns. The
- * semicolon(';' \u003B) must be used to separate DN match patterns in a
- * chain. Wildcards can also be used to match against a complete DN within a
- * chain.
- * <p>
- * The following example matches a certificate signed by Tweety Inc. in the
- * US.
- * </p>
- *
- * <pre>
- * * ; ou=S & V, o=Tweety Inc., c=US
- * </pre>
- * <p>
- * The wildcard ('*') matches zero or one DN in the chain, however,
- * sometimes it is necessary to match a longer chain. The minus sign ('-'
- * \u002D) represents zero or more DNs, whereas the asterisk only
- * represents a single DN. For example, to match a DN where the Tweety Inc.
- * is in the DN chain, use the following expression:
- * </p>
- *
- * <pre>
- * - ; *, o=Tweety Inc., c=US
- * </pre>
- *
- * @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} 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
+ * 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.
*/
- public static boolean matchDistinguishedNameChain(String matchPattern,
- List<String> dnChain) {
- return DNChainMatching.match(matchPattern, dnChain);
+ 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();
+ }
}
/**
- * 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} for the specified bundle class or
- * {@code null} if the specified class was not defined by a
- * bundle class loader.
- * @since 1.5
+ * 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.
*/
- 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>() {
- public Object run() {
- return classFromBundle.getClassLoader();
+ 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);
+ }
- if (cl instanceof BundleReference) {
- return ((BundleReference) cl).getBundle();
+ 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;
}
- return null;
}
/**
@@ -225,12 +1682,11 @@ 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}
- * " and " {@code ou=Super CA,c=CA}
- * ". The first DN is made of of three RDNs: "
- * {@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}".
+ * 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}" 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
@@ -253,7 +1709,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;
}
@@ -262,22 +1718,19 @@ public class FrameworkUtil {
String patNameValue = (String) rdnPattern.get(i);
int rdnNameEnd = rdnNameValue.indexOf('=');
int patNameEnd = patNameValue.indexOf('=');
- if (rdnNameEnd != patNameEnd
- || !rdnNameValue.regionMatches(0, patNameValue, 0,
- rdnNameEnd)) {
+ if (rdnNameEnd != patNameEnd || !rdnNameValue.regionMatches(0, patNameValue, 0, rdnNameEnd)) {
return false;
}
String patValue = patNameValue.substring(patNameEnd);
String rdnValue = rdnNameValue.substring(rdnNameEnd);
- if (!rdnValue.equals(patValue) && !patValue.equals("=*")
- && !patValue.equals("=#16012a")) {
+ if (!rdnValue.equals(patValue) && !patValue.equals("=*") && !patValue.equals("=#16012a")) {
return false;
}
}
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();
@@ -290,8 +1743,7 @@ public class FrameworkUtil {
}
if (dn.size() < patLen) {
return false;
- }
- else {
+ } else {
if (dn.size() > patLen) {
if (!dnPattern.get(0).equals(STAR_WILDCARD)) {
// If the number of rdns do not match we must have a
@@ -304,9 +1756,7 @@ public class FrameworkUtil {
}
}
for (int i = 0; i < patLen; i++) {
- if (!rdnmatch((List< ? >) dn.get(i + dnStart),
- (List< ? >) dnPattern
- .get(i + patStart))) {
+ if (!rdnmatch((List<?>) dn.get(i + dnStart), (List<?>) dnPattern.get(i + patStart))) {
return false;
}
}
@@ -328,8 +1778,7 @@ public class FrameworkUtil {
*/
private static List<Object> parseDNchainPattern(String dnChain) {
if (dnChain == null) {
- throw new IllegalArgumentException(
- "The DN chain must not be null.");
+ throw new IllegalArgumentException("The DN chain must not be null.");
}
List<Object> parsed = new ArrayList<Object>();
int startIndex = 0;
@@ -370,14 +1819,11 @@ public class FrameworkUtil {
List<Object> rdns = new ArrayList<Object>();
if (dn.charAt(0) == '*') {
if (dn.charAt(1) != ',') {
- throw new IllegalArgumentException(
- "invalid wildcard prefix");
+ throw new IllegalArgumentException("invalid wildcard prefix");
}
rdns.add(STAR_WILDCARD);
- dn = new X500Principal(dn.substring(2))
- .getName(X500Principal.CANONICAL);
- }
- else {
+ dn = new X500Principal(dn.substring(2)).getName(X500Principal.CANONICAL);
+ } else {
dn = new X500Principal(dn).getName(X500Principal.CANONICAL);
}
// Now dn is a nice CANONICAL DN
@@ -415,8 +1861,7 @@ public class FrameworkUtil {
* the index of a non-space character.
*/
private static int skipSpaces(String dnChain, int startIndex) {
- while (startIndex < dnChain.length()
- && dnChain.charAt(startIndex) == ' ') {
+ while (startIndex < dnChain.length() && dnChain.charAt(startIndex) == ' ') {
startIndex++;
}
return startIndex;
@@ -446,24 +1891,21 @@ public class FrameworkUtil {
}
}
if (endIndex > dn.length()) {
- throw new IllegalArgumentException("unterminated escape "
- + dn);
+ throw new IllegalArgumentException("unterminated escape " + dn);
}
nameValues.add(dn.substring(startIndex, endIndex));
if (c != '+') {
rdn.add(nameValues);
if (endIndex != dn.length()) {
nameValues = new ArrayList<String>();
- }
- else {
+ } else {
nameValues = null;
}
}
startIndex = endIndex + 1;
}
if (nameValues != null) {
- throw new IllegalArgumentException("improperly terminated DN "
- + dn);
+ throw new IllegalArgumentException("improperly terminated DN " + dn);
}
}
@@ -471,28 +1913,22 @@ 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<Object> dnChainPattern,
- int dnChainPatternIndex) {
+ private static int skipWildCards(List<Object> dnChainPattern, int dnChainPatternIndex) {
int i;
for (i = dnChainPatternIndex; i < dnChainPattern.size(); i++) {
Object dnPattern = dnChainPattern.get(i);
if (dnPattern instanceof String) {
- if (!dnPattern.equals(STAR_WILDCARD)
- && !dnPattern.equals(MINUS_WILDCARD)) {
- throw new IllegalArgumentException(
- "expected wildcard in DN pattern");
+ if (!dnPattern.equals(STAR_WILDCARD) && !dnPattern.equals(MINUS_WILDCARD)) {
+ throw new IllegalArgumentException("expected wildcard in DN pattern");
}
// otherwise continue skipping over wild cards
- }
- else {
- if (dnPattern instanceof List< ? >) {
+ } else {
+ if (dnPattern instanceof List<?>) {
// if its a list then we have our 'non-wildcard' DN
break;
- }
- else {
+ } else {
// unknown member of the DNChainPattern
- throw new IllegalArgumentException(
- "expected String or List in DN Pattern");
+ throw new IllegalArgumentException("expected String or List in DN Pattern");
}
}
}
@@ -506,10 +1942,7 @@ 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<Object> dnChain,
- int dnChainIndex, List<Object> dnChainPattern,
- int dnChainPatternIndex)
- throws IllegalArgumentException {
+ private static boolean dnChainMatch(List<Object> dnChain, int dnChainIndex, List<Object> dnChainPattern, int dnChainPatternIndex) throws IllegalArgumentException {
if (dnChainIndex >= dnChain.size()) {
return false;
}
@@ -519,25 +1952,20 @@ public class FrameworkUtil {
// check to see what the pattern starts with
Object dnPattern = dnChainPattern.get(dnChainPatternIndex);
if (dnPattern instanceof String) {
- if (!dnPattern.equals(STAR_WILDCARD)
- && !dnPattern.equals(MINUS_WILDCARD)) {
- throw new IllegalArgumentException(
- "expected wildcard in DN pattern");
+ if (!dnPattern.equals(STAR_WILDCARD) && !dnPattern.equals(MINUS_WILDCARD)) {
+ throw new IllegalArgumentException("expected wildcard in DN pattern");
}
// here we are processing a wild card as the first DN
// skip all wildcard DN's
if (dnPattern.equals(MINUS_WILDCARD)) {
- dnChainPatternIndex = skipWildCards(dnChainPattern,
- dnChainPatternIndex);
- }
- else {
+ dnChainPatternIndex = skipWildCards(dnChainPattern, dnChainPatternIndex);
+ } else {
dnChainPatternIndex++; // only skip the '*' wildcard
}
if (dnChainPatternIndex >= dnChainPattern.size()) {
// return true iff the wild card is '-' or if we are at the
// end of the chain
- return dnPattern.equals(MINUS_WILDCARD) ? true : dnChain
- .size() - 1 == dnChainIndex;
+ return dnPattern.equals(MINUS_WILDCARD) ? true : dnChain.size() - 1 == dnChainIndex;
}
//
// we will now recursively call to see if the rest of the
@@ -546,45 +1974,36 @@ public class FrameworkUtil {
//
if (dnPattern.equals(STAR_WILDCARD)) {
// '*' option: only wildcard on 0 or 1
- return dnChainMatch(dnChain, dnChainIndex, dnChainPattern,
- dnChainPatternIndex)
- || dnChainMatch(dnChain, dnChainIndex + 1,
- dnChainPattern, dnChainPatternIndex);
+ return dnChainMatch(dnChain, dnChainIndex, dnChainPattern, dnChainPatternIndex) || dnChainMatch(dnChain, dnChainIndex + 1, dnChainPattern, dnChainPatternIndex);
}
for (int i = dnChainIndex; i < dnChain.size(); i++) {
// '-' option: wildcard 0 or more
- if (dnChainMatch(dnChain, i, dnChainPattern,
- dnChainPatternIndex)) {
+ if (dnChainMatch(dnChain, i, dnChainPattern, dnChainPatternIndex)) {
return true;
}
}
// if we are here, then we didn't find a match.. fall through to
// failure
- }
- else {
- if (dnPattern instanceof List< ? >) {
+ } else {
+ 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
dnChainIndex++;
dnChainPatternIndex++;
// if we finished the pattern then it all matched
- if ((dnChainIndex >= dnChain.size())
- && (dnChainPatternIndex >= dnChainPattern
- .size())) {
+ if ((dnChainIndex >= dnChain.size()) && (dnChainPatternIndex >= dnChainPattern.size())) {
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
if (dnChainIndex >= dnChain.size()) {
- dnChainPatternIndex = skipWildCards(dnChainPattern,
- dnChainPatternIndex);
+ dnChainPatternIndex = skipWildCards(dnChainPattern, dnChainPatternIndex);
// return TRUE iff the pattern index moved past the
// list-size (implying that the rest of the pattern
// is all wildcards)
@@ -598,20 +2017,15 @@ public class FrameworkUtil {
// get the next DN Pattern
dnPattern = dnChainPattern.get(dnChainPatternIndex);
if (dnPattern instanceof String) {
- if (!dnPattern.equals(STAR_WILDCARD)
- && !dnPattern.equals(MINUS_WILDCARD)) {
- throw new IllegalArgumentException(
- "expected wildcard in DN pattern");
+ if (!dnPattern.equals(STAR_WILDCARD) && !dnPattern.equals(MINUS_WILDCARD)) {
+ throw new IllegalArgumentException("expected wildcard in DN pattern");
}
// if the next DN is a 'wildcard', then we will
// recurse
- return dnChainMatch(dnChain, dnChainIndex,
- dnChainPattern, dnChainPatternIndex);
- }
- else {
- if (!(dnPattern instanceof List< ? >)) {
- throw new IllegalArgumentException(
- "expected String or List in DN Pattern");
+ return dnChainMatch(dnChain, dnChainIndex, dnChainPattern, dnChainPatternIndex);
+ } else {
+ if (!(dnPattern instanceof List<?>)) {
+ throw new IllegalArgumentException("expected String or List in DN Pattern");
}
}
// if we are here, then we will just continue to the
@@ -619,10 +2033,8 @@ public class FrameworkUtil {
// DNChainPattern since both are lists
} while (true);
// should never reach here?
- }
- else {
- throw new IllegalArgumentException(
- "expected String or List in DN Pattern");
+ } else {
+ throw new IllegalArgumentException("expected String or List in DN Pattern");
}
}
// if we get here, the the default return is 'mis-match'
@@ -667,31 +2079,27 @@ public class FrameworkUtil {
List<Object> parsedDNPattern;
try {
parsedDNChain = parseDNchain(dnChain);
- }
- catch (RuntimeException e) {
- IllegalArgumentException iae = new IllegalArgumentException(
- "Invalid DN chain: " + toString(dnChain));
+ } catch (RuntimeException e) {
+ IllegalArgumentException iae = new IllegalArgumentException("Invalid DN chain: " + toString(dnChain));
iae.initCause(e);
throw iae;
}
try {
parsedDNPattern = parseDNchainPattern(pattern);
- }
- catch (RuntimeException e) {
- IllegalArgumentException iae = new IllegalArgumentException(
- "Invalid match pattern: " + pattern);
+ } catch (RuntimeException e) {
+ IllegalArgumentException iae = new IllegalArgumentException("Invalid match pattern: " + pattern);
iae.initCause(e);
throw iae;
}
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=1337360&r1=1337359&r2=1337360&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 Fri May 11 20:19:02 2012
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2000, 2010). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2012). 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} 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.
+ * 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 $Id: adb84e3bc0b82b842e4da84542057fdf53e2ca6a $
+ * @version $Id: 8820ca2db85b557cef8da09ee861249dfb5ee914 $
*/
public class InvalidSyntaxException extends Exception {
@@ -42,15 +42,14 @@ public class InvalidSyntaxException exte
* Creates an exception of type {@code InvalidSyntaxException}.
*
* <p>
- * This method creates an {@code InvalidSyntaxException} object with
- * the specified message and the filter string which generated the
- * exception.
+ * This method creates an {@code InvalidSyntaxException} object with the
+ * specified message and the filter string which generated the exception.
*
* @param msg The message.
* @param filter The invalid filter string.
*/
public InvalidSyntaxException(String msg, String filter) {
- super(msg);
+ super(message(msg, filter));
this.filter = filter;
}
@@ -58,9 +57,8 @@ public class InvalidSyntaxException exte
* Creates an exception of type {@code InvalidSyntaxException}.
*
* <p>
- * This method creates an {@code InvalidSyntaxException} object with
- * the specified message and the filter string which generated the
- * exception.
+ * This method creates an {@code InvalidSyntaxException} object with the
+ * specified message and the filter string which generated the exception.
*
* @param msg The message.
* @param filter The invalid filter string.
@@ -68,16 +66,27 @@ public class InvalidSyntaxException exte
* @since 1.3
*/
public InvalidSyntaxException(String msg, String filter, Throwable cause) {
- super(msg, cause);
+ super(message(msg, filter), cause);
this.filter = filter;
}
/**
+ * Return message string for super constructor.
+ */
+ private static String message(String msg, String filter) {
+ if ((msg == null) || (filter == null) || msg.indexOf(filter) >= 0) {
+ return msg;
+ }
+ return msg + ": " + filter;
+ }
+
+ /**
* Returns the filter string that generated the
* {@code InvalidSyntaxException} object.
*
* @return The invalid filter string.
- * @see BundleContext#getServiceReferences
+ * @see BundleContext#getServiceReferences(Class, String)
+ * @see BundleContext#getServiceReferences(String, String)
* @see BundleContext#addServiceListener(ServiceListener,String)
*/
public String getFilter() {
@@ -85,11 +94,9 @@ public class InvalidSyntaxException exte
}
/**
- * Returns the cause of this exception or {@code null} if no cause was
- * set.
+ * Returns the cause of this exception or {@code null} if no cause was set.
*
- * @return The cause of this exception or {@code null} if no cause was
- * set.
+ * @return The cause of this exception or {@code null} if no cause was set.
* @since 1.3
*/
public Throwable getCause() {
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=1337360&r1=1337359&r2=1337360&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 Fri May 11 20:19:02 2012
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2000, 2010). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2012). 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.
@@ -50,65 +50,64 @@ import java.util.Map;
*
* <p>
* {@code PackagePermission} has three actions: {@code exportonly},
- * {@code import} and {@code export}. The {@code export} action,
- * which is deprecated, implies the {@code import} action.
+ * {@code import} and {@code export}. The {@code export} action, which is
+ * deprecated, implies the {@code import} action.
*
* @ThreadSafe
- * @version $Id: a286af94405e583f8bedc2ff5d7c818198f8caaf $
+ * @version $Id: e993fbc36b6bff84182a8594af5af3cad8c4e2a3 $
*/
public final class PackagePermission extends BasicPermission {
- static final long serialVersionUID = -5107705877071099135L;
+ static final long serialVersionUID = -5107705877071099135L;
/**
- * The action string {@code export}. The {@code export} action
- * implies the {@code import} action.
+ * The action string {@code export}. The {@code export} action implies the
+ * {@code import} action.
*
* @deprecated Since 1.5. Use {@code exportonly} instead.
*/
- public final static String EXPORT = "export";
+ public final static String EXPORT = "export";
/**
- * The action string {@code exportonly}. The {@code exportonly}
- * action does not imply the {@code import} 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";
+ public final static String EXPORTONLY = "exportonly";
/**
* The action string {@code import}.
*/
- public final static String IMPORT = "import";
+ public final static String IMPORT = "import";
- private final static int ACTION_EXPORT = 0x00000001;
- private final static int ACTION_IMPORT = 0x00000002;
- private final static int ACTION_ALL = ACTION_EXPORT
- | ACTION_IMPORT;
- final static int ACTION_NONE = 0;
+ private final static int ACTION_EXPORT = 0x00000001;
+ private final static int ACTION_IMPORT = 0x00000002;
+ private final static int ACTION_ALL = ACTION_EXPORT | ACTION_IMPORT;
+ final static int ACTION_NONE = 0;
/**
* The actions mask.
*/
- transient int action_mask;
+ transient int action_mask;
/**
* The actions in canonical form.
*
* @serial
*/
- private volatile String actions = null;
+ private volatile String actions = null;
/**
* The bundle used by this PackagePermission.
*/
- transient final Bundle bundle;
+ transient final Bundle bundle;
/**
* If this PackagePermission was constructed with a filter, this holds a
* Filter matching object used to evaluate the filter in implies.
*/
- transient Filter filter;
+ transient Filter filter;
/**
* This map holds the properties of the permission, used to match a filter
@@ -136,8 +135,8 @@ public final class PackagePermission ext
* *
* </pre>
*
- * For the {@code import} action, the name can also be a filter
- * expression. The filter gives access to the following attributes:
+ * 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
* bundle. Wildcards in a DN are not matched according to the filter string
@@ -161,27 +160,23 @@ public final class PackagePermission ext
*
* @param name Package name or filter expression. A filter expression can
* only be specified if the specified action is {@code import}.
- * @param actions {@code exportonly},{@code import} (canonical
- * order).
+ * @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} or the filter has an invalid syntax.
+ * expression and either the specified action is not {@code import}
+ * or the filter has an invalid syntax.
*/
public PackagePermission(String name, String actions) {
this(name, parseActions(actions));
- if ((filter != null)
- && ((action_mask & ACTION_ALL) != ACTION_IMPORT)) {
- throw new IllegalArgumentException(
- "invalid action string for filter expression");
+ if ((filter != null) && ((action_mask & ACTION_ALL) != ACTION_IMPORT)) {
+ throw new IllegalArgumentException("invalid action string for filter expression");
}
}
/**
- * 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} permission collection.
+ * 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} permission collection.
*
* @param name The name of the requested package to import.
* @param exportingBundle The bundle exporting the requested package.
@@ -255,9 +250,7 @@ public final class PackagePermission ext
char c;
// skip whitespace
- while ((i != -1)
- && ((c = a[i]) == ' ' || c == '\r' || c == '\n'
- || c == '\f' || c == '\t'))
+ while ((i != -1) && ((c = a[i]) == ' ' || c == '\r' || c == '\n' || c == '\f' || c == '\t'))
i--;
// check for the known strings
@@ -272,8 +265,7 @@ public final class PackagePermission ext
matchlen = 6;
mask |= ACTION_IMPORT;
- }
- else
+ } else
if (i >= 5 && (a[i - 5] == 'e' || a[i - 5] == 'E')
&& (a[i - 4] == 'x' || a[i - 4] == 'X')
&& (a[i - 3] == 'p' || a[i - 3] == 'P')
@@ -283,8 +275,7 @@ public final class PackagePermission ext
matchlen = 6;
mask |= ACTION_EXPORT | ACTION_IMPORT;
- }
- else {
+ } else {
if (i >= 9 && (a[i - 9] == 'e' || a[i - 9] == 'E')
&& (a[i - 8] == 'x' || a[i - 8] == 'X')
&& (a[i - 7] == 'p' || a[i - 7] == 'P')
@@ -298,11 +289,9 @@ public final class PackagePermission ext
matchlen = 10;
mask |= ACTION_EXPORT;
- }
- else {
+ } else {
// parse error
- throw new IllegalArgumentException(
- "invalid permission: " + actions);
+ throw new IllegalArgumentException("invalid permission: " + actions);
}
}
@@ -321,8 +310,7 @@ public final class PackagePermission ext
case '\t' :
break;
default :
- throw new IllegalArgumentException(
- "invalid permission: " + actions);
+ throw new IllegalArgumentException("invalid permission: " + actions);
}
i--;
}
@@ -354,10 +342,8 @@ public final class PackagePermission ext
try {
return FrameworkUtil.createFilter(filterString);
- }
- catch (InvalidSyntaxException e) {
- IllegalArgumentException iae = new IllegalArgumentException(
- "invalid filter");
+ } catch (InvalidSyntaxException e) {
+ IllegalArgumentException iae = new IllegalArgumentException("invalid filter");
iae.initCause(e);
throw iae;
}
@@ -432,11 +418,11 @@ public final class PackagePermission ext
* {@code PackagePermission} actions.
*
* <p>
- * Always returns present {@code PackagePermission} actions in the
- * following order: {@code EXPORTONLY},{@code IMPORT}.
+ * Always returns present {@code PackagePermission} actions in the following
+ * order: {@code EXPORTONLY},{@code IMPORT}.
*
- * @return Canonical string representation of the
- * {@code PackagePermission} actions.
+ * @return Canonical string representation of the {@code PackagePermission}
+ * actions.
*/
public String getActions() {
String result = actions;
@@ -462,8 +448,8 @@ public final class PackagePermission ext
}
/**
- * Returns a new {@code PermissionCollection} object suitable for
- * storing {@code PackagePermission} objects.
+ * Returns a new {@code PermissionCollection} object suitable for storing
+ * {@code PackagePermission} objects.
*
* @return A new {@code PermissionCollection} object.
*/
@@ -475,15 +461,14 @@ public final class PackagePermission ext
* Determines the equality of two {@code PackagePermission} objects.
*
* This method checks that specified package has the same package name and
- * {@code PackagePermission} actions as this
- * {@code PackagePermission} object.
+ * {@code PackagePermission} actions as this {@code PackagePermission}
+ * object.
*
* @param obj The object to test for equality with this
* {@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.
+ * @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) {
@@ -496,10 +481,7 @@ public final class PackagePermission ext
PackagePermission pp = (PackagePermission) obj;
- return (action_mask == pp.action_mask)
- && getName().equals(pp.getName())
- && ((bundle == pp.bundle) || ((bundle != null) && bundle
- .equals(pp.bundle)));
+ return (action_mask == pp.action_mask) && getName().equals(pp.getName()) && ((bundle == pp.bundle) || ((bundle != null) && bundle.equals(pp.bundle)));
}
/**
@@ -521,8 +503,7 @@ public final class PackagePermission ext
* stream. The actions are serialized, and the superclass takes care of the
* name.
*/
- private synchronized void writeObject(java.io.ObjectOutputStream s)
- throws IOException {
+ private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException {
if (bundle != null) {
throw new NotSerializableException("cannot serialize");
}
@@ -537,8 +518,7 @@ public final class PackagePermission ext
* readObject is called to restore the state of this permission from a
* stream.
*/
- private synchronized void readObject(java.io.ObjectInputStream s)
- throws IOException, ClassNotFoundException {
+ private synchronized void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
// Read in the action, then initialize the rest
s.defaultReadObject();
setTransients(getName(), parseActions(actions));
@@ -588,7 +568,7 @@ public final class PackagePermission ext
*/
final class PackagePermissionCollection extends PermissionCollection {
- static final long serialVersionUID = -3350758995234427603L;
+ static final long serialVersionUID = -3350758995234427603L;
/**
* Table of permissions with names.
*
@@ -602,7 +582,7 @@ final class PackagePermissionCollection
* @serial
* @GuardedBy this
*/
- private boolean all_allowed;
+ private boolean all_allowed;
/**
* Table of permissions with filter expressions.
@@ -627,24 +607,20 @@ final class PackagePermissionCollection
* @throws IllegalArgumentException If the specified permission is not a
* {@code PackagePermission} instance or was constructed with a
* Bundle object.
- * @throws SecurityException If this
- * {@code PackagePermissionCollection} object has been marked
- * read-only.
+ * @throws SecurityException If this {@code PackagePermissionCollection}
+ * object has been marked read-only.
*/
public void add(final Permission permission) {
if (!(permission instanceof PackagePermission)) {
- throw new IllegalArgumentException("invalid permission: "
- + permission);
+ throw new IllegalArgumentException("invalid permission: " + permission);
}
if (isReadOnly()) {
- throw new SecurityException("attempt to add a Permission to a "
- + "readonly PermissionCollection");
+ throw new SecurityException("attempt to add a Permission to a " + "readonly PermissionCollection");
}
final PackagePermission pp = (PackagePermission) permission;
if (pp.bundle != null) {
- throw new IllegalArgumentException("cannot add to collection: "
- + pp);
+ throw new IllegalArgumentException("cannot add to collection: " + pp);
}
final String name = pp.getName();
@@ -657,23 +633,19 @@ final class PackagePermissionCollection
if (pc == null) {
filterPermissions = pc = new HashMap<String, PackagePermission>();
}
- }
- else {
+ } else {
pc = permissions;
}
-
+
final PackagePermission existing = pc.get(name);
if (existing != null) {
final int oldMask = existing.action_mask;
final int newMask = pp.action_mask;
if (oldMask != newMask) {
- pc
- .put(name, new PackagePermission(name, oldMask
- | newMask));
+ pc.put(name, new PackagePermission(name, oldMask | newMask));
}
- }
- else {
+ } else {
pc.put(name, pp);
}
@@ -691,8 +663,8 @@ final class PackagePermissionCollection
*
* @param permission The Permission object to compare with this
* {@code PackagePermission} object.
- * @return {@code true} if {@code permission} is a proper subset
- * of a permission in the set; {@code false} otherwise.
+ * @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)) {
@@ -767,8 +739,8 @@ final class PackagePermissionCollection
}
/**
- * Returns an enumeration of all {@code PackagePermission} objects in
- * the container.
+ * Returns an enumeration of all {@code PackagePermission} objects in the
+ * container.
*
* @return Enumeration of all {@code PackagePermission} objects.
*/
@@ -782,15 +754,11 @@ final class PackagePermissionCollection
}
/* serialization logic */
- private static final ObjectStreamField[] serialPersistentFields = {
- new ObjectStreamField("permissions", Hashtable.class),
- new ObjectStreamField("all_allowed", Boolean.TYPE),
+ private static final ObjectStreamField[] serialPersistentFields = {new ObjectStreamField("permissions", Hashtable.class), new ObjectStreamField("all_allowed", Boolean.TYPE),
new ObjectStreamField("filterPermissions", HashMap.class) };
- private synchronized void writeObject(ObjectOutputStream out)
- throws IOException {
- Hashtable<String, PackagePermission> hashtable = new Hashtable<String, PackagePermission>(
- permissions);
+ private synchronized void writeObject(ObjectOutputStream out) throws IOException {
+ Hashtable<String, PackagePermission> hashtable = new Hashtable<String, PackagePermission>(permissions);
ObjectOutputStream.PutField pfields = out.putFields();
pfields.put("permissions", hashtable);
pfields.put("all_allowed", all_allowed);
@@ -798,15 +766,12 @@ final class PackagePermissionCollection
out.writeFields();
}
- private synchronized void readObject(java.io.ObjectInputStream in)
- throws IOException, ClassNotFoundException {
+ private synchronized void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gfields = in.readFields();
- Hashtable<String, PackagePermission> hashtable = (Hashtable<String, PackagePermission>) gfields
- .get("permissions", null);
+ Hashtable<String, PackagePermission> hashtable = (Hashtable<String, PackagePermission>) gfields.get("permissions", null);
permissions = new HashMap<String, PackagePermission>(hashtable);
all_allowed = gfields.get("all_allowed", false);
- HashMap<String, PackagePermission> fp = (HashMap<String, PackagePermission>) gfields
- .get("filterPermissions", null);
+ HashMap<String, PackagePermission> fp = (HashMap<String, PackagePermission>) gfields.get("filterPermissions", null);
filterPermissions = fp;
}
}