📄 ldapexpr.java
字号:
/* * Copyright (c) 2003-2004, KNOPFLERFISH project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * - Neither the name of the KNOPFLERFISH project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */package org.knopflerfish.framework;import org.osgi.framework.InvalidSyntaxException;import java.util.Dictionary;import java.util.Vector;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Enumeration;import java.lang.reflect.Array;import java.lang.reflect.Constructor;import java.lang.reflect.Method;import java.math.BigInteger;public class LDAPExpr { public static final int AND = 0; public static final int OR = 1; public static final int NOT = 2; public static final int EQ = 4; public static final int LE = 8; public static final int GE = 16; public static final int APPROX = 32; public static final int COMPLEX = AND | OR | NOT; public static final int SIMPLE = EQ | LE | GE | APPROX; private static final char WILDCARD = 65535; private static final String WILDCARD_STRING = new String(new char [] { WILDCARD }); private static final String NULL = "Null query"; private static final String GARBAGE = "Trailing garbage"; private static final String EOS = "Unexpected end of query"; private static final String MALFORMED = "Malformed query"; private static final String EMPTY = "Empty list"; private static final String SUBEXPR = "No subexpression"; private static final String OPERATOR = "Undefined operator"; private static Class classBigDecimal; private static Constructor consBigDecimal; private static Method compBigDecimal; private static Class classBigInteger; private static Constructor consBigInteger; private static Method compBigInteger; public int operator; public LDAPExpr[] args; public String attrName; public String attrValue; // If set to non-null, return this in toString() instead // of correct, normalized form. Required to pass some // incorrect R3 tests String bug = null; public LDAPExpr(String filter) throws InvalidSyntaxException { if(Framework.R3_TESTCOMPLIANT) { // Workaround for bug in R3 test suite which incorrectly thinks // spaces inside of names are legal // fix by saving the "incorrect but expected" filter string // and return that in toString() String zz = " \n(& ( \tn ame = TestService1 ) ( ma ne = ServiceTest1 ) ) \r "; String zz2 = " \n(& ( \tname = TestService1 ) ( mane = ServiceTest1 ) ) \r "; String zz3 = "(&(n ame= TestService1 )(ma ne= ServiceTest1 ))"; if(filter.equals(zz)) { System.out.println("*** Gah! This string is incorrectly expected to parse by the R3 test case:\n" + zz); filter = zz2; bug = zz3; } // The UPnP reference implementation uses // Filter.toString().indexOf("UPnP....") // to look for properties. Since the filter is // normalized to lower case, indexOf never matches // and the UPnP event mechanism fails. // Fix by saving the original filter string // and return that in toString() if(-1 != filter.indexOf("UPnP.device.") || -1 != filter.indexOf("UPnP.service.")) { System.out.println("UPnP: saving original filter case: " + filter); bug = filter; } } ParseState ps = new ParseState(filter); LDAPExpr expr = null; try { expr = parseExpr(ps); } catch (StringIndexOutOfBoundsException e) { ps.error(EOS); } if (ps.rest().trim().length() != 0) ps.error(GARBAGE + " '" + ps.rest() + "'"); operator = expr.operator; args = expr.args; attrName = expr.attrName; attrValue = expr.attrValue; } private LDAPExpr(int operator, LDAPExpr[] args) { this.operator = operator; this.args = args; this.attrName = null; this.attrValue = null; } private LDAPExpr(int operator, String attrName, String attrValue) { this.operator = operator; this.args = null; this.attrName = attrName; this.attrValue = attrValue; } /** * Checks if this LDAP expression is "simple". The definition of * a simple filter is: * <ul> * <li><code>(<it>name</it>=<it>value</it>)</code> is simple if * <it>name</it> is a member of the provided <code>keywords</code>, * and <it>value</it> does not contain a wildcard character;</li> * <li><code>(| EXPR+ )</code> is simple if all <code>EXPR</code> * expressions are simple;</li> * <li>No other expressions are simple.</li> * </ul> * If the filter is found to be simple, the <code>cache</code> is * filled with mappings from the provided keywords to lists * of attribute values. The keyword-value-pairs are the ones that * satisfy this expression, for the given keywords. * * @param keywords The keywords to look for. * @param cache An array (indexed by the keyword indexes) of lists to * fill in with values saturating this expression. * @return <code>true</code> if this expression is simple, * <code>false</code> otherwise. */ public boolean isSimple(List keywords, List[] cache) { if (operator == EQ) { int index; if ((index = keywords.indexOf(attrName)) >= 0 && attrValue.indexOf(WILDCARD) < 0) { if (cache[index] == null) { cache[index] = new ArrayList(); } cache[index].add(attrValue); return true; } } else if (operator == OR) { for (int i = 0; i < args.length; i++) { if (!args[i].isSimple(keywords, cache)) return false; } return true; } return false; } public static boolean query(String filter, Dictionary pd) throws InvalidSyntaxException { return new LDAPExpr(filter).evaluate(pd); } /** * Evaluate this LDAP filter. */ public boolean evaluate(Dictionary p) { if ((operator & SIMPLE) != 0) { return compare(p.get(attrName), operator, attrValue); } else { // (operator & COMPLEX) != 0 switch (operator) { case AND: for (int i = 0; i < args.length; i++) { if (!args[i].evaluate(p)) return false; } return true; case OR: for (int i = 0; i < args.length; i++) { if (args[i].evaluate(p)) return true; } return false; case NOT: return !args[0].evaluate(p); default: return false; // Cannot happen } } } /**** Private methods ****/ protected boolean compare(Object obj, int op, String s) { if (obj == null) return false; if (op == EQ && s.equals(WILDCARD_STRING)) return true; try { if (obj instanceof String) { return compareString((String)obj, op, s); } else if (obj instanceof Character) { return compareString(obj.toString(), op, s); } else if (obj instanceof Boolean) { if (op==LE || op==GE) return false; return ((Boolean)obj).equals(new Boolean(s)); } else if (obj instanceof Number) { if (obj instanceof Byte) { switch(op) { case LE: return ((Byte)obj).byteValue() <= Byte.parseByte(s); case GE: return ((Byte)obj).byteValue() >= Byte.parseByte(s); default: /*APPROX and EQ*/ return (new Byte(s)).equals(obj); } } else if (obj instanceof Integer) { switch(op) { case LE: return ((Integer)obj).intValue() <= Integer.parseInt(s); case GE: return ((Integer)obj).intValue() >= Integer.parseInt(s); default: /*APPROX and EQ*/ return (new Integer(s)).equals(obj); } } else if (obj instanceof Short) { switch(op) { case LE: return ((Short)obj).shortValue() <= Short.parseShort(s); case GE: return ((Short)obj).shortValue() >= Short.parseShort(s); default: /*APPROX and EQ*/ return (new Short(s)).equals(obj); } } else if (obj instanceof Long) { switch(op) { case LE: return ((Long)obj).longValue() <= Long.parseLong(s); case GE: return ((Long)obj).longValue() >= Long.parseLong(s); default: /*APPROX and EQ*/ return (new Long(s)).equals(obj); } } else if (obj instanceof Float) { switch(op) { case LE: return ((Float)obj).floatValue() <= (new Float(s)).floatValue(); case GE: return ((Float)obj).floatValue() >= (new Float(s)).floatValue(); default: /*APPROX and EQ*/ return (new Float(s)).equals(obj); } } else if (obj instanceof Double) { switch(op) { case LE: return ((Double)obj).doubleValue() <= (new Double(s)).doubleValue(); case GE: return ((Double)obj).doubleValue() >= (new Double(s)).doubleValue(); default: /*APPROX and EQ*/ return (new Double(s)).equals(obj); } } else if (classBigInteger != null && classBigInteger.isInstance(obj)) { Object n = consBigInteger.newInstance(new Object [] { s }); int c = ((Integer)compBigInteger.invoke(obj, new Object [] { n })).intValue(); switch(op) { case LE: return c <= 0; case GE: return c >= 0; default: /*APPROX and EQ*/ return c == 0; } } else if (classBigDecimal != null && classBigDecimal.isInstance(obj)) { Object n = consBigDecimal.newInstance(new Object [] { s }); int c = ((Integer)compBigDecimal.invoke(obj, new Object [] { n })).intValue(); switch(op) { case LE: return c <= 0; case GE: return c >= 0; default: /*APPROX and EQ*/ return c == 0; } } } else if (obj instanceof Vector) { for (Enumeration e=((Vector)obj).elements(); e.hasMoreElements();) if (compare(e.nextElement(), op, s)) return true; } else if (obj.getClass().isArray()) { int len = Array.getLength(obj);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -