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 }