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 */ 020package org.apache.directory.shared.ldap.model.schema.syntaxCheckers; 021 022 023import java.util.HashSet; 024import java.util.Set; 025 026import org.apache.directory.shared.ldap.model.constants.SchemaConstants; 027import org.apache.directory.shared.ldap.model.schema.SyntaxChecker; 028import org.apache.directory.shared.util.Chars; 029import org.apache.directory.shared.util.Strings; 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032 033 034/** 035 * A SyntaxChecker which verifies that a value is a DSEType according to 036 * http://tools.ietf.org/id/draft-ietf-asid-ldapv3-attributes-03.txt, par 6.2.1.5 : 037 * 038 * <DSEType> ::= '(' <sp>* <DSEBit> <sp>* <DSEBitList> ')' 039 * <DSEBitList> ::= '$' <sp>* <DSEBit> <sp>* <DSEBitList> | e 040 * <DSEBit> ::= 'root' | 'glue' | 'cp' | 'entry' | 'alias' | 'subr' | 041 * 'nssr' | 'supr' | 'xr' | 'admPoint' | 'subentry' | 042 * 'shadow' | 'zombie' | 'immSupr' | 'rhob' | 'sa' 043 * 044 * 045 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 046 */ 047@SuppressWarnings("serial") 048public class DSETypeSyntaxChecker extends SyntaxChecker 049{ 050 /** A logger for this class */ 051 private static final Logger LOG = LoggerFactory.getLogger( DSETypeSyntaxChecker.class ); 052 053 /** The DSE BITS keywords */ 054 private static final String[] DSE_BITS_STRINGS = 055 { 056 "root", "glue", "cp", "entry", "alias", "subr", 057 "nssr", "supr", "xr", "admPoint", "subentry", 058 "shadow", "zombie", "immSupr", "rhob", "sa" 059 }; 060 061 062 /** The Set which contains the DESBits */ 063 private static final Set<String> DSE_BITS = new HashSet<String>(); 064 065 /** Initialization of the country set */ 066 static 067 { 068 for ( String country:DSE_BITS_STRINGS ) 069 { 070 DSE_BITS.add( country ); 071 } 072 } 073 074 075 /** 076 * 077 * Creates a new instance of DSETypeSyntaxChecker. 078 * 079 */ 080 public DSETypeSyntaxChecker() 081 { 082 super( SchemaConstants.DSE_TYPE_SYNTAX ); 083 } 084 085 086 /** 087 * {@inheritDoc} 088 */ 089 public boolean isValidSyntax( Object value ) 090 { 091 String strValue = null; 092 093 if ( value == null ) 094 { 095 LOG.debug( "Syntax invalid for 'null'" ); 096 return false; 097 } 098 099 if ( value instanceof String ) 100 { 101 strValue = ( String ) value; 102 } 103 else if ( value instanceof byte[] ) 104 { 105 strValue = Strings.utf8ToString((byte[]) value); 106 } 107 else 108 { 109 strValue = value.toString(); 110 } 111 112 // We must have at least '(cp)', '(xr)' or '(ca)' 113 if ( strValue.length() < 4 ) 114 { 115 LOG.debug( "Syntax invalid for '{}'", value ); 116 return false; 117 } 118 119 // Check the opening and closing parenthesis 120 if ( ( strValue.charAt( 0 ) != '(' ) 121 || ( strValue.charAt( strValue.length() - 1 ) != ')' ) ) 122 { 123 LOG.debug( "Syntax invalid for '{}'", value ); 124 return false; 125 } 126 127 Set<String> keywords = new HashSet<String>(); 128 int len = strValue.length() - 1; 129 boolean needKeyword = true; 130 131 // 132 for ( int i = 1; i < len; /* */ ) 133 { 134 // Skip spaces 135 while ( ( i < len ) && ( strValue.charAt( i ) == ' ' ) ) 136 { 137 i++; 138 } 139 140 int pos = i; 141 142 // Search for a keyword 143 while ( ( i < len ) && Chars.isAlphaASCII(strValue, pos) ) 144 { 145 pos++; 146 } 147 148 if ( pos == i ) 149 { 150 // No keyword : error 151 LOG.debug( "Syntax invalid for '{}'", value ); 152 return false; 153 } 154 155 String keyword = strValue.substring( i, pos ); 156 i = pos; 157 158 if ( !DSE_BITS.contains( keyword ) ) 159 { 160 // Unknown keyword 161 LOG.debug( "Syntax invalid for '{}'", value ); 162 return false; 163 } 164 165 // Check that the keyword has not been met 166 if ( keywords.contains( keyword ) ) 167 { 168 LOG.debug( "Syntax invalid for '{}'", value ); 169 return false; 170 } 171 172 keywords.add( keyword ); 173 needKeyword = false; 174 175 // Skip spaces 176 while ( ( i < len ) && ( strValue.charAt( i ) == ' ' ) ) 177 { 178 i++; 179 } 180 181 // Do we have another keyword ? 182 if ( ( i < len) && ( strValue.charAt( i ) == '$' ) ) 183 { 184 // yes 185 i++; 186 needKeyword = true; 187 continue; 188 } 189 } 190 191 // We are done 192 if ( needKeyword ) 193 { 194 LOG.debug( "Syntax invalid for '{}'", value ); 195 } 196 else 197 { 198 LOG.debug( "Syntax valid for '{}'", value ); 199 } 200 201 return !needKeyword; 202 } 203}