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