View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.model.schema.syntaxCheckers;
21  
22  
23  import java.util.HashSet;
24  import java.util.Set;
25  
26  import org.apache.directory.api.ldap.model.constants.SchemaConstants;
27  import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
28  import org.apache.directory.api.util.Chars;
29  import org.apache.directory.api.util.Strings;
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  
33  
34  /**
35   * A SyntaxChecker which verifies that a value is a DSEType according to 
36   * http://tools.ietf.org/id/draft-ietf-asid-ldapv3-attributes-03.txt, par 6.2.1.5 :
37   * 
38   * <DSEType>    ::= '(' <sp>* <DSEBit> <sp>* <DSEBitList> ')'
39   * <DSEBitList> ::= '$' <sp>* <DSEBit> <sp>* <DSEBitList> | e      
40   * <DSEBit>     ::= 'root' | 'glue' | 'cp' | 'entry' | 'alias' | 'subr' |
41   *                  'nssr' | 'supr' | 'xr' | 'admPoint' | 'subentry' |
42   *                  'shadow' | 'zombie' | 'immSupr' | 'rhob' | 'sa'
43   * 
44   *
45   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
46   */
47  @SuppressWarnings("serial")
48  public class DseTypeSyntaxChecker extends SyntaxChecker
49  {
50      /** A logger for this class */
51      private static final Logger LOG = LoggerFactory.getLogger( DseTypeSyntaxChecker.class );
52  
53      /** The DSE BITS keywords */
54      private static final String[] DSE_BITS_STRINGS =
55          {
56              "root", "glue", "cp", "entry", "alias", "subr",
57              "nssr", "supr", "xr", "admPoint", "subentry",
58              "shadow", "zombie", "immSupr", "rhob", "sa"
59      };
60  
61      /** The Set which contains the DESBits */
62      private static final Set<String> DSE_BITS = new HashSet<String>();
63  
64      /** Initialization of the country set */
65      static
66      {
67          for ( String country : DSE_BITS_STRINGS )
68          {
69              DSE_BITS.add( country );
70          }
71      }
72  
73  
74      /**
75       * 
76       * Creates a new instance of DSETypeSyntaxChecker.
77       *
78       */
79      public DseTypeSyntaxChecker()
80      {
81          super( SchemaConstants.DSE_TYPE_SYNTAX );
82      }
83  
84  
85      /**
86       * {@inheritDoc}
87       */
88      public boolean isValidSyntax( Object value )
89      {
90          String strValue = null;
91  
92          if ( value == null )
93          {
94              LOG.debug( "Syntax invalid for 'null'" );
95              return false;
96          }
97  
98          if ( value instanceof String )
99          {
100             strValue = ( String ) value;
101         }
102         else if ( value instanceof byte[] )
103         {
104             strValue = Strings.utf8ToString( ( byte[] ) value );
105         }
106         else
107         {
108             strValue = value.toString();
109         }
110 
111         // We must have at least '(cp)', '(xr)' or '(ca)'
112         if ( strValue.length() < 4 )
113         {
114             LOG.debug( "Syntax invalid for '{}'", value );
115             return false;
116         }
117 
118         // Check the opening and closing parenthesis
119         if ( ( strValue.charAt( 0 ) != '(' )
120             || ( strValue.charAt( strValue.length() - 1 ) != ')' ) )
121         {
122             LOG.debug( "Syntax invalid for '{}'", value );
123             return false;
124         }
125 
126         Set<String> keywords = new HashSet<String>();
127         int len = strValue.length() - 1;
128         boolean needKeyword = true;
129 
130         // 
131         for ( int i = 1; i < len; /* */)
132         {
133             // Skip spaces
134             while ( ( i < len ) && ( strValue.charAt( i ) == ' ' ) )
135             {
136                 i++;
137             }
138 
139             int pos = i;
140 
141             // Search for a keyword
142             while ( ( i < len ) && Chars.isAlphaASCII( strValue, pos ) )
143             {
144                 pos++;
145             }
146 
147             if ( pos == i )
148             {
149                 // No keyword : error
150                 LOG.debug( "Syntax invalid for '{}'", value );
151                 return false;
152             }
153 
154             String keyword = strValue.substring( i, pos );
155             i = pos;
156 
157             if ( !DSE_BITS.contains( keyword ) )
158             {
159                 // Unknown keyword
160                 LOG.debug( "Syntax invalid for '{}'", value );
161                 return false;
162             }
163 
164             // Check that the keyword has not been met
165             if ( keywords.contains( keyword ) )
166             {
167                 LOG.debug( "Syntax invalid for '{}'", value );
168                 return false;
169             }
170 
171             keywords.add( keyword );
172             needKeyword = false;
173 
174             // Skip spaces
175             while ( ( i < len ) && ( strValue.charAt( i ) == ' ' ) )
176             {
177                 i++;
178             }
179 
180             // Do we have another keyword ?
181             if ( ( i < len ) && ( strValue.charAt( i ) == '$' ) )
182             {
183                 // yes
184                 i++;
185                 needKeyword = true;
186                 continue;
187             }
188         }
189 
190         // We are done
191         if ( needKeyword )
192         {
193             LOG.debug( "Syntax invalid for '{}'", value );
194         }
195         else
196         {
197             LOG.debug( "Syntax valid for '{}'", value );
198         }
199 
200         return !needKeyword;
201     }
202 }