KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > opensugar > cube > ldap > Filter


1 /*
2  * JEFFREE: Java(TM) Embedded Framework FREE
3  * Copyright (C) 1999-2003 - Opensugar
4  *
5  * The contents of this file are subject to the Jeffree Public License,
6  * as defined by the file JEFFREE_LICENSE.TXT
7  *
8  * You may not use this file except in compliance with the License.
9  * You may obtain a copy of the License on the Objectweb web site
10  * (www.objectweb.org).
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
14  * the specific terms governing rights and limitations under the License.
15  *
16  * The Original Code is JEFFREE, including the java package com.opensugar.cube,
17  * released January 1, 2003.
18  *
19  * The Initial Developer of the Original Code is Opensugar.
20  * The Original Code is Copyright Opensugar.
21  * All Rights Reserved.
22  *
23  * Initial developer(s): Pierre Scokaert (Opensugar)
24  * Contributor(s):
25  */

26
27 package com.opensugar.cube.ldap;
28
29 import org.osgi.framework.InvalidSyntaxException;
30
31 import java.util.Vector JavaDoc;
32
33 public abstract class Filter {
34
35    protected static final String JavaDoc AND = "&";
36    protected static final String JavaDoc OR = "|";
37    protected static final String JavaDoc NOT = "!";
38
39    protected static final String JavaDoc EQUALS = "=";
40    protected static final String JavaDoc APPROX = "~=";
41    protected static final String JavaDoc GREATER = ">=";
42    protected static final String JavaDoc LESS = "<=";
43
44    private static final char ESCAPE_CHAR = '\\';
45
46    public static Clause parse( String JavaDoc 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 JavaDoc 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 JavaDoc filterComp, boolean keysCaseSensitive ) throws InvalidSyntaxException {
77       // remove leading spaces - but not trailing spaces which are useful characters
78
// if filterComp is an item
79
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 JavaDoc filterList, String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc v = new Vector JavaDoc();
166       String JavaDoc 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 JavaDoc extractFirstFilter( String JavaDoc 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 JavaDoc filterType, String JavaDoc attr, String JavaDoc value, boolean keysCaseSensitive ) throws InvalidSyntaxException {
198       attr = attr.trim();
199
200       // There should be no unescaped '(', ')', '<', '>' '~' or '=' characters in the attr
201
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       // There should be no unescaped '(' or ')' characters in the value
210
if ( getIndicesOfNonEscapedChar( value, '(' ).length > 0 ||
211            getIndicesOfNonEscapedChar( value, ')' ).length > 0 ) {
212          throw new InvalidSyntaxException( "Special character not escaped (in value)", null );
213       }
214       // There should be no unescaped WILDCARD characters in the value
215
// unless filter is of type EQUALS
216
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 JavaDoc 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 JavaDoc e ) {
246          throw new InvalidSyntaxException( e.getMessage(), null );
247       }
248    }
249
250    private static int[] getIndicesOfNonEscapedChar( String JavaDoc s, char c ) {
251       int n = -1;
252       Vector JavaDoc v = new Vector JavaDoc();
253       while ( ( n = s.indexOf( c, n + 1 ) ) != -1 ) {
254          if ( n == 0 || s.charAt( n - 1 ) != ESCAPE_CHAR ) {
255             v.addElement( new Integer JavaDoc( n ) );
256          }
257       }
258       int[] ret = new int[ v.size() ];
259       for ( int i = 0; i < v.size(); i++ ) {
260          ret[ i ] = ( (Integer JavaDoc)v.elementAt( i ) ).intValue();
261       }
262       return ret;
263    }
264
265    private static String JavaDoc removeEscapeChars( String JavaDoc s ) {
266       s = removeEscapeChar( s, SubstringClause.WILDCARD );
267       s = removeEscapeChar( s, '(' );
268       return removeEscapeChar( s, ')' );
269    }
270
271    private static String JavaDoc removeEscapeChar( String JavaDoc s, char escapedChar ) {
272       StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
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