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 NisNetGroupTriple according to 031 * RFC 2307 : 032 * <pre> 033 * nisnetgrouptriple = "(" hostname "," username "," domainname ")" 034 * hostname = "" / "-" / keystring 035 * username = "" / "-" / keystring 036 * domainname = "" / "-" / keystring 037 * </pre> 038 * 039 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 040 */ 041@SuppressWarnings("serial") 042public final class NisNetgroupTripleSyntaxChecker extends SyntaxChecker 043{ 044 /** 045 * A static instance of NisNetGroupTripleChecker 046 */ 047 public static final NisNetgroupTripleSyntaxChecker INSTANCE = 048 new NisNetgroupTripleSyntaxChecker( SchemaConstants.NIS_NETGROUP_TRIPLE_SYNTAX ); 049 050 /** 051 * A static Builder for this class 052 */ 053 public static final class Builder extends SCBuilder<NisNetgroupTripleSyntaxChecker> 054 { 055 /** 056 * The Builder constructor 057 */ 058 private Builder() 059 { 060 super( SchemaConstants.NIS_NETGROUP_TRIPLE_SYNTAX ); 061 } 062 063 064 /** 065 * Create a new instance of NisNetgroupTripleSyntaxChecker 066 * @return A new instance of NisNetgroupTripleSyntaxChecker 067 */ 068 @Override 069 public NisNetgroupTripleSyntaxChecker build() 070 { 071 return new NisNetgroupTripleSyntaxChecker( oid ); 072 } 073 } 074 075 076 /** 077 * Creates a new instance of NisNetgroupTripleSyntaxChecker. 078 * 079 * @param oid The OID to use for this SyntaxChecker 080 */ 081 private NisNetgroupTripleSyntaxChecker( 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 ) 097 { 098 char c = strValue.charAt( pos ); 099 100 // The end of the keyString 101 if ( ( c == ',' ) || ( c == ')' ) ) 102 { 103 return pos; 104 } 105 106 // We must have a first alphabetic char 107 if ( Character.isUpperCase( c ) || Character.isLowerCase( c ) ) 108 { 109 pos++; 110 } 111 else 112 { 113 return -1; 114 } 115 116 try 117 { 118 c = strValue.charAt( pos ); 119 120 while ( ( c != ',' ) && ( c != ')' ) ) 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 /** 145 * {@inheritDoc} 146 */ 147 @Override 148 public boolean isValidSyntax( Object value ) 149 { 150 String strValue; 151 152 if ( value == null ) 153 { 154 if ( LOG.isDebugEnabled() ) 155 { 156 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, "null" ) ); 157 } 158 159 return false; 160 } 161 162 if ( value instanceof String ) 163 { 164 strValue = ( String ) value; 165 } 166 else if ( value instanceof byte[] ) 167 { 168 strValue = Strings.utf8ToString( ( byte[] ) value ); 169 } 170 else 171 { 172 strValue = value.toString(); 173 } 174 175 // The nisNetGroup must at least contain a '(', 2 ',' and a ')' 176 if ( strValue.length() < 4 ) 177 { 178 if ( LOG.isDebugEnabled() ) 179 { 180 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, value ) ); 181 } 182 183 return false; 184 } 185 186 // The hostname 187 int pos = parseKeyString( strValue, 1 ); 188 189 if ( pos == -1 ) 190 { 191 if ( LOG.isDebugEnabled() ) 192 { 193 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, value ) ); 194 } 195 196 return false; 197 } 198 199 if ( strValue.charAt( pos ) != ',' ) 200 { 201 if ( LOG.isDebugEnabled() ) 202 { 203 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, value ) ); 204 } 205 206 return false; 207 } 208 else 209 { 210 pos++; 211 } 212 213 // The username 214 pos = parseKeyString( strValue, pos ); 215 216 if ( pos == -1 ) 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 if ( strValue.charAt( pos ) != ',' ) 227 { 228 if ( LOG.isDebugEnabled() ) 229 { 230 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, value ) ); 231 } 232 233 return false; 234 } 235 else 236 { 237 pos++; 238 } 239 240 // The domainname 241 pos = parseKeyString( strValue, pos ); 242 243 if ( pos == -1 ) 244 { 245 if ( LOG.isDebugEnabled() ) 246 { 247 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, value ) ); 248 } 249 250 return false; 251 } 252 253 if ( strValue.charAt( pos ) != ')' ) 254 { 255 if ( LOG.isDebugEnabled() ) 256 { 257 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, value ) ); 258 } 259 260 return false; 261 } 262 263 return true; 264 } 265}