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-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2013-2015 ForgeRock AS 026 */ 027package org.opends.server.protocols.ldap; 028 029import static org.opends.messages.ProtocolMessages.*; 030import static org.opends.server.util.CollectionUtils.*; 031import static org.opends.server.util.ServerConstants.*; 032 033import java.util.ArrayList; 034import java.util.Iterator; 035import java.util.List; 036 037import org.forgerock.i18n.LocalizableMessage; 038import org.forgerock.opendj.ldap.ByteString; 039import org.opends.server.types.Attribute; 040import org.opends.server.types.AttributeBuilder; 041import org.opends.server.types.LDAPException; 042import org.opends.server.types.RawAttribute; 043 044/** 045 * This class defines the data structures and methods to use when interacting 046 * with an LDAP attribute, which is the basic unit of information in an LDAP 047 * entry. 048 */ 049public class LDAPAttribute 050 extends RawAttribute 051{ 052 /** The set of values for this attribute. */ 053 private List<ByteString> values; 054 055 /** The attribute type for this attribute. */ 056 private String attributeType; 057 058 059 060 /** 061 * Creates a new LDAP attribute with the provided type and no values. 062 * 063 * @param attributeType The attribute type for this attribute. 064 */ 065 public LDAPAttribute(String attributeType) 066 { 067 this.attributeType = attributeType; 068 069 values = new ArrayList<>(0); 070 } 071 072 073 074 /** 075 * Creates a new LDAP attribute with the provided type and no values. 076 * 077 * @param attributeType The attribute type for this attribute. 078 * @param value The value to use for this attribute. 079 */ 080 public LDAPAttribute(String attributeType, String value) 081 { 082 this.attributeType = attributeType; 083 084 values = newArrayList(ByteString.valueOfUtf8(value)); 085 } 086 087 088 089 /** 090 * Creates a new LDAP attribute with the provided type and no values. 091 * 092 * @param attributeType The attribute type for this attribute. 093 * @param value The value to use for this attribute. 094 */ 095 public LDAPAttribute(String attributeType, ByteString value) 096 { 097 this.attributeType = attributeType; 098 099 values = newArrayList(value); 100 } 101 102 103 104 /** 105 * Creates a new LDAP attribute with the provided type and values. 106 * 107 * @param attributeType The attribute type for this attribute. 108 * @param values The set of values for this attribute. 109 */ 110 public LDAPAttribute(String attributeType, List<String> values) 111 { 112 this.attributeType = attributeType; 113 114 if (values == null) 115 { 116 this.values = new ArrayList<>(0); 117 } 118 else 119 { 120 this.values = new ArrayList<>(values.size()); 121 for (String value : values) 122 { 123 this.values.add(ByteString.valueOfUtf8(value)); 124 } 125 } 126 } 127 128 129 130 /** 131 * Creates a new LDAP attribute with the provided type and values. 132 * 133 * @param attributeType The attribute type for this attribute. 134 * @param values The set of values for this attribute. 135 */ 136 public LDAPAttribute(String attributeType, ArrayList<ByteString> values) 137 { 138 this.attributeType = attributeType; 139 140 if (values == null) 141 { 142 this.values = new ArrayList<>(0); 143 } 144 else 145 { 146 this.values = values; 147 } 148 } 149 150 151 152 /** 153 * Creates a new LDAP attribute from the provided attribute. 154 * 155 * @param attribute The attribute to use to create this LDAP attribute. 156 */ 157 public LDAPAttribute(Attribute attribute) 158 { 159 this.attributeType = attribute.getNameWithOptions(); 160 161 if (attribute.isVirtual()) 162 { 163 values = new ArrayList<>(); 164 } 165 else if (attribute.isEmpty()) 166 { 167 values = new ArrayList<>(0); 168 return; 169 } 170 else 171 { 172 values = new ArrayList<>(attribute.size()); 173 } 174 175 for (ByteString v : attribute) 176 { 177 values.add(v); 178 } 179 } 180 181 182 183 /** 184 * Retrieves the attribute type for this attribute. 185 * 186 * @return The attribute type for this attribute. 187 */ 188 @Override 189 public String getAttributeType() 190 { 191 return attributeType; 192 } 193 194 195 196 /** 197 * Specifies the attribute type for this attribute. 198 * 199 * @param attributeType The attribute type for this attribute. 200 */ 201 @Override 202 public void setAttributeType(String attributeType) 203 { 204 this.attributeType = attributeType; 205 } 206 207 208 209 /** 210 * Retrieves the set of values for this attribute. The returned list may be 211 * modified by the caller. 212 * 213 * @return The set of values for this attribute. 214 */ 215 @Override 216 public List<ByteString> getValues() 217 { 218 return values; 219 } 220 221 222 223 /** 224 * Retrieves a core attribute containing the information for this LDAP 225 * attribute. 226 * 227 * @return A core attribute containing the information for this LDAP 228 * attribute. 229 * 230 * @throws LDAPException If the provided value is invalid according to the 231 * attribute syntax. 232 */ 233 @Override 234 public Attribute toAttribute() 235 throws LDAPException 236 { 237 AttributeBuilder builder; 238 int semicolonPos = attributeType.indexOf(';'); 239 if (semicolonPos > 0) 240 { 241 builder = new AttributeBuilder(attributeType.substring(0, semicolonPos)); 242 int nextPos = attributeType.indexOf(';', semicolonPos+1); 243 while (nextPos > 0) 244 { 245 String option = attributeType.substring(semicolonPos+1, nextPos); 246 if (option.length() > 0) 247 { 248 builder.setOption(option); 249 } 250 251 semicolonPos = nextPos; 252 nextPos = attributeType.indexOf(';', semicolonPos+1); 253 } 254 255 String option = attributeType.substring(semicolonPos+1); 256 if (option.length() > 0) 257 { 258 builder.setOption(option); 259 } 260 } 261 else 262 { 263 builder = new AttributeBuilder(attributeType); 264 } 265 266 for (ByteString value : values) 267 { 268 if (!builder.add(value)) 269 { 270 LocalizableMessage message = 271 ERR_LDAP_ATTRIBUTE_DUPLICATE_VALUES.get(attributeType); 272 throw new LDAPException( 273 LDAPResultCode.ATTRIBUTE_OR_VALUE_EXISTS, message); 274 } 275 } 276 277 return builder.toAttribute(); 278 } 279 280 281 282 /** 283 * Retrieves a string representation of this attribute. 284 * 285 * @return A string representation of this attribute. 286 */ 287 @Override 288 public String toString() 289 { 290 StringBuilder buffer = new StringBuilder(); 291 toString(buffer); 292 return buffer.toString(); 293 } 294 295 296 297 /** 298 * Appends a string representation of this attribute to the provided buffer. 299 * 300 * @param buffer The buffer to which the information should be appended. 301 */ 302 @Override 303 public void toString(StringBuilder buffer) 304 { 305 buffer.append("LDAPAttribute(type="); 306 buffer.append(attributeType); 307 buffer.append(", values={"); 308 309 if (! values.isEmpty()) 310 { 311 Iterator<ByteString> iterator = values.iterator(); 312 buffer.append(iterator.next()); 313 while (iterator.hasNext()) 314 { 315 buffer.append(", "); 316 buffer.append(iterator.next()); 317 } 318 } 319 320 buffer.append("})"); 321 } 322 323 324 325 /** 326 * Appends a multi-line string representation of this LDAP attribute to the 327 * provided buffer. 328 * 329 * @param buffer The buffer to which the information should be appended. 330 * @param indent The number of spaces from the margin that the lines should 331 * be indented. 332 */ 333 @Override 334 public void toString(StringBuilder buffer, int indent) 335 { 336 StringBuilder indentBuf = new StringBuilder(indent); 337 for (int i=0 ; i < indent; i++) 338 { 339 indentBuf.append(' '); 340 } 341 342 buffer.append(indentBuf); 343 buffer.append("LDAP Attribute"); 344 buffer.append(EOL); 345 346 buffer.append(indentBuf); 347 buffer.append(" Attribute Type: "); 348 buffer.append(attributeType); 349 buffer.append(EOL); 350 351 buffer.append(" Attribute Values:"); 352 buffer.append(EOL); 353 354 for (ByteString value : values) 355 { 356 buffer.append(value.toHexPlusAsciiString(indent+4)); 357 } 358 } 359} 360