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