001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.schema; 028 029 030 031 import java.util.HashSet; 032 033 import org.opends.server.admin.std.server.AttributeSyntaxCfg; 034 import org.opends.server.api.ApproximateMatchingRule; 035 import org.opends.server.api.AttributeSyntax; 036 import org.opends.server.api.EqualityMatchingRule; 037 import org.opends.server.api.OrderingMatchingRule; 038 import org.opends.server.api.SubstringMatchingRule; 039 import org.opends.server.config.ConfigException; 040 import org.opends.server.core.DirectoryServer; 041 import org.opends.server.types.ByteString; 042 043 044 045 import static org.opends.server.loggers.ErrorLogger.*; 046 import static org.opends.messages.SchemaMessages.*; 047 import org.opends.messages.MessageBuilder; 048 import static org.opends.server.schema.SchemaConstants.*; 049 050 051 052 /** 053 * This class implements the teletex terminal identifier attribute syntax, which 054 * contains a printable string (the terminal identifier) followed by zero or 055 * more parameters, which start with a dollar sign and are followed by a 056 * parameter name, a colon, and a value. The parameter value should consist of 057 * any string of bytes (the dollar sign and backslash must be escaped with a 058 * preceding backslash), and the parameter name must be one of the following 059 * strings: 060 * <UL> 061 * <LI>graphic</LI> 062 * <LI>control</LI> 063 * <LI>misc</LI> 064 * <LI>page</LI> 065 * <LI>private</LI> 066 * </UL> 067 */ 068 public class TeletexTerminalIdentifierSyntax 069 extends AttributeSyntax<AttributeSyntaxCfg> 070 { 071 /** 072 * The set of allowed fax parameter values, formatted entirely in lowercase 073 * characters. 074 */ 075 public static final HashSet<String> ALLOWED_TTX_PARAMETERS = 076 new HashSet<String>(5); 077 078 static 079 { 080 ALLOWED_TTX_PARAMETERS.add("graphic"); 081 ALLOWED_TTX_PARAMETERS.add("control"); 082 ALLOWED_TTX_PARAMETERS.add("misc"); 083 ALLOWED_TTX_PARAMETERS.add("page"); 084 ALLOWED_TTX_PARAMETERS.add("private"); 085 } 086 087 088 089 // The default equality matching rule for this syntax. 090 private EqualityMatchingRule defaultEqualityMatchingRule; 091 092 // The default ordering matching rule for this syntax. 093 private OrderingMatchingRule defaultOrderingMatchingRule; 094 095 // The default substring matching rule for this syntax. 096 private SubstringMatchingRule defaultSubstringMatchingRule; 097 098 099 100 /** 101 * Creates a new instance of this syntax. Note that the only thing that 102 * should be done here is to invoke the default constructor for the 103 * superclass. All initialization should be performed in the 104 * <CODE>initializeSyntax</CODE> method. 105 */ 106 public TeletexTerminalIdentifierSyntax() 107 { 108 super(); 109 } 110 111 112 113 /** 114 * {@inheritDoc} 115 */ 116 public void initializeSyntax(AttributeSyntaxCfg configuration) 117 throws ConfigException 118 { 119 defaultEqualityMatchingRule = 120 DirectoryServer.getEqualityMatchingRule(EMR_CASE_IGNORE_OID); 121 if (defaultEqualityMatchingRule == null) 122 { 123 logError(ERR_ATTR_SYNTAX_UNKNOWN_EQUALITY_MATCHING_RULE.get( 124 EMR_CASE_IGNORE_OID, SYNTAX_TELETEX_TERM_ID_NAME)); 125 } 126 127 defaultOrderingMatchingRule = 128 DirectoryServer.getOrderingMatchingRule(OMR_CASE_IGNORE_OID); 129 if (defaultOrderingMatchingRule == null) 130 { 131 logError(ERR_ATTR_SYNTAX_UNKNOWN_ORDERING_MATCHING_RULE.get( 132 OMR_CASE_IGNORE_OID, SYNTAX_TELETEX_TERM_ID_NAME)); 133 } 134 135 defaultSubstringMatchingRule = 136 DirectoryServer.getSubstringMatchingRule(SMR_CASE_IGNORE_OID); 137 if (defaultSubstringMatchingRule == null) 138 { 139 logError(ERR_ATTR_SYNTAX_UNKNOWN_SUBSTRING_MATCHING_RULE.get( 140 SMR_CASE_IGNORE_OID, SYNTAX_TELETEX_TERM_ID_NAME)); 141 } 142 } 143 144 145 146 /** 147 * Retrieves the common name for this attribute syntax. 148 * 149 * @return The common name for this attribute syntax. 150 */ 151 public String getSyntaxName() 152 { 153 return SYNTAX_TELETEX_TERM_ID_NAME; 154 } 155 156 157 158 /** 159 * Retrieves the OID for this attribute syntax. 160 * 161 * @return The OID for this attribute syntax. 162 */ 163 public String getOID() 164 { 165 return SYNTAX_TELETEX_TERM_ID_OID; 166 } 167 168 169 170 /** 171 * Retrieves a description for this attribute syntax. 172 * 173 * @return A description for this attribute syntax. 174 */ 175 public String getDescription() 176 { 177 return SYNTAX_TELETEX_TERM_ID_DESCRIPTION; 178 } 179 180 181 182 /** 183 * Retrieves the default equality matching rule that will be used for 184 * attributes with this syntax. 185 * 186 * @return The default equality matching rule that will be used for 187 * attributes with this syntax, or <CODE>null</CODE> if equality 188 * matches will not be allowed for this type by default. 189 */ 190 public EqualityMatchingRule getEqualityMatchingRule() 191 { 192 return defaultEqualityMatchingRule; 193 } 194 195 196 197 /** 198 * Retrieves the default ordering matching rule that will be used for 199 * attributes with this syntax. 200 * 201 * @return The default ordering matching rule that will be used for 202 * attributes with this syntax, or <CODE>null</CODE> if ordering 203 * matches will not be allowed for this type by default. 204 */ 205 public OrderingMatchingRule getOrderingMatchingRule() 206 { 207 return defaultOrderingMatchingRule; 208 } 209 210 211 212 /** 213 * Retrieves the default substring matching rule that will be used for 214 * attributes with this syntax. 215 * 216 * @return The default substring matching rule that will be used for 217 * attributes with this syntax, or <CODE>null</CODE> if substring 218 * matches will not be allowed for this type by default. 219 */ 220 public SubstringMatchingRule getSubstringMatchingRule() 221 { 222 return defaultSubstringMatchingRule; 223 } 224 225 226 227 /** 228 * Retrieves the default approximate matching rule that will be used for 229 * attributes with this syntax. 230 * 231 * @return The default approximate matching rule that will be used for 232 * attributes with this syntax, or <CODE>null</CODE> if approximate 233 * matches will not be allowed for this type by default. 234 */ 235 public ApproximateMatchingRule getApproximateMatchingRule() 236 { 237 // There is no approximate matching rule by default. 238 return null; 239 } 240 241 242 243 /** 244 * Indicates whether the provided value is acceptable for use in an attribute 245 * with this syntax. If it is not, then the reason may be appended to the 246 * provided buffer. 247 * 248 * @param value The value for which to make the determination. 249 * @param invalidReason The buffer to which the invalid reason should be 250 * appended. 251 * 252 * @return <CODE>true</CODE> if the provided value is acceptable for use with 253 * this syntax, or <CODE>false</CODE> if not. 254 */ 255 public boolean valueIsAcceptable(ByteString value, 256 MessageBuilder invalidReason) 257 { 258 // Get a lowercase string representation of the value and find its length. 259 String valueString = value.stringValue(); 260 int valueLength = valueString.length(); 261 262 263 // The value must contain at least one character. 264 if (valueLength == 0) 265 { 266 267 invalidReason.append(ERR_ATTR_SYNTAX_TELETEXID_EMPTY.get()); 268 return false; 269 } 270 271 272 // The first character must be a printable string character. 273 char c = valueString.charAt(0); 274 if (! PrintableString.isPrintableCharacter(c)) 275 { 276 277 invalidReason.append(ERR_ATTR_SYNTAX_TELETEXID_NOT_PRINTABLE.get( 278 valueString, String.valueOf(c), 0)); 279 return false; 280 } 281 282 283 // Continue reading until we find a dollar sign or the end of the string. 284 // Every intermediate character must be a printable string character. 285 int pos = 1; 286 for ( ; pos < valueLength; pos++) 287 { 288 c = valueString.charAt(pos); 289 if (c == '$') 290 { 291 pos++; 292 break; 293 } 294 else 295 { 296 if (! PrintableString.isPrintableCharacter(c)) 297 { 298 299 invalidReason.append(ERR_ATTR_SYNTAX_TELETEXID_NOT_PRINTABLE.get( 300 valueString, String.valueOf(c), pos)); 301 } 302 } 303 } 304 305 if (pos >= valueLength) 306 { 307 // We're at the end of the value, so it must be valid unless the last 308 // character was a dollar sign. 309 if (c == '$') 310 { 311 312 invalidReason.append(ERR_ATTR_SYNTAX_TELETEXID_END_WITH_DOLLAR.get( 313 valueString)); 314 return false; 315 } 316 else 317 { 318 return true; 319 } 320 } 321 322 323 // Continue reading until we find the end of the string. Each substring 324 // must be a valid teletex terminal identifier parameter followed by a colon 325 // and the value. Dollar signs must be escaped 326 int paramStartPos = pos; 327 boolean escaped = false; 328 while (pos < valueLength) 329 { 330 if (escaped) 331 { 332 pos++; 333 continue; 334 } 335 336 c = valueString.charAt(pos++); 337 if (c == '\\') 338 { 339 escaped = true; 340 continue; 341 } 342 else if (c == '$') 343 { 344 String paramStr = valueString.substring(paramStartPos, pos); 345 346 int colonPos = paramStr.indexOf(':'); 347 if (colonPos < 0) 348 { 349 350 invalidReason.append(ERR_ATTR_SYNTAX_TELETEXID_PARAM_NO_COLON.get( 351 valueString)); 352 return false; 353 } 354 355 String paramName = paramStr.substring(0, colonPos); 356 if (! ALLOWED_TTX_PARAMETERS.contains(paramName)) 357 { 358 359 invalidReason.append(ERR_ATTR_SYNTAX_TELETEXID_ILLEGAL_PARAMETER.get( 360 valueString, paramName)); 361 return false; 362 } 363 364 paramStartPos = pos; 365 } 366 } 367 368 369 // We must be at the end of the value. Read the last parameter and make 370 // sure it is valid. 371 String paramStr = valueString.substring(paramStartPos); 372 int colonPos = paramStr.indexOf(':'); 373 if (colonPos < 0) 374 { 375 376 invalidReason.append(ERR_ATTR_SYNTAX_TELETEXID_PARAM_NO_COLON.get( 377 valueString)); 378 return false; 379 } 380 381 String paramName = paramStr.substring(0, colonPos); 382 if (! ALLOWED_TTX_PARAMETERS.contains(paramName)) 383 { 384 385 invalidReason.append(ERR_ATTR_SYNTAX_TELETEXID_ILLEGAL_PARAMETER.get( 386 valueString, paramName)); 387 return false; 388 } 389 390 391 // If we've gotten here, then the value must be valid. 392 return true; 393 } 394 } 395