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-2016 ForgeRock AS. 016 */ 017package org.opends.server.types; 018 019import java.security.SecureRandom; 020import java.util.Random; 021import java.util.SortedSet; 022 023import org.forgerock.i18n.LocalizableMessage; 024import org.forgerock.opendj.config.server.ConfigException; 025 026import static org.opends.messages.UtilityMessages.*; 027import static org.opends.server.util.StaticUtils.*; 028 029/** 030 * This class provides a data structure that makes it possible to 031 * associate a name with a given set of characters. The name must 032 * consist only of ASCII alphabetic characters. 033 */ 034@org.opends.server.types.PublicAPI( 035 stability=org.opends.server.types.StabilityLevel.VOLATILE, 036 mayInstantiate=true, 037 mayExtend=false, 038 mayInvoke=true) 039public final class NamedCharacterSet 040{ 041 /** The characters contained in this character set. */ 042 private final char[] characters; 043 /** The random number generator to use with this character set. */ 044 private final Random random; 045 /** The name assigned to this character set. */ 046 private final String name; 047 048 049 050 /** 051 * Creates a new named character set with the provided information. 052 * 053 * @param name The name for this character set. 054 * @param characters The characters to include in this character 055 * set. 056 * 057 * @throws ConfigException If the provided name contains one or 058 * more illegal characters. 059 */ 060 private NamedCharacterSet(String name, char[] characters) 061 throws ConfigException 062 { 063 this(name, characters, new SecureRandom()); 064 } 065 066 067 068 /** 069 * Creates a new named character set with the provided information. 070 * 071 * @param name The name for this character set. 072 * @param characters The characters to include in this character 073 * set. 074 * @param random The random number generator to use with this 075 * character set. 076 * 077 * @throws ConfigException If the provided name contains one or 078 * more illegal characters. 079 */ 080 private NamedCharacterSet(String name, char[] characters, 081 Random random) 082 throws ConfigException 083 { 084 this.name = name; 085 this.characters = characters; 086 this.random = random; 087 088 if (name == null || name.length() == 0) 089 { 090 LocalizableMessage message = ERR_CHARSET_CONSTRUCTOR_NO_NAME.get(); 091 throw new ConfigException(message); 092 } 093 094 for (int i=0; i < name.length(); i++) 095 { 096 if (! isAlpha(name.charAt(i))) 097 { 098 throw new ConfigException(ERR_CHARSET_CONSTRUCTOR_INVALID_NAME_CHAR.get(name.charAt(i), i)); 099 } 100 } 101 } 102 103 104 105 /** 106 * Retrieves the name for this character set. 107 * 108 * @return The name for this character set. 109 */ 110 public String getName() 111 { 112 return name; 113 } 114 115 116 117 /** 118 * Retrieves the characters included in this character set. 119 * 120 * @return The characters included in this character set. 121 */ 122 public char[] getCharacters() 123 { 124 return characters; 125 } 126 127 128 129 /** 130 * Retrieves a character at random from this named character set. 131 * 132 * @return The randomly-selected character from this named 133 * character set; 134 */ 135 public char getRandomCharacter() 136 { 137 if (characters == null || characters.length == 0) 138 { 139 return 0; 140 } 141 142 return characters[random.nextInt(characters.length)]; 143 } 144 145 146 147 /** 148 * Appends the specified number of characters chosen at random from 149 * this character set to the provided buffer. 150 * 151 * @param buffer The buffer to which the characters should be 152 * appended. 153 * @param count The number of characters to append to the 154 * provided buffer. 155 */ 156 public void getRandomCharacters(StringBuilder buffer, int count) 157 { 158 if (characters == null || characters.length == 0) 159 { 160 return; 161 } 162 163 for (int i=0; i < count; i++) 164 { 165 buffer.append(characters[random.nextInt(characters.length)]); 166 } 167 } 168 169 /** 170 * Decodes the values of the provided configuration attribute as a 171 * set of character set definitions. 172 * 173 * @param values The set of encoded character set values to 174 * decode. 175 * 176 * @return The decoded character set definitions. 177 * 178 * @throws ConfigException If a problem occurs while attempting to 179 * decode the character set definitions. 180 */ 181 public static NamedCharacterSet[] 182 decodeCharacterSets(SortedSet<String> values) 183 throws ConfigException 184 { 185 NamedCharacterSet[] sets = new NamedCharacterSet[values.size()]; 186 int i = 0 ; 187 for (String value : values) 188 { 189 int colonPos = value.indexOf(':'); 190 if (colonPos < 0) 191 { 192 throw new ConfigException(ERR_CHARSET_NO_COLON.get(value)); 193 } 194 else if (colonPos == 0) 195 { 196 throw new ConfigException(ERR_CHARSET_NO_NAME.get(value)); 197 } 198 else if (colonPos == (value.length() - 1)) 199 { 200 throw new ConfigException(ERR_CHARSET_NO_CHARS.get(value)); 201 } 202 else 203 { 204 String name = value.substring(0, colonPos); 205 char[] characters = value.substring(colonPos+1).toCharArray(); 206 sets[i] = new NamedCharacterSet(name, characters); 207 } 208 i++; 209 } 210 211 return sets; 212 } 213} 214