KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > framework > internal > core > FilterImpl


1 /*******************************************************************************
2  * Copyright (c) 2003, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.osgi.framework.internal.core;
13
14 import java.lang.reflect.Constructor JavaDoc;
15 import java.lang.reflect.InvocationTargetException JavaDoc;
16 import java.security.AccessController JavaDoc;
17 import java.security.PrivilegedAction JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.Collection JavaDoc;
20 import java.util.Dictionary JavaDoc;
21 import java.util.Iterator JavaDoc;
22
23 import org.eclipse.osgi.framework.debug.Debug;
24 import org.eclipse.osgi.framework.util.Headers;
25 import org.eclipse.osgi.util.NLS;
26 import org.osgi.framework.Filter;
27 import org.osgi.framework.InvalidSyntaxException;
28
29 /**
30  * RFC 1960-based Filter. Filter objects can be created by calling
31  * the constructor with the desired filter string.
32  * A Filter object can be called numerous times to determine if the
33  * match argument matches the filter string that was used to create the Filter
34  * object.
35  *
36  * <p>The syntax of a filter string is the string representation
37  * of LDAP search filters as defined in RFC 1960:
38  * <i>A String Representation of LDAP Search Filters</i> (available at
39  * http://www.ietf.org/rfc/rfc1960.txt).
40  * It should be noted that RFC 2254:
41  * <i>A String Representation of LDAP Search Filters</i>
42  * (available at http://www.ietf.org/rfc/rfc2254.txt) supersedes
43  * RFC 1960 but only adds extensible matching and is not applicable for this
44  * API.
45  *
46  * <p>The string representation of an LDAP search filter is defined by the
47  * following grammar. It uses a prefix format.
48  * <pre>
49  * &lt;filter&gt; ::= '(' &lt;filtercomp&gt; ')'
50  * &lt;filtercomp&gt; ::= &lt;and&gt; | &lt;or&gt; | &lt;not&gt; | &lt;item&gt;
51  * &lt;and&gt; ::= '&' &lt;filterlist&gt;
52  * &lt;or&gt; ::= '|' &lt;filterlist&gt;
53  * &lt;not&gt; ::= '!' &lt;filter&gt;
54  * &lt;filterlist&gt; ::= &lt;filter&gt; | &lt;filter&gt; &lt;filterlist&gt;
55  * &lt;item&gt; ::= &lt;simple&gt; | &lt;present&gt; | &lt;substring&gt;
56  * &lt;simple&gt; ::= &lt;attr&gt; &lt;filtertype&gt; &lt;value&gt;
57  * &lt;filtertype&gt; ::= &lt;equal&gt; | &lt;approx&gt; | &lt;greater&gt; | &lt;less&gt;
58  * &lt;equal&gt; ::= '='
59  * &lt;approx&gt; ::= '~='
60  * &lt;greater&gt; ::= '&gt;='
61  * &lt;less&gt; ::= '&lt;='
62  * &lt;present&gt; ::= &lt;attr&gt; '=*'
63  * &lt;substring&gt; ::= &lt;attr&gt; '=' &lt;initial&gt; &lt;any&gt; &lt;final&gt;
64  * &lt;initial&gt; ::= NULL | &lt;value&gt;
65  * &lt;any&gt; ::= '*' &lt;starval&gt;
66  * &lt;starval&gt; ::= NULL | &lt;value&gt; '*' &lt;starval&gt;
67  * &lt;final&gt; ::= NULL | &lt;value&gt;
68  * </pre>
69  *
70  * <code>&lt;attr&gt;</code> is a string representing an attribute, or
71  * key, in the properties objects of the registered services.
72  * Attribute names are not case sensitive;
73  * that is cn and CN both refer to the same attribute.
74  * <code>&lt;value&gt;</code> is a string representing the value, or part of
75  * one, of a key in the properties objects of the registered services.
76  * If a <code>&lt;value&gt;</code> must
77  * contain one of the characters '<code>*</code>' or '<code>(</code>'
78  * or '<code>)</code>', these characters
79  * should be escaped by preceding them with the backslash '<code>\</code>'
80  * character.
81  * Note that although both the <code>&lt;substring&gt;</code> and
82  * <code>&lt;present&gt;</code> productions can
83  * produce the <code>'attr=*'</code> construct, this construct is used only to
84  * denote a presence filter.
85  *
86  * <p>Examples of LDAP filters are:
87  *
88  * <pre>
89  * &quot;(cn=Babs Jensen)&quot;
90  * &quot;(!(cn=Tim Howes))&quot;
91  * &quot;(&(&quot; + Constants.OBJECTCLASS + &quot;=Person)(|(sn=Jensen)(cn=Babs J*)))&quot;
92  * &quot;(o=univ*of*mich*)&quot;
93  * </pre>
94  *
95  * <p>The approximate match (<code>~=</code>) is implementation specific but
96  * should at least ignore case and white space differences. Optional are
97  * codes like soundex or other smart "closeness" comparisons.
98  *
99  * <p>Comparison of values is not straightforward. Strings
100  * are compared differently than numbers and it is
101  * possible for a key to have multiple values. Note that
102  * that keys in the match argument must always be strings.
103  * The comparison is defined by the object type of the key's
104  * value. The following rules apply for comparison:
105  *
106  * <blockquote>
107  * <TABLE BORDER=0>
108  * <TR><TD><b>Property Value Type </b></TD><TD><b>Comparison Type</b></TD></TR>
109  * <TR><TD>String </TD><TD>String comparison</TD></TR>
110  * <TR valign=top><TD>Integer, Long, Float, Double, Byte, Short, BigInteger, BigDecimal </TD><TD>numerical comparison</TD></TR>
111  * <TR><TD>Character </TD><TD>character comparison</TD></TR>
112  * <TR><TD>Boolean </TD><TD>equality comparisons only</TD></TR>
113  * <TR><TD>[] (array)</TD><TD>recursively applied to values </TD></TR>
114  * <TR><TD>Vector</TD><TD>recursively applied to elements </TD></TR>
115  * </TABLE>
116  * Note: arrays of primitives are also supported.
117  * </blockquote>
118  *
119  * A filter matches a key that has multiple values if it
120  * matches at least one of those values. For example,
121  * <pre>
122  * Dictionary d = new Hashtable();
123  * d.put( "cn", new String[] { "a", "b", "c" } );
124  * </pre>
125  * d will match <code>(cn=a)</code> and also <code>(cn=b)</code>
126  *
127  * <p>A filter component that references a key having an unrecognizable
128  * data type will evaluate to <code>false</code> .
129  */

130
131 public class FilterImpl implements Filter /* since Framework 1.1 */{
132     /* public methods in org.osgi.framework.Filter */
133
134     /**
135      * Constructs a {@link FilterImpl} object. This filter object may be used
136      * to match a {@link ServiceReferenceImpl} or a Dictionary.
137      *
138      * <p> If the filter cannot be parsed, an {@link InvalidSyntaxException}
139      * will be thrown with a human readable message where the
140      * filter became unparsable.
141      *
142      * @param filter the filter string.
143      * @exception InvalidSyntaxException If the filter parameter contains
144      * an invalid filter string that cannot be parsed.
145      */

146     public FilterImpl(String JavaDoc filter) throws InvalidSyntaxException {
147         topLevel = true;
148         new Parser(filter).parse(this);
149     }
150
151     /**
152      * Filter using a service's properties.
153      * The Filter is executed using the referenced service's
154      * properties.
155      *
156      * @param reference the reference to the service whose
157      * properties are used in the match.
158      * @return <code>true</code> if the service's properties match this filter;
159      * <code>false</code> otherwise.
160      */

161     public boolean match(org.osgi.framework.ServiceReference reference) {
162         return match0(((ServiceReferenceImpl) reference).registration.properties);
163     }
164
165     /**
166      * Filter using a Dictionary.
167      * The Filter is executed using the Dictionary's keys.
168      *
169      * @param dictionary the dictionary whose keys are used in the match.
170      * @return <code>true</code> if the Dictionary's keys match this filter;
171      * <code>false</code> otherwise.
172      */

173     public boolean match(Dictionary JavaDoc dictionary) {
174         if (dictionary != null) {
175             dictionary = new Headers(dictionary);
176         }
177
178         return match0(dictionary);
179     }
180
181     /**
182      * Filter with case sensitivity using a <tt>Dictionary</tt> object. The
183      * Filter is executed using the <tt>Dictionary</tt> object's keys and
184      * values. The keys are case sensitivley matched with the filter.
185      *
186      * @param dictionary The <tt>Dictionary</tt> object whose keys are used in
187      * the match.
188      *
189      * @return <tt>true</tt> if the <tt>Dictionary</tt> object's keys and
190      * values match this filter; <tt>false</tt> otherwise.
191      *
192      * @since 1.3
193      */

194     public boolean matchCase(Dictionary JavaDoc dictionary) {
195         return match0(dictionary);
196     }
197
198     /**
199      * Returns this Filter object's filter string.
200      * The filter string is normalized by removing
201      * whitespace which does not affect the meaning of the filter.
202      *
203      * @return filter string.
204      */

205     public String JavaDoc toString() {
206         if (this.filter == null) {
207             StringBuffer JavaDoc filter = new StringBuffer JavaDoc();
208             filter.append('(');
209
210             switch (operation) {
211                 case AND :
212                     {
213                         filter.append('&');
214
215                         FilterImpl[] filters = (FilterImpl[]) value;
216                         int size = filters.length;
217
218                         for (int i = 0; i < size; i++) {
219                             filter.append(filters[i].toString());
220                         }
221
222                         break;
223                     }
224
225                 case OR :
226                     {
227                         filter.append('|');
228
229                         FilterImpl[] filters = (FilterImpl[]) value;
230                         int size = filters.length;
231
232                         for (int i = 0; i < size; i++) {
233                             filter.append(filters[i].toString());
234                         }
235
236                         break;
237                     }
238
239                 case NOT :
240                     {
241                         filter.append('!');
242                         filter.append(value.toString());
243
244                         break;
245                     }
246
247                 case SUBSTRING :
248                     {
249                         filter.append(attr);
250                         filter.append('=');
251
252                         String JavaDoc[] substrings = (String JavaDoc[]) value;
253
254                         int size = substrings.length;
255
256                         for (int i = 0; i < size; i++) {
257                             String JavaDoc substr = substrings[i];
258
259                             if (substr == null) /* * */{
260                                 filter.append('*');
261                             } else /* xxx */{
262                                 filter.append(encodeValue(substr));
263                             }
264                         }
265
266                         break;
267                     }
268                 case EQUAL :
269                     {
270                         filter.append(attr);
271                         filter.append('=');
272                         filter.append(encodeValue(value.toString()));
273
274                         break;
275                     }
276                 case GREATER :
277                     {
278                         filter.append(attr);
279                         filter.append(">="); //$NON-NLS-1$
280
filter.append(encodeValue(value.toString()));
281
282                         break;
283                     }
284                 case LESS :
285                     {
286                         filter.append(attr);
287                         filter.append("<="); //$NON-NLS-1$
288
filter.append(encodeValue(value.toString()));
289
290                         break;
291                     }
292                 case APPROX :
293                     {
294                         filter.append(attr);
295                         filter.append("~="); //$NON-NLS-1$
296
filter.append(encodeValue(approxString(value.toString())));
297
298                         break;
299                     }
300
301                 case PRESENT :
302                     {
303                         filter.append(attr);
304                         filter.append("=*"); //$NON-NLS-1$
305

306                         break;
307                     }
308             }
309
310             filter.append(')');
311
312             if (topLevel) /* only hold onto String object at toplevel */{
313                 this.filter = filter.toString();
314             } else {
315                 return filter.toString();
316             }
317         }
318
319         return this.filter;
320     }
321
322     /**
323      * Compares this Filter object to another object.
324      *
325      * @param obj the object to compare.
326      * @return If the other object is a Filter object, then
327      * returns <code>this.toString().equals(obj.toString())</code>,
328      * otherwise <code>false</code>.
329      */

330     public boolean equals(Object JavaDoc obj) {
331         if (obj == this) {
332             return true;
333         }
334
335         if (!(obj instanceof FilterImpl)) {
336             return false;
337         }
338
339         return this.toString().equals(obj.toString());
340     }
341
342     /**
343      * Returns the hashCode for this Filter object.
344      *
345      * @return The hashCode of the filter string, <i>i.e.</i>
346      * <code>this.toString().hashCode()</code>.
347      */

348     public int hashCode() {
349         return this.toString().hashCode();
350     }
351
352     /* Protected fields and methods for the Filter implementation */
353
354     /** filter operation */
355     protected int operation;
356     protected static final int EQUAL = 1;
357     protected static final int APPROX = 2;
358     protected static final int GREATER = 3;
359     protected static final int LESS = 4;
360     protected static final int PRESENT = 5;
361     protected static final int SUBSTRING = 6;
362     protected static final int AND = 7;
363     protected static final int OR = 8;
364     protected static final int NOT = 9;
365
366     /** filter attribute or null if operation AND, OR or NOT */
367     protected String JavaDoc attr;
368     /** filter operands */
369     protected Object JavaDoc value;
370
371     /* normalized filter string for topLevel Filter object */
372     protected String JavaDoc filter;
373
374     /* true if root Filter object */
375     protected boolean topLevel;
376
377     protected FilterImpl() {
378         topLevel = false;
379     }
380
381     protected void setFilter(int operation, String JavaDoc attr, Object JavaDoc value) {
382         this.operation = operation;
383         this.attr = attr;
384         this.value = value;
385     }
386
387     /**
388      * Filter using a service's properties.
389      * The Filter is executed using the referenced service's
390      * properties.
391      *
392      * @param reference A reference to the service whose
393      * properties are used in the match.
394      * @return If the service's properties match the filter,
395      * return <code>true</code>. Otherwise, return <code>false</code>.
396      */

397     protected boolean match(ServiceReferenceImpl reference) {
398         return match0(reference.registration.properties);
399     }
400
401     /**
402      * Internal match routine.
403      * Dictionary parameter must support case-insensitive get.
404      *
405      * @param properties A dictionary whose
406      * keys are used in the match.
407      * @return If the Dictionary's keys match the filter,
408      * return <code>true</code>. Otherwise, return <code>false</code>.
409      */

410     protected boolean match0(Dictionary JavaDoc properties) {
411         switch (operation) {
412             case AND :
413                 {
414                     FilterImpl[] filters = (FilterImpl[]) value;
415                     int size = filters.length;
416
417                     for (int i = 0; i < size; i++) {
418                         if (!filters[i].match0(properties)) {
419                             return false;
420                         }
421                     }
422
423                     return true;
424                 }
425
426             case OR :
427                 {
428                     FilterImpl[] filters = (FilterImpl[]) value;
429                     int size = filters.length;
430
431                     for (int i = 0; i < size; i++) {
432                         if (filters[i].match0(properties)) {
433                             return true;
434                         }
435                     }
436
437                     return false;
438                 }
439
440             case NOT :
441                 {
442                     FilterImpl filter = (FilterImpl) value;
443
444                     return !filter.match0(properties);
445                 }
446
447             case SUBSTRING :
448             case EQUAL :
449             case GREATER :
450             case LESS :
451             case APPROX :
452                 {
453                     Object JavaDoc prop = (properties == null) ? null : properties.get(attr);
454
455                     return compare(operation, prop, value);
456                 }
457
458             case PRESENT :
459                 {
460                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
461                         Debug.println("PRESENT(" + attr + ")"); //$NON-NLS-1$ //$NON-NLS-2$
462
}
463
464                     Object JavaDoc prop = (properties == null) ? null : properties.get(attr);
465
466                     return prop != null;
467                 }
468         }
469
470         return false;
471     }
472
473     /**
474      * Encode the value string such that '(', '*', ')'
475      * and '\' are escaped.
476      *
477      * @param value unencoded value string.
478      * @return encoded value string.
479      */

480     protected static String JavaDoc encodeValue(String JavaDoc value) {
481         boolean encoded = false;
482         int inlen = value.length();
483         int outlen = inlen << 1; /* inlen * 2 */
484
485         char[] output = new char[outlen];
486         value.getChars(0, inlen, output, inlen);
487
488         int cursor = 0;
489         for (int i = inlen; i < outlen; i++) {
490             char c = output[i];
491
492             switch (c) {
493                 case '(' :
494                 case '*' :
495                 case ')' :
496                 case '\\' :
497                     {
498                         output[cursor] = '\\';
499                         cursor++;
500                         encoded = true;
501
502                         break;
503                     }
504             }
505
506             output[cursor] = c;
507             cursor++;
508         }
509
510         return encoded ? new String JavaDoc(output, 0, cursor) : value;
511     }
512
513     protected boolean compare(int operation, Object JavaDoc value1, Object JavaDoc value2) {
514         if (value1 == null) {
515             if (Debug.DEBUG && Debug.DEBUG_FILTER) {
516                 Debug.println("compare(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
517
}
518
519             return false;
520         }
521
522         if (value1 instanceof String JavaDoc) {
523             return compare_String(operation, (String JavaDoc) value1, value2);
524         }
525
526         Class JavaDoc clazz = value1.getClass();
527
528         if (clazz.isArray()) {
529             Class JavaDoc type = clazz.getComponentType();
530
531             if (type.isPrimitive()) {
532                 return compare_PrimitiveArray(operation, type, value1, value2);
533             } else {
534                 return compare_ObjectArray(operation, (Object JavaDoc[]) value1, value2);
535             }
536         }
537
538         if (value1 instanceof Collection JavaDoc) {
539             return compare_Collection(operation, (Collection JavaDoc) value1, value2);
540         }
541
542         if (value1 instanceof Integer JavaDoc) {
543             return compare_Integer(operation, ((Integer JavaDoc) value1).intValue(), value2);
544         }
545
546         if (value1 instanceof Long JavaDoc) {
547             return compare_Long(operation, ((Long JavaDoc) value1).longValue(), value2);
548         }
549
550         if (value1 instanceof Byte JavaDoc) {
551             return compare_Byte(operation, ((Byte JavaDoc) value1).byteValue(), value2);
552         }
553
554         if (value1 instanceof Short JavaDoc) {
555             return compare_Short(operation, ((Short JavaDoc) value1).shortValue(), value2);
556         }
557
558         if (value1 instanceof Character JavaDoc) {
559             return compare_Character(operation, ((Character JavaDoc) value1).charValue(), value2);
560         }
561
562         if (value1 instanceof Float JavaDoc) {
563             return compare_Float(operation, ((Float JavaDoc) value1).floatValue(), value2);
564         }
565
566         if (value1 instanceof Double JavaDoc) {
567             return compare_Double(operation, ((Double JavaDoc) value1).doubleValue(), value2);
568         }
569
570         if (value1 instanceof Boolean JavaDoc) {
571             return compare_Boolean(operation, ((Boolean JavaDoc) value1).booleanValue(), value2);
572         }
573
574         if (value1 instanceof Comparable JavaDoc) {
575             return compare_Comparable(operation, (Comparable JavaDoc) value1, value2);
576         }
577         
578         return compare_Unknown(operation, value1, value2); // RFC 59
579
}
580
581     protected boolean compare_Collection(int operation, Collection JavaDoc collection, Object JavaDoc value2) {
582         Iterator JavaDoc iterator = collection.iterator();
583
584         while (iterator.hasNext()) {
585             if (compare(operation, iterator.next(), value2)) {
586                 return true;
587             }
588         }
589
590         return false;
591     }
592
593     protected boolean compare_ObjectArray(int operation, Object JavaDoc[] array, Object JavaDoc value2) {
594         int size = array.length;
595
596         for (int i = 0; i < size; i++) {
597             if (compare(operation, array[i], value2)) {
598                 return true;
599             }
600         }
601
602         return false;
603     }
604
605     protected boolean compare_PrimitiveArray(int operation, Class JavaDoc type, Object JavaDoc primarray, Object JavaDoc value2) {
606         if (Integer.TYPE.isAssignableFrom(type)) {
607             int[] array = (int[]) primarray;
608
609             int size = array.length;
610
611             for (int i = 0; i < size; i++) {
612                 if (compare_Integer(operation, array[i], value2)) {
613                     return true;
614                 }
615             }
616
617             return false;
618         }
619
620         if (Long.TYPE.isAssignableFrom(type)) {
621             long[] array = (long[]) primarray;
622
623             int size = array.length;
624
625             for (int i = 0; i < size; i++) {
626                 if (compare_Long(operation, array[i], value2)) {
627                     return true;
628                 }
629             }
630
631             return false;
632         }
633
634         if (Byte.TYPE.isAssignableFrom(type)) {
635             byte[] array = (byte[]) primarray;
636
637             int size = array.length;
638
639             for (int i = 0; i < size; i++) {
640                 if (compare_Byte(operation, array[i], value2)) {
641                     return true;
642                 }
643             }
644
645             return false;
646         }
647
648         if (Short.TYPE.isAssignableFrom(type)) {
649             short[] array = (short[]) primarray;
650
651             int size = array.length;
652
653             for (int i = 0; i < size; i++) {
654                 if (compare_Short(operation, array[i], value2)) {
655                     return true;
656                 }
657             }
658
659             return false;
660         }
661
662         if (Character.TYPE.isAssignableFrom(type)) {
663             char[] array = (char[]) primarray;
664
665             int size = array.length;
666
667             for (int i = 0; i < size; i++) {
668                 if (compare_Character(operation, array[i], value2)) {
669                     return true;
670                 }
671             }
672
673             return false;
674         }
675
676         if (Float.TYPE.isAssignableFrom(type)) {
677             float[] array = (float[]) primarray;
678
679             int size = array.length;
680
681             for (int i = 0; i < size; i++) {
682                 if (compare_Float(operation, array[i], value2)) {
683                     return true;
684                 }
685             }
686
687             return false;
688         }
689
690         if (Double.TYPE.isAssignableFrom(type)) {
691             double[] array = (double[]) primarray;
692
693             int size = array.length;
694
695             for (int i = 0; i < size; i++) {
696                 if (compare_Double(operation, array[i], value2)) {
697                     return true;
698                 }
699             }
700
701             return false;
702         }
703
704         if (Boolean.TYPE.isAssignableFrom(type)) {
705             boolean[] array = (boolean[]) primarray;
706
707             int size = array.length;
708
709             for (int i = 0; i < size; i++) {
710                 if (compare_Boolean(operation, array[i], value2)) {
711                     return true;
712                 }
713             }
714
715             return false;
716         }
717
718         return false;
719     }
720
721     protected boolean compare_String(int operation, String JavaDoc string, Object JavaDoc value2) {
722         switch (operation) {
723             case SUBSTRING :
724                 {
725                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
726                         Debug.println("SUBSTRING(" + string + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
727
}
728         
729                     String JavaDoc[] substrings = (String JavaDoc[]) value2;
730                     int pos = 0;
731         
732                     int size = substrings.length;
733         
734                     for (int i = 0; i < size; i++) {
735                         String JavaDoc substr = substrings[i];
736         
737                         if (i + 1 < size) /* if this is not that last substr */{
738                             if (substr == null) /* * */{
739                                 String JavaDoc substr2 = substrings[i + 1];
740         
741                                 if (substr2 == null) /* ** */
742                                     continue; /* ignore first star */
743                                 /* *xxx */
744                                 if (Debug.DEBUG && Debug.DEBUG_FILTER) {
745                                     Debug.println("indexOf(\"" + substr2 + "\"," + pos + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
746
}
747                                 int index = string.indexOf(substr2, pos);
748                                 if (index == -1) {
749                                     return false;
750                                 }
751         
752                                 pos = index + substr2.length();
753                                 if (i + 2 < size) // if there are more substrings, increment over the string we just matched; otherwise need to do the last substr check
754
i++;
755                             } else /* xxx */{
756                                 int len = substr.length();
757         
758                                 if (Debug.DEBUG && Debug.DEBUG_FILTER) {
759                                     Debug.println("regionMatches(" + pos + ",\"" + substr + "\")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
760
}
761                                 if (string.regionMatches(pos, substr, 0, len)) {
762                                     pos += len;
763                                 } else {
764                                     return false;
765                                 }
766                             }
767                         } else /* last substr */{
768                             if (substr == null) /* * */{
769                                 return true;
770                             } else /* xxx */{
771                                 if (Debug.DEBUG && Debug.DEBUG_FILTER) {
772                                     Debug.println("regionMatches(" + pos + "," + substr + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
773
}
774                                 return string.endsWith(substr);
775                             }
776                         }
777                     }
778         
779                     return true;
780                 }
781             case EQUAL :
782                 {
783                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
784                         Debug.println("EQUAL(" + string + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
785
}
786                     return string.equals(value2);
787                 }
788             case APPROX :
789                 {
790                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
791                         Debug.println("APPROX(" + string + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
792
}
793
794                     string = approxString(string);
795                     String JavaDoc string2 = approxString((String JavaDoc) value2);
796
797                     return string.equalsIgnoreCase(string2);
798                 }
799             case GREATER :
800                 {
801                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
802                         Debug.println("GREATER(" + string + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
803
}
804                     return string.compareTo((String JavaDoc) value2) >= 0;
805                 }
806             case LESS :
807                 {
808                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
809                         Debug.println("LESS(" + string + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
810
}
811                     return string.compareTo((String JavaDoc) value2) <= 0;
812                 }
813         }
814
815         return false;
816     }
817
818     protected boolean compare_Integer(int operation, int intval, Object JavaDoc value2) {
819         int intval2 = Integer.parseInt(((String JavaDoc) value2).trim());
820
821         switch (operation) {
822             case SUBSTRING :
823                 {
824                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
825                         Debug.println("SUBSTRING(" + intval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
826
}
827                     return false;
828                 }
829             case EQUAL :
830                 {
831                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
832                         Debug.println("EQUAL(" + intval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
833
}
834                     return intval == intval2;
835                 }
836             case APPROX :
837                 {
838                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
839                         Debug.println("APPROX(" + intval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
840
}
841                     return intval == intval2;
842                 }
843             case GREATER :
844                 {
845                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
846                         Debug.println("GREATER(" + intval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
847
}
848                     return intval >= intval2;
849                 }
850             case LESS :
851                 {
852                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
853                         Debug.println("LESS(" + intval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
854
}
855                     return intval <= intval2;
856                 }
857         }
858
859         return false;
860     }
861
862     protected boolean compare_Long(int operation, long longval, Object JavaDoc value2) {
863         long longval2 = Long.parseLong(((String JavaDoc) value2).trim());
864
865         switch (operation) {
866             case SUBSTRING :
867                 {
868                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
869                         Debug.println("SUBSTRING(" + longval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
870
}
871                     return false;
872                 }
873             case EQUAL :
874                 {
875                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
876                         Debug.println("EQUAL(" + longval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
877
}
878                     return longval == longval2;
879                 }
880             case APPROX :
881                 {
882                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
883                         Debug.println("APPROX(" + longval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
884
}
885                     return longval == longval2;
886                 }
887             case GREATER :
888                 {
889                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
890                         Debug.println("GREATER(" + longval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
891
}
892                     return longval >= longval2;
893                 }
894             case LESS :
895                 {
896                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
897                         Debug.println("LESS(" + longval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
898
}
899                     return longval <= longval2;
900                 }
901         }
902
903         return false;
904     }
905
906     protected boolean compare_Byte(int operation, byte byteval, Object JavaDoc value2) {
907         byte byteval2 = Byte.parseByte(((String JavaDoc) value2).trim());
908
909         switch (operation) {
910             case SUBSTRING :
911                 {
912                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
913                         Debug.println("SUBSTRING(" + byteval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
914
}
915                     return false;
916                 }
917             case EQUAL :
918                 {
919                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
920                         Debug.println("EQUAL(" + byteval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
921
}
922                     return byteval == byteval2;
923                 }
924             case APPROX :
925                 {
926                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
927                         Debug.println("APPROX(" + byteval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
928
}
929                     return byteval == byteval2;
930                 }
931             case GREATER :
932                 {
933                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
934                         Debug.println("GREATER(" + byteval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
935
}
936                     return byteval >= byteval2;
937                 }
938             case LESS :
939                 {
940                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
941                         Debug.println("LESS(" + byteval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
942
}
943                     return byteval <= byteval2;
944                 }
945         }
946
947         return false;
948     }
949
950     protected boolean compare_Short(int operation, short shortval, Object JavaDoc value2) {
951         short shortval2 = Short.parseShort(((String JavaDoc) value2).trim());
952
953         switch (operation) {
954             case SUBSTRING :
955                 {
956                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
957                         Debug.println("SUBSTRING(" + shortval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
958
}
959                     return false;
960                 }
961             case EQUAL :
962                 {
963                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
964                         Debug.println("EQUAL(" + shortval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
965
}
966                     return shortval == shortval2;
967                 }
968             case APPROX :
969                 {
970                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
971                         Debug.println("APPROX(" + shortval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
972
}
973                     return shortval == shortval2;
974                 }
975             case GREATER :
976                 {
977                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
978                         Debug.println("GREATER(" + shortval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
979
}
980                     return shortval >= shortval2;
981                 }
982             case LESS :
983                 {
984                     if (Debug.DEBUG && Debug.DEBUG_FILTER) {
985                         Debug.println("LESS(" + shortval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
986
}
987                     return shortval <= shortval2;
988                 }
989         }
990
991         return false;
992     }
993
994     protected boolean compare_Character(int operation, char charval, Object JavaDoc value2) {
995         char charval2 = (((String JavaDoc) value2).trim()).charAt(0);
996
997         switch (operation) {
998             case SUBSTRING :
999                 {
1000                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1001                        Debug.println("SUBSTRING(" + charval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1002
}
1003                    return false;
1004                }
1005            case EQUAL :
1006                {
1007                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1008                        Debug.println("EQUAL(" + charval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1009
}
1010                    return charval == charval2;
1011                }
1012            case APPROX :
1013                {
1014                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1015                        Debug.println("APPROX(" + charval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1016
}
1017                    return Character.toLowerCase(charval) == Character.toLowerCase(charval2);
1018                }
1019            case GREATER :
1020                {
1021                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1022                        Debug.println("GREATER(" + charval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1023
}
1024                    return charval >= charval2;
1025                }
1026            case LESS :
1027                {
1028                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1029                        Debug.println("LESS(" + charval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1030
}
1031                    return charval <= charval2;
1032                }
1033        }
1034
1035        return false;
1036    }
1037
1038    protected boolean compare_Boolean(int operation, boolean boolval, Object JavaDoc value2) {
1039        boolean boolval2 = new Boolean JavaDoc(((String JavaDoc) value2).trim()).booleanValue();
1040
1041        switch (operation) {
1042            case SUBSTRING :
1043                {
1044                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1045                        Debug.println("SUBSTRING(" + boolval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1046
}
1047                    return false;
1048                }
1049            case EQUAL :
1050                {
1051                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1052                        Debug.println("EQUAL(" + boolval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1053
}
1054                    return boolval == boolval2;
1055                }
1056            case APPROX :
1057                {
1058                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1059                        Debug.println("APPROX(" + boolval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1060
}
1061                    return boolval == boolval2;
1062                }
1063            case GREATER :
1064                {
1065                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1066                        Debug.println("GREATER(" + boolval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1067
}
1068                    return boolval == boolval2;
1069                }
1070            case LESS :
1071                {
1072                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1073                        Debug.println("LESS(" + boolval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1074
}
1075                    return boolval == boolval2;
1076                }
1077        }
1078
1079        return false;
1080    }
1081
1082    protected boolean compare_Float(int operation, float floatval, Object JavaDoc value2) {
1083        float floatval2 = Float.parseFloat(((String JavaDoc) value2).trim());
1084
1085        switch (operation) {
1086            case SUBSTRING :
1087                {
1088                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1089                        Debug.println("SUBSTRING(" + floatval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1090
}
1091                    return false;
1092                }
1093            case EQUAL :
1094                {
1095                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1096                        Debug.println("EQUAL(" + floatval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1097
}
1098                    return floatval == floatval2;
1099                }
1100            case APPROX :
1101                {
1102                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1103                        Debug.println("APPROX(" + floatval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1104
}
1105                    return floatval == floatval2;
1106                }
1107            case GREATER :
1108                {
1109                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1110                        Debug.println("GREATER(" + floatval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1111
}
1112                    return floatval >= floatval2;
1113                }
1114            case LESS :
1115                {
1116                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1117                        Debug.println("LESS(" + floatval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1118
}
1119                    return floatval <= floatval2;
1120                }
1121        }
1122
1123        return false;
1124    }
1125
1126    protected boolean compare_Double(int operation, double doubleval, Object JavaDoc value2) {
1127        double doubleval2 = Double.parseDouble(((String JavaDoc) value2).trim());
1128
1129        switch (operation) {
1130            case SUBSTRING :
1131                {
1132                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1133                        Debug.println("SUBSTRING(" + doubleval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1134
}
1135                    return false;
1136                }
1137            case EQUAL :
1138                {
1139                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1140                        Debug.println("EQUAL(" + doubleval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1141
}
1142                    return doubleval == doubleval2;
1143                }
1144            case APPROX :
1145                {
1146                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1147                        Debug.println("APPROX(" + doubleval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1148
}
1149                    return doubleval == doubleval2;
1150                }
1151            case GREATER :
1152                {
1153                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1154                        Debug.println("GREATER(" + doubleval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1155
}
1156                    return doubleval >= doubleval2;
1157                }
1158            case LESS :
1159                {
1160                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1161                        Debug.println("LESS(" + doubleval + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1162
}
1163                    return doubleval <= doubleval2;
1164                }
1165        }
1166
1167        return false;
1168    }
1169    
1170    protected static final Class JavaDoc[] constructorType = new Class JavaDoc [] {String JavaDoc.class};
1171
1172    protected boolean compare_Comparable(int operation, Comparable JavaDoc value1, Object JavaDoc value2) {
1173        Constructor JavaDoc constructor;
1174
1175        try {
1176            constructor = value1.getClass().getConstructor(constructorType);
1177        }
1178        catch (NoSuchMethodException JavaDoc e) {
1179            return false;
1180        }
1181        try {
1182            if (!constructor.isAccessible())
1183                AccessController.doPrivileged(new SetAccessibleAction(constructor));
1184            value2 = constructor.newInstance(new Object JavaDoc[] {((String JavaDoc) value2).trim()});
1185        }
1186        catch (IllegalAccessException JavaDoc e) {
1187            return false;
1188        }
1189        catch (InvocationTargetException JavaDoc e) {
1190            return false;
1191        }
1192        catch (InstantiationException JavaDoc e) {
1193            return false;
1194        }
1195
1196        switch (operation) {
1197            case SUBSTRING :
1198                {
1199                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1200                        Debug.println("SUBSTRING(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1201
}
1202                    return false;
1203                }
1204            case EQUAL :
1205                {
1206                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1207                        Debug.println("EQUAL(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1208
}
1209                    return value1.compareTo(value2) == 0;
1210                }
1211            case APPROX :
1212                {
1213                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1214                        Debug.println("APPROX(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1215
}
1216                    return value1.compareTo(value2) == 0;
1217                }
1218            case GREATER :
1219                {
1220                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1221                        Debug.println("GREATER(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1222
}
1223                    return value1.compareTo(value2) >= 0;
1224                }
1225            case LESS :
1226                {
1227                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1228                        Debug.println("LESS(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1229
}
1230                    return value1.compareTo(value2) <= 0;
1231                }
1232        }
1233
1234        return false;
1235    }
1236
1237    protected boolean compare_Unknown(int operation, Object JavaDoc value1, Object JavaDoc value2) { //RFC 59
1238
Constructor JavaDoc constructor;
1239        try {
1240            constructor = value1.getClass().getConstructor(constructorType);
1241        }
1242        catch (NoSuchMethodException JavaDoc e) {
1243            if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1244                Debug.println("Type not supported"); //$NON-NLS-1$
1245
}
1246            return false;
1247        }
1248        try {
1249            if (!constructor.isAccessible())
1250                AccessController.doPrivileged(new SetAccessibleAction(constructor));
1251            value2 = constructor.newInstance(new Object JavaDoc[] {((String JavaDoc) value2).trim()});
1252        }
1253        catch (IllegalAccessException JavaDoc e) {
1254            return false;
1255        }
1256        catch (InvocationTargetException JavaDoc e) {
1257            return false;
1258        }
1259        catch (InstantiationException JavaDoc e) {
1260            return false;
1261        }
1262    
1263        switch (operation) {
1264            case SUBSTRING :
1265                {
1266                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1267                        Debug.println("SUBSTRING(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1268
}
1269                    return false;
1270                }
1271            case EQUAL :
1272                {
1273                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1274                        Debug.println("EQUAL(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1275
}
1276                    return value1.equals(value2);
1277                }
1278            case APPROX :
1279                {
1280                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1281                        Debug.println("APPROX(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1282
}
1283                    return value1.equals(value2);
1284                }
1285            case GREATER :
1286                {
1287                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1288                        Debug.println("GREATER(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1289
}
1290                    return value1.equals(value2);
1291                }
1292            case LESS :
1293                {
1294                    if (Debug.DEBUG && Debug.DEBUG_FILTER) {
1295                        Debug.println("LESS(" + value1 + "," + value2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1296
}
1297                    return value1.equals(value2);
1298                }
1299        }
1300    
1301        return false;
1302    }
1303
1304    /**
1305     * Map a string for an APPROX (~=) comparison.
1306     *
1307     * This implementation removes white spaces.
1308     * This is the minimum implementation allowed by
1309     * the OSGi spec.
1310     *
1311     * @param input Input string.
1312     * @return String ready for APPROX comparison.
1313     */

1314    protected static String JavaDoc approxString(String JavaDoc input) {
1315        boolean changed = false;
1316        char[] output = input.toCharArray();
1317
1318        int length = output.length;
1319
1320        int cursor = 0;
1321        for (int i = 0; i < length; i++) {
1322            char c = output[i];
1323
1324            if (Character.isWhitespace(c)) {
1325                changed = true;
1326                continue;
1327            }
1328
1329            output[cursor] = c;
1330            cursor++;
1331        }
1332
1333        return changed ? new String JavaDoc(output, 0, cursor) : input;
1334    }
1335    
1336    /**
1337     * Returns the leftmost required objectClass value for the filter to evaluate to true.
1338     *
1339     * @return The leftmost required objectClass value or null if none could be determined.
1340     */

1341    public String JavaDoc getRequiredObjectClass() {
1342        // just checking for simple filters here where objectClass is the only attr or it is one attr of a base '&' clause
1343
// (objectClass=org.acme.BrickService) OK
1344
// (&(objectClass=org.acme.BrickService)(|(vendor=IBM)(vendor=SUN))) OK
1345
// (objectClass=org.acme.*) NOT OK
1346
// (|(objectClass=org.acme.BrickService)(objectClass=org.acme.CementService)) NOT OK
1347
// (&(objectClass=org.acme.BrickService)(objectClass=org.acme.CementService)) OK but only the first objectClass is returned
1348
switch (operation) {
1349            case EQUAL :
1350                if (attr.equalsIgnoreCase(org.osgi.framework.Constants.OBJECTCLASS) && (value instanceof String JavaDoc))
1351                    return (String JavaDoc) value;
1352                break;
1353            case AND :
1354                FilterImpl[] clauses = (FilterImpl[]) value;
1355                for (int i = 0; i < clauses.length; i++)
1356                    if (clauses[i].operation == EQUAL) {
1357                        String JavaDoc result = clauses[i].getRequiredObjectClass();
1358                        if (result != null)
1359                            return result;
1360                    }
1361                break;
1362        }
1363        return null;
1364    }
1365
1366    /**
1367     * Returns a objectClass filter string for the specified objectClass.
1368     * @return A filter string for the specified objectClass or null if the specified objectClass is null.
1369     */

1370    public static String JavaDoc getObjectClassFilterString(String JavaDoc objectClass) {
1371        if (objectClass == null)
1372            return null;
1373        return "(" + org.osgi.framework.Constants.OBJECTCLASS + "=" + objectClass + ")"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
1374
}
1375
1376    /**
1377     * Returns all the attributes contained within this filter
1378     * @return all the attributes contained within this filter
1379     */

1380    public String JavaDoc[] getAttributes() {
1381        ArrayList JavaDoc results = new ArrayList JavaDoc();
1382        getAttributesInternal(results);
1383        return (String JavaDoc[]) results.toArray(new String JavaDoc[results.size()]);
1384    }
1385
1386    private void getAttributesInternal(ArrayList JavaDoc results) {
1387        if (value instanceof FilterImpl[]) {
1388            FilterImpl[] children = (FilterImpl[]) value;
1389            for (int i = 0; i < children.length; i++)
1390                children[i].getAttributesInternal(results);
1391            return;
1392        } else if (value instanceof FilterImpl) {
1393            // The NOT operation only has one child filter (bug 188075)
1394
((FilterImpl) value).getAttributesInternal(results);
1395            return;
1396        }
1397        if (attr != null)
1398            results.add(attr);
1399    }
1400
1401    /**
1402     * Parser class for OSGi filter strings. This class parses
1403     * the complete filter string and builds a tree of Filter
1404     * objects rooted at the parent.
1405     */

1406    static class Parser {
1407        protected String JavaDoc filterstring;
1408        protected char[] filter;
1409        protected int pos;
1410
1411        protected Parser(String JavaDoc filterstring) {
1412            this.filterstring = filterstring;
1413            filter = filterstring.toCharArray();
1414            pos = 0;
1415        }
1416
1417        protected void parse(FilterImpl parent) throws InvalidSyntaxException {
1418            try {
1419                parse_filter(parent);
1420            } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
1421                throw new InvalidSyntaxException(Msg.FILTER_TERMINATED_ABRUBTLY, filterstring);
1422            }
1423
1424            if (pos != filter.length) {
1425                throw new InvalidSyntaxException(NLS.bind(Msg.FILTER_TRAILING_CHARACTERS, String.valueOf(pos)), filterstring);
1426            }
1427        }
1428
1429        protected void parse_filter(FilterImpl parent) throws InvalidSyntaxException {
1430            skipWhiteSpace();
1431
1432            if (filter[pos] != '(') {
1433                throw new InvalidSyntaxException(NLS.bind(Msg.FILTER_MISSING_LEFTPAREN, String.valueOf(pos)), filterstring);
1434            }
1435
1436            pos++;
1437
1438            parse_filtercomp(parent);
1439
1440            skipWhiteSpace();
1441
1442            if (filter[pos] != ')') {
1443                throw new InvalidSyntaxException(NLS.bind(Msg.FILTER_MISSING_RIGHTPAREN, String.valueOf(pos)), filterstring);
1444            }
1445
1446            pos++;
1447
1448            skipWhiteSpace();
1449        }
1450
1451        protected void parse_filtercomp(FilterImpl parent) throws InvalidSyntaxException {
1452            skipWhiteSpace();
1453
1454            char c = filter[pos];
1455
1456            switch (c) {
1457                case '&' :
1458                    {
1459                        pos++;
1460                        parse_and(parent);
1461                        break;
1462                    }
1463                case '|' :
1464                    {
1465                        pos++;
1466                        parse_or(parent);
1467                        break;
1468                    }
1469                case '!' :
1470                    {
1471                        pos++;
1472                        parse_not(parent);
1473                        break;
1474                    }
1475                default :
1476                    {
1477                        parse_item(parent);
1478                        break;
1479                    }
1480            }
1481        }
1482
1483        protected void parse_and(FilterImpl parent) throws InvalidSyntaxException {
1484            skipWhiteSpace();
1485
1486            if (filter[pos] != '(') {
1487                throw new InvalidSyntaxException(NLS.bind(Msg.FILTER_MISSING_LEFTPAREN, String.valueOf(pos)), filterstring);
1488            }
1489
1490            ArrayList JavaDoc operands = new ArrayList JavaDoc(10);
1491
1492            while (filter[pos] == '(') {
1493                FilterImpl child = new FilterImpl();
1494                parse_filter(child);
1495                operands.add(child);
1496            }
1497
1498            int size = operands.size();
1499
1500            FilterImpl[] children = new FilterImpl[size];
1501
1502            operands.toArray(children);
1503
1504            parent.setFilter(FilterImpl.AND, null, children);
1505        }
1506
1507        protected void parse_or(FilterImpl parent) throws InvalidSyntaxException {
1508            skipWhiteSpace();
1509
1510            if (filter[pos] != '(') {
1511                throw new InvalidSyntaxException(NLS.bind(Msg.FILTER_MISSING_LEFTPAREN, String.valueOf(pos)), filterstring);
1512            }
1513
1514            ArrayList JavaDoc operands = new ArrayList JavaDoc(10);
1515
1516            while (filter[pos] == '(') {
1517                FilterImpl child = new FilterImpl();
1518                parse_filter(child);
1519                operands.add(child);
1520            }
1521
1522            int size = operands.size();
1523
1524            FilterImpl[] children = new FilterImpl[size];
1525
1526            operands.toArray(children);
1527
1528            parent.setFilter(FilterImpl.OR, null, children);
1529        }
1530
1531        protected void parse_not(FilterImpl parent) throws InvalidSyntaxException {
1532            skipWhiteSpace();
1533
1534            if (filter[pos] != '(') {
1535                throw new InvalidSyntaxException(NLS.bind(Msg.FILTER_MISSING_LEFTPAREN, String.valueOf(pos)), filterstring);
1536            }
1537
1538            FilterImpl child = new FilterImpl();
1539            parse_filter(child);
1540
1541            parent.setFilter(FilterImpl.NOT, null, child);
1542        }
1543
1544        protected void parse_item(FilterImpl parent) throws InvalidSyntaxException {
1545            String JavaDoc attr = parse_attr();
1546
1547            skipWhiteSpace();
1548
1549            switch (filter[pos]) {
1550                case '~' :
1551                    {
1552                        if (filter[pos + 1] == '=') {
1553                            pos += 2;
1554                            parent.setFilter(FilterImpl.APPROX, attr, parse_value());
1555                            return;
1556                        }
1557                        break;
1558                    }
1559                case '>' :
1560                    {
1561                        if (filter[pos + 1] == '=') {
1562                            pos += 2;
1563                            parent.setFilter(FilterImpl.GREATER, attr, parse_value());
1564                            return;
1565                        }
1566                        break;
1567                    }
1568                case '<' :
1569                    {
1570                        if (filter[pos + 1] == '=') {
1571                            pos += 2;
1572                            parent.setFilter(FilterImpl.LESS, attr, parse_value());
1573                            return;
1574                        }
1575                        break;
1576                    }
1577                case '=' :
1578                    {
1579                        if (filter[pos + 1] == '*') {
1580                            int oldpos = pos;
1581                            pos += 2;
1582                            skipWhiteSpace();
1583                            if (filter[pos] == ')') {
1584                                parent.setFilter(FilterImpl.PRESENT, attr, null);
1585                                return; /* present */
1586                            }
1587                            pos = oldpos;
1588                        }
1589
1590                        pos++;
1591                        Object JavaDoc string = parse_substring();
1592
1593                        if (string instanceof String JavaDoc) {
1594                            parent.setFilter(FilterImpl.EQUAL, attr, string);
1595                        } else {
1596                            parent.setFilter(FilterImpl.SUBSTRING, attr, string);
1597                        }
1598
1599                        return;
1600                    }
1601            }
1602
1603            throw new InvalidSyntaxException(NLS.bind(Msg.FILTER_INVALID_OPERATOR, String.valueOf(pos)), filterstring);
1604        }
1605
1606        protected String JavaDoc parse_attr() throws InvalidSyntaxException {
1607            skipWhiteSpace();
1608
1609            int begin = pos;
1610            int end = pos;
1611
1612            char c = filter[pos];
1613
1614            while ("~<>=()".indexOf(c) == -1) { //$NON-NLS-1$
1615
pos++;
1616
1617                if (!Character.isWhitespace(c)) {
1618                    end = pos;
1619                }
1620
1621                c = filter[pos];
1622            }
1623
1624            int length = end - begin;
1625
1626            if (length == 0) {
1627                throw new InvalidSyntaxException(NLS.bind(Msg.FILTER_MISSING_ATTR, String.valueOf(pos)), filterstring);
1628            }
1629
1630            return new String JavaDoc(filter, begin, length);
1631        }
1632
1633        protected String JavaDoc parse_value() throws InvalidSyntaxException {
1634            StringBuffer JavaDoc sb = new StringBuffer JavaDoc(filter.length - pos);
1635
1636            parseloop: while (true) {
1637                char c = filter[pos];
1638
1639                switch (c) {
1640                    case ')' :
1641                        {
1642                            break parseloop;
1643                        }
1644
1645                    case '(' :
1646                        {
1647                            throw new InvalidSyntaxException(NLS.bind(Msg.FILTER_INVALID_VALUE, String.valueOf(pos)), filterstring);
1648                        }
1649
1650                    case '\\' :
1651                        {
1652                            pos++;
1653                            c = filter[pos];
1654                            /* fall through into default */
1655                        }
1656
1657                    default :
1658                        {
1659                            sb.append(c);
1660                            pos++;
1661                            break;
1662                        }
1663                }
1664            }
1665
1666            if (sb.length() == 0) {
1667                throw new InvalidSyntaxException(NLS.bind(Msg.FILTER_MISSING_VALUE, String.valueOf(pos)), filterstring);
1668            }
1669
1670            return sb.toString();
1671        }
1672
1673        protected Object JavaDoc parse_substring() throws InvalidSyntaxException {
1674            StringBuffer JavaDoc sb = new StringBuffer JavaDoc(filter.length - pos);
1675
1676            ArrayList JavaDoc operands = new ArrayList JavaDoc(10);
1677
1678            parseloop: while (true) {
1679                char c = filter[pos];
1680
1681                switch (c) {
1682                    case ')' :
1683                        {
1684                            if (sb.length() > 0) {
1685                                operands.add(sb.toString());
1686                            }
1687
1688                            break parseloop;
1689                        }
1690
1691                    case '(' :
1692                        {
1693                            throw new InvalidSyntaxException(NLS.bind(Msg.FILTER_INVALID_VALUE, String.valueOf(pos)), filterstring);
1694                        }
1695
1696                    case '*' :
1697                        {
1698                            if (sb.length() > 0) {
1699                                operands.add(sb.toString());
1700                            }
1701
1702                            sb.setLength(0);
1703
1704                            operands.add(null);
1705                            pos++;
1706
1707                            break;
1708                        }
1709
1710                    case '\\' :
1711                        {
1712                            pos++;
1713                            c = filter[pos];
1714                            /* fall through into default */
1715                        }
1716
1717                    default :
1718                        {
1719                            sb.append(c);
1720                            pos++;
1721                            break;
1722                        }
1723                }
1724            }
1725
1726            int size = operands.size();
1727
1728            if (size == 0) {
1729                throw new InvalidSyntaxException(NLS.bind(Msg.FILTER_MISSING_VALUE, String.valueOf(pos)), filterstring);
1730            }
1731
1732            if (size == 1) {
1733                Object JavaDoc single = operands.get(0);
1734
1735                if (single != null) {
1736                    return single;
1737                }
1738            }
1739
1740            String JavaDoc[] strings = new String JavaDoc[size];
1741
1742            operands.toArray(strings);
1743
1744            return strings;
1745        }
1746
1747        protected void skipWhiteSpace() {
1748            int length = filter.length;
1749
1750            while ((pos < length) && Character.isWhitespace(filter[pos])) {
1751                pos++;
1752            }
1753        }
1754    }
1755
1756    static class SetAccessibleAction implements PrivilegedAction JavaDoc {
1757        private Constructor JavaDoc constructor;
1758        public SetAccessibleAction(Constructor JavaDoc constructor) {
1759            this.constructor = constructor;
1760        }
1761        public Object JavaDoc run() {
1762            constructor.setAccessible(true);
1763            return null;
1764        }
1765    }
1766}
1767
Popular Tags