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 legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2006-2008 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027package org.opends.server.types; 028 029import org.forgerock.i18n.LocalizableMessage; 030 031 032 033import java.util.Random; 034import java.util.SortedSet; 035 036import org.forgerock.opendj.config.server.ConfigException; 037 038import static org.opends.messages.UtilityMessages.*; 039import static org.opends.server.util.StaticUtils.*; 040 041 042 043/** 044 * This class provides a data structure that makes it possible to 045 * associate a name with a given set of characters. The name must 046 * consist only of ASCII alphabetic characters. 047 */ 048@org.opends.server.types.PublicAPI( 049 stability=org.opends.server.types.StabilityLevel.VOLATILE, 050 mayInstantiate=true, 051 mayExtend=false, 052 mayInvoke=true) 053public final class NamedCharacterSet 054{ 055 /** The characters contained in this character set. */ 056 private char[] characters; 057 058 /** The random number generator to use with this character set. */ 059 private Random random; 060 061 /** The name assigned to this character set. */ 062 private String name; 063 064 065 066 /** 067 * Creates a new named character set with the provided information. 068 * 069 * @param name The name for this character set. 070 * @param characters The characters to include in this character 071 * set. 072 * 073 * @throws ConfigException If the provided name contains one or 074 * more illegal characters. 075 */ 076 public NamedCharacterSet(String name, char[] characters) 077 throws ConfigException 078 { 079 this.name = name; 080 this.characters = characters; 081 082 random = new Random(); 083 084 if (name == null || name.length() == 0) 085 { 086 LocalizableMessage message = ERR_CHARSET_CONSTRUCTOR_NO_NAME.get(); 087 throw new ConfigException(message); 088 } 089 090 for (int i=0; i < name.length(); i++) 091 { 092 if (! isAlpha(name.charAt(i))) 093 { 094 throw new ConfigException(ERR_CHARSET_CONSTRUCTOR_INVALID_NAME_CHAR.get(name.charAt(i), i)); 095 } 096 } 097 } 098 099 100 101 /** 102 * Creates a new named character set with the provided information. 103 * 104 * @param name The name for this character set. 105 * @param characters The characters to include in this character 106 * set. 107 * @param random The random number generator to use with this 108 * character set. 109 * 110 * @throws ConfigException If the provided name contains one or 111 * more illegal characters. 112 */ 113 public NamedCharacterSet(String name, char[] characters, 114 Random random) 115 throws ConfigException 116 { 117 this.name = name; 118 this.characters = characters; 119 this.random = random; 120 121 if (name == null || name.length() == 0) 122 { 123 LocalizableMessage message = ERR_CHARSET_CONSTRUCTOR_NO_NAME.get(); 124 throw new ConfigException(message); 125 } 126 127 for (int i=0; i < name.length(); i++) 128 { 129 if (! isAlpha(name.charAt(i))) 130 { 131 throw new ConfigException(ERR_CHARSET_CONSTRUCTOR_INVALID_NAME_CHAR.get(name.charAt(i), i)); 132 } 133 } 134 } 135 136 137 138 /** 139 * Retrieves the name for this character set. 140 * 141 * @return The name for this character set. 142 */ 143 public String getName() 144 { 145 return name; 146 } 147 148 149 150 /** 151 * Retrieves the characters included in this character set. 152 * 153 * @return The characters included in this character set. 154 */ 155 public char[] getCharacters() 156 { 157 return characters; 158 } 159 160 161 162 /** 163 * Retrieves a character at random from this named character set. 164 * 165 * @return The randomly-selected character from this named 166 * character set; 167 */ 168 public char getRandomCharacter() 169 { 170 if (characters == null || characters.length == 0) 171 { 172 return 0; 173 } 174 175 return characters[random.nextInt(characters.length)]; 176 } 177 178 179 180 /** 181 * Appends the specified number of characters chosen at random from 182 * this character set to the provided buffer. 183 * 184 * @param buffer The buffer to which the characters should be 185 * appended. 186 * @param count The number of characters to append to the 187 * provided buffer. 188 */ 189 public void getRandomCharacters(StringBuilder buffer, int count) 190 { 191 if (characters == null || characters.length == 0) 192 { 193 return; 194 } 195 196 for (int i=0; i < count; i++) 197 { 198 buffer.append(characters[random.nextInt(characters.length)]); 199 } 200 } 201 202 203 204 /** 205 * Encodes this character set to a form suitable for use in the 206 * value of a configuration attribute. 207 * 208 * @return The encoded character set in a form suitable for use in 209 * the value of a configuration attribute. 210 */ 211 public String encode() 212 { 213 return name + ":" + new String(characters); 214 } 215 216 217 218 /** 219 * Decodes the values of the provided configuration attribute as a 220 * set of character set definitions. 221 * 222 * @param values The set of encoded character set values to 223 * decode. 224 * 225 * @return The decoded character set definitions. 226 * 227 * @throws ConfigException If a problem occurs while attempting to 228 * decode the character set definitions. 229 */ 230 public static NamedCharacterSet[] 231 decodeCharacterSets(SortedSet<String> values) 232 throws ConfigException 233 { 234 NamedCharacterSet[] sets = new NamedCharacterSet[values.size()]; 235 int i = 0 ; 236 for (String value : values) 237 { 238 int colonPos = value.indexOf(':'); 239 if (colonPos < 0) 240 { 241 throw new ConfigException(ERR_CHARSET_NO_COLON.get(value)); 242 } 243 else if (colonPos == 0) 244 { 245 throw new ConfigException(ERR_CHARSET_NO_NAME.get(value)); 246 } 247 else if (colonPos == (value.length() - 1)) 248 { 249 throw new ConfigException(ERR_CHARSET_NO_CHARS.get(value)); 250 } 251 else 252 { 253 String name = value.substring(0, colonPos); 254 char[] characters = value.substring(colonPos+1).toCharArray(); 255 sets[i] = new NamedCharacterSet(name, characters); 256 } 257 i++; 258 } 259 260 return sets; 261 } 262} 263