001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.schema;
028
029
030
031 import java.util.List;
032
033 import org.opends.server.admin.std.server.SubstringMatchingRuleCfg;
034 import org.opends.server.api.SubstringMatchingRule;
035 import org.opends.server.config.ConfigException;
036 import org.opends.server.protocols.asn1.ASN1OctetString;
037 import org.opends.server.types.ByteString;
038 import org.opends.server.types.DirectoryException;
039 import org.opends.server.types.InitializationException;
040
041 import static org.opends.server.schema.SchemaConstants.*;
042 import static org.opends.server.util.StaticUtils.*;
043
044
045
046 /**
047 * This class defines the octetStringSubstringsMatch matching rule defined in
048 * X.520. It will be used as the default substring matching rule for the binary
049 * and octet string syntaxes.
050 */
051 public class OctetStringSubstringMatchingRule
052 extends SubstringMatchingRule
053 {
054 /**
055 * Creates a new instance of this octetStringSubstringsMatch matching rule.
056 */
057 public OctetStringSubstringMatchingRule()
058 {
059 super();
060 }
061
062
063
064 /**
065 * {@inheritDoc}
066 */
067 public void initializeMatchingRule(SubstringMatchingRuleCfg configuration)
068 throws ConfigException, InitializationException
069 {
070 // No initialization is required.
071 }
072
073
074
075 /**
076 * Retrieves the common name for this matching rule.
077 *
078 * @return The common name for this matching rule, or <CODE>null</CODE> if
079 * it does not have a name.
080 */
081 public String getName()
082 {
083 return SMR_OCTET_STRING_NAME;
084 }
085
086
087
088 /**
089 * Retrieves the OID for this matching rule.
090 *
091 * @return The OID for this matching rule.
092 */
093 public String getOID()
094 {
095 return SMR_OCTET_STRING_OID;
096 }
097
098
099
100 /**
101 * Retrieves the description for this matching rule.
102 *
103 * @return The description for this matching rule, or <CODE>null</CODE> if
104 * there is none.
105 */
106 public String getDescription()
107 {
108 // There is no standard description for this matching rule.
109 return null;
110 }
111
112
113
114 /**
115 * Retrieves the OID of the syntax with which this matching rule is
116 * associated.
117 *
118 * @return The OID of the syntax with which this matching rule is associated.
119 */
120 public String getSyntaxOID()
121 {
122 return SYNTAX_SUBSTRING_ASSERTION_OID;
123 }
124
125
126
127 /**
128 * Retrieves the normalized form of the provided value, which is best suited
129 * for efficiently performing matching operations on that value.
130 *
131 * @param value The value to be normalized.
132 *
133 * @return The normalized version of the provided value.
134 *
135 * @throws DirectoryException If the provided value is invalid according to
136 * the associated attribute syntax.
137 */
138 public ByteString normalizeValue(ByteString value)
139 throws DirectoryException
140 {
141 return new ASN1OctetString(value.value());
142 }
143
144
145
146 /**
147 * Normalizes the provided value fragment into a form that can be used to
148 * efficiently compare values.
149 *
150 * @param substring The value fragment to be normalized.
151 *
152 * @return The normalized form of the value fragment.
153 *
154 * @throws DirectoryException If the provided value fragment is not
155 * acceptable according to the associated syntax.
156 */
157 public ByteString normalizeSubstring(ByteString substring)
158 throws DirectoryException
159 {
160 // This is exactly the same as normalizing a full value.
161 return new ASN1OctetString(substring.value());
162 }
163
164
165
166 /**
167 * Determines whether the provided value matches the given substring filter
168 * components. Note that any of the substring filter components may be
169 * <CODE>null</CODE> but at least one of them must be non-<CODE>null</CODE>.
170 *
171 * @param value The normalized value against which to compare the
172 * substring components.
173 * @param subInitial The normalized substring value fragment that should
174 * appear at the beginning of the target value.
175 * @param subAnyElements The normalized substring value fragments that
176 * should appear in the middle of the target value.
177 * @param subFinal The normalized substring value fragment that should
178 * appear at the end of the target value.
179 *
180 * @return <CODE>true</CODE> if the provided value does match the given
181 * substring components, or <CODE>false</CODE> if not.
182 */
183 public boolean valueMatchesSubstring(ByteString value, ByteString subInitial,
184 List<ByteString> subAnyElements,
185 ByteString subFinal)
186 {
187 byte[] valueBytes = value.value();
188 int valueLength = valueBytes.length;
189
190 int pos = 0;
191 if (subInitial != null)
192 {
193 byte[] initialBytes = subInitial.value();
194 int initialLength = initialBytes.length;
195 if (initialLength > valueLength)
196 {
197 return false;
198 }
199
200 for (; pos < initialLength; pos++)
201 {
202 if (initialBytes[pos] != valueBytes[pos])
203 {
204 return false;
205 }
206 }
207 }
208
209
210 if ((subAnyElements != null) && (! subAnyElements.isEmpty()))
211 {
212 for (ByteString element : subAnyElements)
213 {
214 byte[] anyBytes = element.value();
215 int anyLength = anyBytes.length;
216
217 int end = valueLength - anyLength;
218 boolean match = false;
219 for (; pos <= end; pos++)
220 {
221 if (anyBytes[0] == valueBytes[pos])
222 {
223 boolean subMatch = true;
224 for (int i=1; i < anyLength; i++)
225 {
226 if (anyBytes[i] != valueBytes[pos+i])
227 {
228 subMatch = false;
229 break;
230 }
231 }
232
233 if (subMatch)
234 {
235 match = subMatch;
236 break;
237 }
238 }
239 }
240
241 if (match)
242 {
243 pos += anyLength;
244 }
245 else
246 {
247 return false;
248 }
249 }
250 }
251
252
253 if (subFinal != null)
254 {
255 byte[] finalBytes = subFinal.value();
256 int finalLength = finalBytes.length;
257
258 if ((valueLength - finalLength) < pos)
259 {
260 return false;
261 }
262
263 pos = valueLength - finalLength;
264 for (int i=0; i < finalLength; i++,pos++)
265 {
266 if (finalBytes[i] != valueBytes[pos])
267 {
268 return false;
269 }
270 }
271 }
272
273
274 return true;
275 }
276 }
277