diff options
Diffstat (limited to 'java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/impl/LDAPFilter.java')
-rw-r--r-- | java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/impl/LDAPFilter.java | 1373 |
1 files changed, 0 insertions, 1373 deletions
diff --git a/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/impl/LDAPFilter.java b/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/impl/LDAPFilter.java deleted file mode 100644 index 8d3630baa4..0000000000 --- a/java/sca/modules/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/impl/LDAPFilter.java +++ /dev/null @@ -1,1373 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2005, 2009). All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.tuscany.sca.extensibility.impl; - -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.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.Properties; - -import org.apache.tuscany.sca.extensibility.ServiceDeclaration; - - -/** - * This code is derived from <a href="http://svn.apache.org/repos/asf/felix/releases/org.osgi.core-1.4.0/src/main/java/org/osgi/framework/FrameworkUtil.java">FrameworkUtil</a> - * <p> - * 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></code> 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></code> 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></code> must contain one of the characters ' - * <code>*</code>' or '<code>(</code>' or '<code>)</code>', these characters - * should be escaped by preceding them with the backslash '<code>\</code>' - * character. Note that although both the <code><substring></code> and - * <code><present></code> productions can produce the <code>'attr=*'</code> - * 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>~=</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)</code> and also <code>(cn=b)</code> - * - * <p> - * A filter component that references a key having an unrecognizable data - * type will evaluate to <code>false</code> . - */ -public class LDAPFilter { - /* 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 volatile String filterString; - - /** - * Constructs a {@link LDAPFilter} 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. - * @exception InvalidSyntaxException If the filter parameter contains an - * invalid filter string that cannot be parsed. - */ - public static LDAPFilter newInstance(String filterString) throws InvalidSyntaxException { - return new Parser(filterString).parse(); - } - - LDAPFilter(int operation, String attr, Object value) { - this.op = operation; - this.attr = attr; - this.value = value; - } - - /** - * Filter using a <code>Dictionary</code>. This <code>Filter</code> is - * executed using the specified <code>Dictionary</code>'s keys and - * values. The keys are case insensitively matched with this - * <code>Filter</code>. - * - * @param dictionary The <code>Dictionary</code> whose keys are used in - * the match. - * @return <code>true</code> if the <code>Dictionary</code>'s keys and - * values match this filter; <code>false</code> otherwise. - * @throws IllegalArgumentException If <code>dictionary</code> contains - * case variants of the same key name. - */ - public boolean match(Dictionary dictionary) { - return match0(new CaseInsensitiveDictionary(dictionary)); - } - - public boolean match(Map map) { - Properties props = new Properties(); - props.putAll(map); - return match0(new CaseInsensitiveDictionary(props)); - } - - public static boolean matches(ServiceDeclaration declaration, String filter) { - if (filter == null) { - return true; - } - LDAPFilter filterImpl = newInstance(filter); - return filterImpl.match(declaration.getAttributes()); - } - - /** - * Filter with case sensitivity using a <code>Dictionary</code>. This - * <code>Filter</code> is executed using the specified - * <code>Dictionary</code>'s keys and values. The keys are case - * sensitively matched with this <code>Filter</code>. - * - * @param dictionary The <code>Dictionary</code> whose keys are used in - * the match. - * @return <code>true</code> if the <code>Dictionary</code>'s keys and - * values match this filter; <code>false</code> otherwise. - * @since 1.3 - */ - public boolean matchCase(Dictionary dictionary) { - return match0(dictionary); - } - - /** - * Returns this <code>Filter</code>'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</code>'s filter string. - */ - public String toString() { - String result = filterString; - if (result == null) { - filterString = result = normalize(); - } - return result; - } - - /** - * Returns this <code>Filter</code>'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</code>'s filter string. - */ - private String normalize() { - StringBuffer sb = new StringBuffer(); - sb.append('('); - - switch (op) { - case AND: { - sb.append('&'); - - LDAPFilter[] filters = (LDAPFilter[])value; - for (int i = 0, size = filters.length; i < size; i++) { - sb.append(filters[i].normalize()); - } - - break; - } - - case OR: { - sb.append('|'); - - LDAPFilter[] filters = (LDAPFilter[])value; - for (int i = 0, size = filters.length; i < size; i++) { - sb.append(filters[i].normalize()); - } - - break; - } - - case NOT: { - sb.append('!'); - LDAPFilter filter = (LDAPFilter)value; - sb.append(filter.normalize()); - - break; - } - - case SUBSTRING: { - sb.append(attr); - sb.append('='); - - String[] substrings = (String[])value; - - for (int i = 0, size = substrings.length; i < size; i++) { - String substr = substrings[i]; - - 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.toString(); - } - - /** - * Compares this <code>Filter</code> to another <code>Filter</code>. - * - * <p> - * This implementation returns the result of calling - * <code>this.toString().equals(obj.toString()</code>. - * - * @param obj The object to compare against this <code>Filter</code>. - * @return If the other object is a <code>Filter</code> object, then - * returns the result of calling - * <code>this.toString().equals(obj.toString()</code>; - * <code>false</code> otherwise. - */ - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof LDAPFilter)) { - return false; - } - - return this.toString().equals(obj.toString()); - } - - /** - * Returns the hashCode for this <code>Filter</code>. - * - * <p> - * This implementation returns the result of calling - * <code>this.toString().hashCode()</code>. - * - * @return The hashCode of this <code>Filter</code>. - */ - public int hashCode() { - return this.toString().hashCode(); - } - - /** - * Internal match routine. Dictionary parameter must support - * case-insensitive get. - * - * @param properties A dictionary whose keys are used in the match. - * @return If the Dictionary's keys match the filter, return - * <code>true</code>. Otherwise, return <code>false</code>. - */ - private boolean match0(Dictionary properties) { - switch (op) { - case AND: { - LDAPFilter[] filters = (LDAPFilter[])value; - for (int i = 0, size = filters.length; i < size; i++) { - if (!filters[i].match0(properties)) { - return false; - } - } - - return true; - } - - case OR: { - LDAPFilter[] filters = (LDAPFilter[])value; - for (int i = 0, size = filters.length; i < size; i++) { - if (filters[i].match0(properties)) { - return true; - } - } - - return false; - } - - case NOT: { - LDAPFilter filter = (LDAPFilter)value; - - return !filter.match0(properties); - } - - case SUBSTRING: - case EQUAL: - case GREATER: - case LESS: - case APPROX: { - Object prop = (properties == null) ? null : properties.get(attr); - - return compare(op, prop, value); - } - - case PRESENT: { - Object prop = (properties == null) ? null : properties.get(attr); - - return prop != null; - } - } - - return false; - } - - /** - * 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) { - return compare_Comparable(operation, (Comparable)value1, value2); - } - return compare_Unknown(operation, value1, value2); // RFC 59 - } - - private boolean compare_Collection(int operation, Collection collection, Object value2) { - for (Iterator iterator = collection.iterator(); iterator.hasNext();) { - if (compare(operation, iterator.next(), value2)) { - return true; - } - } - return false; - } - - private boolean compare_ObjectArray(int operation, Object[] array, Object value2) { - for (int i = 0, size = array.length; i < size; i++) { - if (compare(operation, array[i], 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 i = 0, size = array.length; i < size; i++) { - if (compare_Integer(operation, array[i], value2)) { - return true; - } - } - return false; - } - if (Long.TYPE.isAssignableFrom(type)) { - long[] array = (long[])primarray; - for (int i = 0, size = array.length; i < size; i++) { - if (compare_Long(operation, array[i], value2)) { - return true; - } - } - return false; - } - if (Byte.TYPE.isAssignableFrom(type)) { - byte[] array = (byte[])primarray; - for (int i = 0, size = array.length; i < size; i++) { - if (compare_Byte(operation, array[i], value2)) { - return true; - } - } - return false; - } - if (Short.TYPE.isAssignableFrom(type)) { - short[] array = (short[])primarray; - for (int i = 0, size = array.length; i < size; i++) { - if (compare_Short(operation, array[i], value2)) { - return true; - } - } - return false; - } - if (Character.TYPE.isAssignableFrom(type)) { - char[] array = (char[])primarray; - for (int i = 0, size = array.length; i < size; i++) { - if (compare_Character(operation, array[i], value2)) { - return true; - } - } - return false; - } - if (Float.TYPE.isAssignableFrom(type)) { - float[] array = (float[])primarray; - for (int i = 0, size = array.length; i < size; i++) { - if (compare_Float(operation, array[i], value2)) { - return true; - } - } - return false; - } - if (Double.TYPE.isAssignableFrom(type)) { - double[] array = (double[])primarray; - for (int i = 0, size = array.length; i < size; i++) { - if (compare_Double(operation, array[i], value2)) { - return true; - } - } - return false; - } - if (Boolean.TYPE.isAssignableFrom(type)) { - boolean[] array = (boolean[])primarray; - for (int i = 0, size = array.length; i < size; i++) { - if (compare_Boolean(operation, array[i], 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 = Integer.parseInt(((String)value2).trim()); - 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 = Long.parseLong(((String)value2).trim()); - 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 = Byte.parseByte(((String)value2).trim()); - 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 = Short.parseShort(((String)value2).trim()); - 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 = (((String)value2).trim()).charAt(0); - 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 = Float.parseFloat(((String)value2).trim()); - 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 = Double.parseDouble(((String)value2).trim()); - switch (operation) { - case APPROX: - case EQUAL: { - return Double.compare(doubleval, doubleval2) == 0; - } - case GREATER: { - return Double.compare(doubleval, doubleval2) >= 0; - } - case LESS: { - return Double.compare(doubleval, doubleval2) <= 0; - } - } - return false; - } - - private static final Class[] constructorType = new Class[] {String.class}; - - private boolean compare_Comparable(int operation, Comparable value1, Object value2) { - if (operation == SUBSTRING) { - return false; - } - Constructor constructor; - try { - constructor = value1.getClass().getConstructor(constructorType); - } catch (NoSuchMethodException e) { - return false; - } - try { - if (!constructor.isAccessible()) - AccessController.doPrivileged(new SetAccessibleAction(constructor)); - value2 = constructor.newInstance(new Object[] {((String)value2).trim()}); - } catch (IllegalAccessException e) { - return false; - } catch (InvocationTargetException e) { - return false; - } catch (InstantiationException e) { - return false; - } - - 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; - } - } - return false; - } - - private boolean compare_Unknown(int operation, Object value1, Object value2) { - if (operation == SUBSTRING) { - return false; - } - Constructor constructor; - try { - constructor = value1.getClass().getConstructor(constructorType); - } catch (NoSuchMethodException e) { - return false; - } - try { - if (!constructor.isAccessible()) - AccessController.doPrivileged(new SetAccessibleAction(constructor)); - value2 = constructor.newInstance(new Object[] {((String)value2).trim()}); - } catch (IllegalAccessException e) { - return false; - } catch (InvocationTargetException e) { - return false; - } catch (InstantiationException e) { - return false; - } - - switch (operation) { - case APPROX: - case EQUAL: - case GREATER: - case LESS: { - return value1.equals(value2); - } - } - 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 (int i = 0, length = output.length; i < length; i++) { - char c = output[i]; - - 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. - */ - private static class Parser { - private final String filterstring; - private final char[] filterChars; - private int pos; - - Parser(String filterstring) { - this.filterstring = filterstring; - filterChars = filterstring.toCharArray(); - pos = 0; - } - - LDAPFilter parse() throws InvalidSyntaxException { - LDAPFilter filter; - try { - filter = parse_filter(); - } catch (ArrayIndexOutOfBoundsException e) { - throw new InvalidSyntaxException("Filter ended abruptly", filterstring); - } - - if (pos != filterChars.length) { - throw new InvalidSyntaxException("Extraneous trailing characters: " + filterstring.substring(pos), - filterstring); - } - return filter; - } - - private LDAPFilter parse_filter() throws InvalidSyntaxException { - LDAPFilter 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 LDAPFilter 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 LDAPFilter parse_and() throws InvalidSyntaxException { - skipWhiteSpace(); - - if (filterChars[pos] != '(') { - throw new InvalidSyntaxException("Missing '(': " + filterstring.substring(pos), filterstring); - } - - List operands = new ArrayList(10); - - while (filterChars[pos] == '(') { - LDAPFilter child = parse_filter(); - operands.add(child); - } - - return new LDAPFilter(LDAPFilter.AND, null, operands.toArray(new LDAPFilter[operands.size()])); - } - - private LDAPFilter parse_or() throws InvalidSyntaxException { - skipWhiteSpace(); - - if (filterChars[pos] != '(') { - throw new InvalidSyntaxException("Missing '(': " + filterstring.substring(pos), filterstring); - } - - List operands = new ArrayList(10); - - while (filterChars[pos] == '(') { - LDAPFilter child = parse_filter(); - operands.add(child); - } - - return new LDAPFilter(LDAPFilter.OR, null, operands.toArray(new LDAPFilter[operands.size()])); - } - - private LDAPFilter parse_not() throws InvalidSyntaxException { - skipWhiteSpace(); - - if (filterChars[pos] != '(') { - throw new InvalidSyntaxException("Missing '(': " + filterstring.substring(pos), filterstring); - } - - LDAPFilter child = parse_filter(); - - return new LDAPFilter(LDAPFilter.NOT, null, child); - } - - private LDAPFilter parse_item() throws InvalidSyntaxException { - String attr = parse_attr(); - - skipWhiteSpace(); - - switch (filterChars[pos]) { - case '~': { - if (filterChars[pos + 1] == '=') { - pos += 2; - return new LDAPFilter(LDAPFilter.APPROX, attr, parse_value()); - } - break; - } - case '>': { - if (filterChars[pos + 1] == '=') { - pos += 2; - return new LDAPFilter(LDAPFilter.GREATER, attr, parse_value()); - } - break; - } - case '<': { - if (filterChars[pos + 1] == '=') { - pos += 2; - return new LDAPFilter(LDAPFilter.LESS, attr, parse_value()); - } - break; - } - case '=': { - if (filterChars[pos + 1] == '*') { - int oldpos = pos; - pos += 2; - skipWhiteSpace(); - if (filterChars[pos] == ')') { - return new LDAPFilter(LDAPFilter.PRESENT, attr, null); - } - pos = oldpos; - } - - pos++; - Object string = parse_substring(); - - if (string instanceof String) { - return new LDAPFilter(LDAPFilter.EQUAL, attr, string); - } - return new LDAPFilter(LDAPFilter.SUBSTRING, attr, string); - } - } - - throw new InvalidSyntaxException("Invalid operator: " + filterstring.substring(pos), filterstring); - } - - private String parse_attr() throws InvalidSyntaxException { - skipWhiteSpace(); - - int begin = pos; - int end = pos; - - char c = filterChars[pos]; - - while (c != '~' && c != '<' && c != '>' && c != '=' && c != '(' && c != ')') { - pos++; - - if (!Character.isWhitespace(c)) { - end = pos; - } - - c = filterChars[pos]; - } - - int length = end - begin; - - if (length == 0) { - throw new InvalidSyntaxException("Missing attr: " + filterstring.substring(pos), filterstring); - } - - return new String(filterChars, begin, length); - } - - private String parse_value() throws InvalidSyntaxException { - StringBuffer sb = new StringBuffer(filterChars.length - pos); - - parseloop: while (true) { - char c = filterChars[pos]; - - switch (c) { - case ')': { - break parseloop; - } - - case '(': { - throw new InvalidSyntaxException("Invalid value: " + filterstring.substring(pos), - filterstring); - } - - case '\\': { - pos++; - c = filterChars[pos]; - /* fall through into default */ - } - - default: { - sb.append(c); - pos++; - break; - } - } - } - - if (sb.length() == 0) { - throw new InvalidSyntaxException("Missing value: " + filterstring.substring(pos), filterstring); - } - - return sb.toString(); - } - - private Object parse_substring() throws InvalidSyntaxException { - StringBuffer sb = new StringBuffer(filterChars.length - pos); - - List operands = new ArrayList(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) { - throw new InvalidSyntaxException("Missing value: " + filterstring.substring(pos), filterstring); - } - - if (size == 1) { - Object single = operands.get(0); - - if (single != null) { - return single; - } - } - - return operands.toArray(new String[size]); - } - - private void skipWhiteSpace() { - for (int length = filterChars.length; (pos < length) && Character.isWhitespace(filterChars[pos]);) { - pos++; - } - } - } - - /** - * This Dictionary is used for case-insensitive key lookup during filter - * evaluation. This Dictionary implementation only supports the get - * operation using a String key as no other operations are used by the - * Filter implementation. - */ - static class CaseInsensitiveDictionary extends Dictionary { - private final Dictionary dictionary; - private final String[] keys; - - /** - * Create a case insensitive dictionary from the specified dictionary. - * - * @param dictionary - * @throws IllegalArgumentException If <code>dictionary</code> contains - * case variants of the same key name. - */ - CaseInsensitiveDictionary(Dictionary dictionary) { - if (dictionary == null) { - this.dictionary = null; - this.keys = new String[0]; - return; - } - this.dictionary = dictionary; - List keyList = new ArrayList(dictionary.size()); - for (Enumeration e = dictionary.keys(); e.hasMoreElements();) { - Object k = e.nextElement(); - if (k instanceof String) { - String key = (String)k; - for (Iterator i = keyList.iterator(); i.hasNext();) { - if (key.equalsIgnoreCase((String)i.next())) { - throw new IllegalArgumentException(); - } - } - keyList.add(key); - } - } - this.keys = (String[])keyList.toArray(new String[keyList.size()]); - } - - public Object get(Object o) { - String k = (String)o; - for (int i = 0, length = keys.length; i < length; i++) { - String key = keys[i]; - if (key.equalsIgnoreCase(k)) { - return dictionary.get(key); - } - } - return null; - } - - public boolean isEmpty() { - throw new UnsupportedOperationException(); - } - - public Enumeration keys() { - throw new UnsupportedOperationException(); - } - - public Enumeration elements() { - throw new UnsupportedOperationException(); - } - - public Object put(Object key, Object value) { - throw new UnsupportedOperationException(); - } - - public Object remove(Object key) { - throw new UnsupportedOperationException(); - } - - public int size() { - throw new UnsupportedOperationException(); - } - } - - static class SetAccessibleAction implements PrivilegedAction { - private final AccessibleObject accessible; - - SetAccessibleAction(AccessibleObject accessible) { - this.accessible = accessible; - } - - public Object run() { - accessible.setAccessible(true); - return null; - } - } -}
\ No newline at end of file |