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 * https://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.api.ldap.model.schema.syntaxCheckers; 021 022 023import org.apache.directory.api.i18n.I18n; 024import org.apache.directory.api.ldap.model.constants.SchemaConstants; 025import org.apache.directory.api.ldap.model.schema.SyntaxChecker; 026import org.apache.directory.api.util.Strings; 027 028 029/** 030 * A SyntaxChecker which verifies that a value is a BootParameter according to 031 * RFC 2307 : 032 * <pre> 033 * bootparameter = key "=" server ":" path 034 * key = keystring 035 * server = keystring 036 * path = keystring 037 * </pre> 038 * 039 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 040 */ 041@SuppressWarnings("serial") 042public final class BootParameterSyntaxChecker extends SyntaxChecker 043{ 044 /** 045 * A static instance of BootParameterSyntaxChecker 046 */ 047 public static final BootParameterSyntaxChecker INSTANCE = 048 new BootParameterSyntaxChecker( SchemaConstants.BOOT_PARAMETER_SYNTAX ); 049 050 /** 051 * A static Builder for this class 052 */ 053 public static final class Builder extends SCBuilder<BootParameterSyntaxChecker> 054 { 055 /** 056 * The Builder constructor 057 */ 058 private Builder() 059 { 060 super( SchemaConstants.BOOT_PARAMETER_SYNTAX ); 061 } 062 063 064 /** 065 * Create a new instance of BootParameterSyntaxChecker 066 * @return A new instance of BootParameterSyntaxChecker 067 */ 068 @Override 069 public BootParameterSyntaxChecker build() 070 { 071 return new BootParameterSyntaxChecker( oid ); 072 } 073 } 074 075 076 /** 077 * Creates a new instance of BootParameterSyntaxChecker. 078 * 079 * @param oid The OID to use for this SyntaxChecker 080 */ 081 private BootParameterSyntaxChecker( String oid ) 082 { 083 super( oid ); 084 } 085 086 087 /** 088 * @return An instance of the Builder for this class 089 */ 090 public static Builder builder() 091 { 092 return new Builder(); 093 } 094 095 096 private int parseKeyString( String strValue, int pos, char limit ) 097 { 098 try 099 { 100 char c = strValue.charAt( pos ); 101 102 // The end of the keyString 103 if ( c == limit ) 104 { 105 return pos; 106 } 107 108 // We must have a first alphabetic char 109 if ( Character.isUpperCase( c ) || Character.isLowerCase( c ) ) 110 { 111 pos++; 112 } 113 else 114 { 115 return -1; 116 } 117 118 c = strValue.charAt( pos ); 119 120 while ( c != limit ) 121 { 122 if ( Character.isUpperCase( c ) || Character.isLowerCase( c ) || Character.isDigit( c ) 123 || ( c == '-' ) || ( c == ';' ) || ( c == '_' ) ) 124 { 125 pos++; 126 } 127 else 128 { 129 return -1; 130 } 131 132 c = strValue.charAt( pos ); 133 } 134 135 return pos; 136 } 137 catch ( IndexOutOfBoundsException ioobe ) 138 { 139 return -1; 140 } 141 } 142 143 144 private int parseKeyString( String strValue, int pos ) 145 { 146 try 147 { 148 char c = strValue.charAt( pos ); 149 150 // We must have a first alphabetic char 151 if ( Character.isUpperCase( c ) || Character.isLowerCase( c ) ) 152 { 153 pos++; 154 } 155 else 156 { 157 return -1; 158 } 159 160 while ( pos < strValue.length() ) 161 { 162 c = strValue.charAt( pos ); 163 164 if ( Character.isUpperCase( c ) || Character.isLowerCase( c ) || Character.isDigit( c ) 165 || ( c == '-' ) || ( c == ';' ) || ( c == '_' ) ) 166 { 167 pos++; 168 } 169 else 170 { 171 return -1; 172 } 173 } 174 175 return pos; 176 } 177 catch ( IndexOutOfBoundsException ioobe ) 178 { 179 return -1; 180 } 181 } 182 183 184 /** 185 * {@inheritDoc} 186 */ 187 @Override 188 public boolean isValidSyntax( Object value ) 189 { 190 String strValue; 191 192 if ( value == null ) 193 { 194 if ( LOG.isDebugEnabled() ) 195 { 196 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, "null" ) ); 197 } 198 199 return false; 200 } 201 202 if ( value instanceof String ) 203 { 204 strValue = ( String ) value; 205 } 206 else if ( value instanceof byte[] ) 207 { 208 strValue = Strings.utf8ToString( ( byte[] ) value ); 209 } 210 else 211 { 212 strValue = value.toString(); 213 } 214 215 // The BootParameter must at least contain a '=' and a ':', plus 3 keyStrings 216 if ( strValue.length() < 5 ) 217 { 218 if ( LOG.isDebugEnabled() ) 219 { 220 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, value ) ); 221 } 222 223 return false; 224 } 225 226 // The key 227 int pos = parseKeyString( strValue, 0, '=' ); 228 229 if ( pos == -1 ) 230 { 231 if ( LOG.isDebugEnabled() ) 232 { 233 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, value ) ); 234 } 235 236 return false; 237 } 238 239 if ( strValue.charAt( pos ) != '=' ) 240 { 241 if ( LOG.isDebugEnabled() ) 242 { 243 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, value ) ); 244 } 245 246 return false; 247 } 248 else 249 { 250 pos++; 251 } 252 253 // The server 254 pos = parseKeyString( strValue, pos, ':' ); 255 256 if ( pos == -1 ) 257 { 258 if ( LOG.isDebugEnabled() ) 259 { 260 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, value ) ); 261 } 262 263 return false; 264 } 265 266 if ( strValue.charAt( pos ) != ':' ) 267 { 268 if ( LOG.isDebugEnabled() ) 269 { 270 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, value ) ); 271 } 272 273 return false; 274 } 275 else 276 { 277 pos++; 278 } 279 280 // The path 281 pos = parseKeyString( strValue, pos ); 282 283 if ( pos == -1 ) 284 { 285 if ( LOG.isDebugEnabled() ) 286 { 287 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, value ) ); 288 } 289 290 return false; 291 } 292 293 return true; 294 } 295}