blob: 1c8e5799a906ceae941f8e6c1de5ff00c7aefa81 [file] [log] [blame]
Richard S. Hall930fecc2005-08-16 18:33:34 +00001/*
2 * Copyright 2005 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
Richard S. Hall5a031592005-08-19 19:53:58 +000017package org.apache.felix.framework;
Richard S. Hall930fecc2005-08-16 18:33:34 +000018
19import java.io.CharArrayReader;
20import java.io.IOException;
21import java.util.*;
22
Richard S. Hall5a031592005-08-19 19:53:58 +000023import org.apache.felix.framework.util.CaseInsensitiveMap;
24import org.apache.felix.framework.util.ldap.*;
Richard S. Hall930fecc2005-08-16 18:33:34 +000025import org.osgi.framework.*;
26
27/**
28 * This class implements an RFC 1960-based filter. The syntax of the
29 * filter string is the string representation of LDAP search filters
30 * as defined in RFC 1960. These filters are used to search for services
31 * and to track services using <tt>ServiceTracker</tt> objects.
32**/
33public class FilterImpl implements Filter
34{
35 private LogWrapper m_logger = null;
36 private String m_toString = null;
37 private Evaluator m_evaluator = null;
38 private SimpleMapper m_mapper = null;
39
40// TODO: FilterImpl needs a logger, this is a hack to get FrameworkUtil to compile.
41 public FilterImpl(String expr) throws InvalidSyntaxException
42 {
43 this(null, expr);
44 }
45
46 /**
47 * Construct a filter for a given filter expression string.
48 * @param expr the filter expression string for the filter.
49 **/
50 public FilterImpl(LogWrapper logger, String expr) throws InvalidSyntaxException
51 {
52 m_logger = logger;
53 if (expr == null)
54 {
55 throw new InvalidSyntaxException("Filter cannot be null", null);
56 }
57
58 if (expr != null)
59 {
60 CharArrayReader car = new CharArrayReader(expr.toCharArray());
61 LdapLexer lexer = new LdapLexer(car);
62 Parser parser = new Parser(lexer);
63 try
64 {
65 if (!parser.start())
66 {
67 throw new InvalidSyntaxException(
68 "Failed to parse LDAP query.", expr);
69 }
70 }
71 catch (ParseException ex)
72 {
73 throw new InvalidSyntaxException(
74 ex.getMessage(), expr);
75 }
76 catch (IOException ex)
77 {
78 throw new InvalidSyntaxException(
79 ex.getMessage(), expr);
80 }
81 m_evaluator = new Evaluator(parser.getProgram());
82 m_mapper = new SimpleMapper();
83 }
84 }
85
86 /**
87 * Compares the <tt>Filter</tt> object to another.
88 * @param o the object to compare this <tt>Filter</tt> against.
89 * @return If the other object is a <tt>Filter</tt> object, it
90 * returns <tt>this.toString().equals(obj.toString())</tt>;
91 * <tt>false</tt> otherwise.
92 **/
93 public boolean equals(Object o)
94 {
95 if (o == null)
96 {
97 return false;
98 }
99 else if (o instanceof Filter)
100 {
101 return toString().equals(o.toString());
102 }
103 return false;
104 }
105
106 /**
107 * Returns the hash code for the <tt>Filter</tt> object.
108 * @return The value <tt>this.toString().hashCode()</tt>.
109 **/
110 public int hashCode()
111 {
112 return toString().hashCode();
113 }
114
115 /**
116 * Filter using a <tt>Dictionary</tt> object. The <tt>Filter</tt>
117 * is executed using the <tt>Dictionary</tt> object's keys and values.
118 * @param dict the <tt>Dictionary</tt> object whose keys and values
119 * are used to determine a match.
120 * @return <tt>true</tt> if the <tt>Dictionary</tt> object's keys
121 * and values match this filter; <tt>false</tt> otherwise.
122 * @throws IllegalArgumentException if the dictionary contains case
123 * variants of the same key name.
124 **/
125 public boolean match(Dictionary dict)
126 throws IllegalArgumentException
127 {
128 try
129 {
130 m_mapper.setSource(dict);
131 return m_evaluator.evaluate(m_mapper);
132 }
133 catch (AttributeNotFoundException ex)
134 {
135 m_logger.log(LogWrapper.LOG_DEBUG, "FilterImpl: " + ex);
136 }
137 catch (EvaluationException ex)
138 {
139 m_logger.log(LogWrapper.LOG_ERROR, "FilterImpl: " + toString(), ex);
140 }
141 return false;
142 }
143
144 /**
145 * Filter using a service's properties. The <tt>Filter</tt>
146 * is executed using the properties of the referenced service.
147 * @param ref A reference to the service whose properties
148 * are used to determine a match.
149 * @return <tt>true</tt> if the service's properties match this
150 * filter; <tt>false</tt> otherwise.
151 **/
152 public boolean match(ServiceReference ref)
153 {
154 try
155 {
156 m_mapper.setSource(ref);
157 return m_evaluator.evaluate(m_mapper);
158 }
159 catch (AttributeNotFoundException ex)
160 {
161 m_logger.log(LogWrapper.LOG_DEBUG, "FilterImpl: " + ex);
162 }
163 catch (EvaluationException ex)
164 {
165 m_logger.log(LogWrapper.LOG_ERROR, "FilterImpl: " + toString(), ex);
166 }
167 return false;
168 }
169
170 public boolean matchCase(Dictionary dictionary)
171 {
172 // TODO: Implement Filter.matchCase()
173 return false;
174 }
175
176 /**
177 * Returns the <tt>Filter</tt> object's filter string.
178 * @return Filter string.
179 **/
180 public String toString()
181 {
182 if (m_toString == null)
183 {
184 m_toString = m_evaluator.toStringInfix();
185 }
186 return m_toString;
187 }
188
189 static class SimpleMapper implements Mapper
190 {
191 private ServiceReference m_ref = null;
192 private Map m_map = null;
193
194 public void setSource(ServiceReference ref)
195 {
196 m_ref = ref;
197 m_map = null;
198 }
199
200 public void setSource(Dictionary dict)
201 {
202 if (m_map == null)
203 {
204 m_map = new CaseInsensitiveMap();
205 }
206 else
207 {
208 m_map.clear();
209 }
210
211 if (dict != null)
212 {
213 Enumeration keys = dict.keys();
214 while (keys.hasMoreElements())
215 {
216 Object key = keys.nextElement();
217 if (m_map.get(key) == null)
218 {
219 m_map.put(key, dict.get(key));
220 }
221 else
222 {
223 throw new IllegalArgumentException(
224 "Duplicate attribute: " + key.toString());
225 }
226 }
227 }
228 m_ref = null;
229 }
230
231 public Object lookup(String name)
232 {
233 if (m_map == null)
234 {
235 return m_ref.getProperty(name);
236 }
237 return m_map.get(name);
238 }
239 }
240}