001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 package org.apache.directory.shared.ldap.schema.syntaxCheckers;
021
022
023 import java.util.HashSet;
024 import java.util.Set;
025
026 import org.apache.directory.shared.ldap.constants.SchemaConstants;
027 import org.apache.directory.shared.ldap.schema.SyntaxChecker;
028 import org.apache.directory.shared.ldap.util.StringTools;
029 import org.slf4j.Logger;
030 import org.slf4j.LoggerFactory;
031
032
033 /**
034 * A SyntaxChecker which verifies that a value is a DSEType according to
035 * http://tools.ietf.org/id/draft-ietf-asid-ldapv3-attributes-03.txt, par 6.2.1.5 :
036 *
037 * <DSEType> ::= '(' <sp>* <DSEBit> <sp>* <DSEBitList> ')'
038 * <DSEBitList> ::= '$' <sp>* <DSEBit> <sp>* <DSEBitList> | e
039 * <DSEBit> ::= 'root' | 'glue' | 'cp' | 'entry' | 'alias' | 'subr' |
040 * 'nssr' | 'supr' | 'xr' | 'admPoint' | 'subentry' |
041 * 'shadow' | 'zombie' | 'immSupr' | 'rhob' | 'sa'
042 *
043 *
044 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
045 * @version $Rev$
046 */
047 public class DSETypeSyntaxChecker extends SyntaxChecker
048 {
049 /** A logger for this class */
050 private static final Logger LOG = LoggerFactory.getLogger( DSETypeSyntaxChecker.class );
051
052 /** The serialVersionUID */
053 private static final long serialVersionUID = 1L;
054
055 /** The DSE BITS keywords */
056 private static final String[] DSE_BITS_STRINGS =
057 {
058 "root", "glue", "cp", "entry", "alias", "subr",
059 "nssr", "supr", "xr", "admPoint", "subentry",
060 "shadow", "zombie", "immSupr", "rhob", "sa"
061 };
062
063
064 /** The Set which contains the DESBits */
065 private static final Set<String> DSE_BITS = new HashSet<String>();
066
067 /** Initialization of the country set */
068 static
069 {
070 for ( String country:DSE_BITS_STRINGS )
071 {
072 DSE_BITS.add( country );
073 }
074 }
075
076
077 /**
078 *
079 * Creates a new instance of DSETypeSyntaxChecker.
080 *
081 */
082 public DSETypeSyntaxChecker()
083 {
084 super( SchemaConstants.DSE_TYPE_SYNTAX );
085 }
086
087
088 /**
089 * {@inheritDoc}
090 */
091 public boolean isValidSyntax( Object value )
092 {
093 String strValue = null;
094
095 if ( value == null )
096 {
097 LOG.debug( "Syntax invalid for '{}'", value );
098 return false;
099 }
100
101 if ( value instanceof String )
102 {
103 strValue = ( String ) value;
104 }
105 else if ( value instanceof byte[] )
106 {
107 strValue = StringTools.utf8ToString( ( byte[] ) value );
108 }
109 else
110 {
111 strValue = value.toString();
112 }
113
114 // We must have at least '(cp)', '(xr)' or '(ca)'
115 if ( strValue.length() < 4 )
116 {
117 LOG.debug( "Syntax invalid for '{}'", value );
118 return false;
119 }
120
121 // Check the opening and closing parenthesis
122 if ( ( strValue.charAt( 0 ) != '(' ) ||
123 ( strValue.charAt( strValue.length() - 1 ) != ')' ) )
124 {
125 LOG.debug( "Syntax invalid for '{}'", value );
126 return false;
127 }
128
129 Set<String> keywords = new HashSet<String>();
130 int len = strValue.length() - 1;
131 boolean needKeyword = true;
132
133 //
134 for ( int i = 1; i < len; /* */ )
135 {
136 // Skip spaces
137 while ( ( i < len ) && ( strValue.charAt( i ) == ' ' ) )
138 {
139 i++;
140 }
141
142 int pos = i;
143
144 // Search for a keyword
145 while ( ( i < len ) && StringTools.isAlphaASCII( strValue, pos ) )
146 {
147 pos++;
148 }
149
150 if ( pos == i )
151 {
152 // No keyword : error
153 LOG.debug( "Syntax invalid for '{}'", value );
154 return false;
155 }
156
157 String keyword = strValue.substring( i, pos );
158 i = pos;
159
160 if ( !DSE_BITS.contains( keyword ) )
161 {
162 // Unknown keyword
163 LOG.debug( "Syntax invalid for '{}'", value );
164 return false;
165 }
166
167 // Check that the keyword has not been met
168 if ( keywords.contains( keyword ) )
169 {
170 LOG.debug( "Syntax invalid for '{}'", value );
171 return false;
172 }
173
174 keywords.add( keyword );
175 needKeyword = false;
176
177 // Skip spaces
178 while ( ( i < len ) && ( strValue.charAt( i ) == ' ' ) )
179 {
180 i++;
181 }
182
183 // Do we have another keyword ?
184 if ( ( i < len) && ( strValue.charAt( i ) == '$' ) )
185 {
186 // yes
187 i++;
188 needKeyword = true;
189 continue;
190 }
191 }
192
193 // We are done
194 if ( needKeyword )
195 {
196 LOG.debug( "Syntax invalid for '{}'", value );
197 }
198 else
199 {
200 LOG.debug( "Syntax valid for '{}'", value );
201 }
202
203 return !needKeyword;
204 }
205 }