1 26 27 package com.opensugar.cube.ldap; 28 29 import org.osgi.framework.InvalidSyntaxException; 30 31 import java.util.Vector ; 32 33 public abstract class Filter { 34 35 protected static final String AND = "&"; 36 protected static final String OR = "|"; 37 protected static final String NOT = "!"; 38 39 protected static final String EQUALS = "="; 40 protected static final String APPROX = "~="; 41 protected static final String GREATER = ">="; 42 protected static final String LESS = "<="; 43 44 private static final char ESCAPE_CHAR = '\\'; 45 46 public static Clause parse( String filter, boolean keysCaseSensitive ) throws InvalidSyntaxException { 47 try { 48 return parseFilter( filter, keysCaseSensitive, false ); 49 } 50 catch ( InvalidSyntaxException e ) { 51 throw new InvalidSyntaxException( e.getMessage(), filter ); 52 } 53 } 54 55 private static Clause parseFilter( String filter, boolean keysCaseSensitive, boolean not ) throws InvalidSyntaxException { 56 if ( filter == null || filter.trim().length() == 0 ) { 57 if ( !not ) { 58 return new NullClause(); 59 } 60 else { 61 throw new InvalidSyntaxException( "Not operator used on an empty filter", filter ); 62 } 63 } 64 65 filter = filter.trim(); 66 if ( filter.startsWith( "(" ) && filter.endsWith( ")" ) ) { 67 Clause clause = parseFilterComp( filter.substring( 1, filter.length() - 1 ), keysCaseSensitive ); 68 if ( not ) { 69 clause = new NotClause( clause ); 70 } 71 return clause; 72 } 73 throw new InvalidSyntaxException( "Missing opening or closing bracket on filter", filter ); 74 } 75 76 private static Clause parseFilterComp( String filterComp, boolean keysCaseSensitive ) throws InvalidSyntaxException { 77 while ( Character.isWhitespace( filterComp.charAt( 0 ) ) ) { 80 filterComp = filterComp.substring( 1 ); 81 } 82 83 if ( filterComp.startsWith( AND ) ) { 84 return parseFilterList( filterComp.substring( 1, filterComp.length() ).trim(), AND, keysCaseSensitive ); 85 } 86 else if ( filterComp.startsWith( OR ) ) { 87 return parseFilterList( filterComp.substring( 1, filterComp.length() ).trim(), OR, keysCaseSensitive ); 88 } 89 else if ( filterComp.startsWith( NOT ) ) { 90 return parseFilter( filterComp.substring( 1, filterComp.length() ).trim(), keysCaseSensitive, true ); 91 } 92 else { 93 return parseItem( filterComp, keysCaseSensitive ); 94 } 95 } 96 97 private static Clause parseFilterList( String filterList, String op, boolean keysCaseSensitive ) throws InvalidSyntaxException { 98 Clause[] clauses = parseFilterList( filterList, keysCaseSensitive ); 99 100 if ( op.equals( AND ) ) { 101 return new SuperClauseAND( clauses ); 102 } 103 else if ( op.equals( OR ) ) { 104 return new SuperClauseOR( clauses ); 105 } 106 else { 107 throw new InvalidSyntaxException( "Invalid boolean operator on filter list", null ); 108 } 109 } 110 111 private static Clause parseItem( String s, boolean keysCaseSensitive ) throws InvalidSyntaxException { 112 int n1 = s.indexOf( EQUALS ); 113 int n2 = s.indexOf( APPROX ); 114 int n3 = s.indexOf( GREATER ); 115 int n4 = s.indexOf( LESS ); 116 if ( n1 == -1 ) { 117 n1 = Integer.MAX_VALUE; 118 } 119 if ( n2 == -1 ) { 120 n2 = Integer.MAX_VALUE; 121 } 122 if ( n3 == -1 ) { 123 n3 = Integer.MAX_VALUE; 124 } 125 if ( n4 == -1 ) { 126 n4 = Integer.MAX_VALUE; 127 } 128 129 String filterType; 130 int n, m; 131 if ( n1 < n2 && n1 < n3 && n1 < n4 ) { 132 filterType = EQUALS; 133 n = n1; 134 m = n + 1; 135 } 136 else if ( n2 < n3 && n2 < n4 ) { 137 filterType = APPROX; 138 n = n2; 139 m = n + 2; 140 } 141 else if ( n3 < n4 ) { 142 filterType = GREATER; 143 n = n3; 144 m = n + 2; 145 } 146 else { 147 filterType = LESS; 148 n = n4; 149 m = n + 2; 150 } 151 152 if ( n > s.length() || m > s.length() ) { 153 throw new InvalidSyntaxException( "No filter type found in filter comp", null ); 154 } 155 156 return createClause( filterType, s.substring( 0, n ), s.substring( m, s.length() ), keysCaseSensitive ); 157 } 158 159 private static Clause[] parseFilterList( String filterList, boolean keysCaseSensitive ) throws InvalidSyntaxException { 160 filterList = filterList.trim(); 161 162 if ( filterList.length() == 0 ) { 163 throw new InvalidSyntaxException( "Empty filter list", null ); 164 } 165 Vector v = new Vector (); 166 String filter; 167 while ( filterList.length() > 0 ) { 168 filter = extractFirstFilter( filterList ); 169 v.addElement( parseFilter( filter, keysCaseSensitive, false ) ); 170 filterList = filterList.substring( filter.length(), filterList.length() ).trim(); 171 } 172 173 if ( v.size() < 2 ) { 174 throw new InvalidSyntaxException( "Filter list with a single filter", null ); 175 } 176 177 Clause[] clauses = new Clause[ v.size() ]; 178 for ( int i = 0; i < v.size(); i++ ) { 179 clauses[ i ] = (Clause)v.elementAt( i ); 180 } 181 return clauses; 182 } 183 184 private static String extractFirstFilter( String filterList ) throws InvalidSyntaxException { 185 filterList = filterList.trim(); 186 187 if ( filterList.startsWith( "(" ) ) { 188 int n = filterList.indexOf( ')' ); 189 if ( n == -1 ) { 190 throw new InvalidSyntaxException( "Missing closing bracket", null ); 191 } 192 return filterList.substring( 0, n + 1 ); 193 } 194 throw new InvalidSyntaxException( "Missing opening bracket", null ); 195 } 196 197 private static Clause createClause( String filterType, String attr, String value, boolean keysCaseSensitive ) throws InvalidSyntaxException { 198 attr = attr.trim(); 199 200 if ( getIndicesOfNonEscapedChar( attr, '(' ).length > 0 || 202 getIndicesOfNonEscapedChar( attr, ')' ).length > 0 || 203 getIndicesOfNonEscapedChar( attr, '<' ).length > 0 || 204 getIndicesOfNonEscapedChar( attr, '>' ).length > 0 || 205 getIndicesOfNonEscapedChar( attr, '~' ).length > 0 || 206 getIndicesOfNonEscapedChar( attr, '=' ).length > 0 ) { 207 throw new InvalidSyntaxException( "Special character not escaped (in attr)", null ); 208 } 209 if ( getIndicesOfNonEscapedChar( value, '(' ).length > 0 || 211 getIndicesOfNonEscapedChar( value, ')' ).length > 0 ) { 212 throw new InvalidSyntaxException( "Special character not escaped (in value)", null ); 213 } 214 if ( !filterType.equals( EQUALS ) && 217 getIndicesOfNonEscapedChar( value, SubstringClause.WILDCARD ).length > 0 ) { 218 throw new InvalidSyntaxException( "Special character not escaped (in value with equal filter)", null ); 219 } 220 221 String valueNoEscapeChars = removeEscapeChars( value ); 222 try { 223 if ( filterType.equals( EQUALS ) ) { 224 if ( value.equals( "" + SubstringClause.WILDCARD ) ) { 225 return new PresenceClause( attr, keysCaseSensitive ); 226 } 227 else if ( getIndicesOfNonEscapedChar( value, SubstringClause.WILDCARD ).length > 0 ) { 228 return new SubstringClause( attr, valueNoEscapeChars, keysCaseSensitive ); 229 } 230 return new EqualsClause( attr, valueNoEscapeChars, keysCaseSensitive ); 231 } 232 else if ( filterType.equals( APPROX ) ) { 233 return new ApproxClause( attr, valueNoEscapeChars, keysCaseSensitive ); 234 } 235 else if ( filterType.equals( GREATER ) ) { 236 return new GreaterThanClause( attr, valueNoEscapeChars, keysCaseSensitive ); 237 } 238 else if ( filterType.equals( LESS ) ) { 239 return new LessThanClause( attr, valueNoEscapeChars, keysCaseSensitive ); 240 } 241 else { 242 throw new InvalidSyntaxException( "Invalid filter type", null ); 243 } 244 } 245 catch( IllegalArgumentException e ) { 246 throw new InvalidSyntaxException( e.getMessage(), null ); 247 } 248 } 249 250 private static int[] getIndicesOfNonEscapedChar( String s, char c ) { 251 int n = -1; 252 Vector v = new Vector (); 253 while ( ( n = s.indexOf( c, n + 1 ) ) != -1 ) { 254 if ( n == 0 || s.charAt( n - 1 ) != ESCAPE_CHAR ) { 255 v.addElement( new Integer ( n ) ); 256 } 257 } 258 int[] ret = new int[ v.size() ]; 259 for ( int i = 0; i < v.size(); i++ ) { 260 ret[ i ] = ( (Integer )v.elementAt( i ) ).intValue(); 261 } 262 return ret; 263 } 264 265 private static String removeEscapeChars( String s ) { 266 s = removeEscapeChar( s, SubstringClause.WILDCARD ); 267 s = removeEscapeChar( s, '(' ); 268 return removeEscapeChar( s, ')' ); 269 } 270 271 private static String removeEscapeChar( String s, char escapedChar ) { 272 StringBuffer sb = new StringBuffer (); 273 int n = 0; 274 int m; 275 while ( ( m = s.indexOf( "" + ESCAPE_CHAR + escapedChar, n ) ) != -1 ) { 276 sb.append( s.substring( n, m ) + escapedChar ); 277 n = m + 2; 278 } 279 if ( n < s.length() ) { 280 sb.append( s.substring( n, s.length() ) ); 281 } 282 return sb.toString(); 283 } 284 285 } 286 | Popular Tags |