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