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 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.protocols.ldap; 028 import org.opends.messages.Message; 029 030 031 032 import java.util.ArrayList; 033 import java.util.Iterator; 034 import java.util.LinkedHashSet; 035 import java.util.List; 036 037 import org.opends.server.core.DirectoryServer; 038 import org.opends.server.protocols.asn1.ASN1OctetString; 039 import org.opends.server.types.Attribute; 040 import org.opends.server.types.AttributeType; 041 import org.opends.server.types.AttributeValue; 042 import org.opends.server.types.LDAPException; 043 import org.opends.server.types.RawAttribute; 044 045 import static org.opends.server.loggers.debug.DebugLogger.*; 046 import org.opends.server.loggers.debug.DebugTracer; 047 import static org.opends.messages.ProtocolMessages.*; 048 import static org.opends.server.protocols.ldap.LDAPResultCode.*; 049 import static org.opends.server.util.ServerConstants.*; 050 import static org.opends.server.util.StaticUtils.*; 051 052 053 054 055 /** 056 * This class defines the data structures and methods to use when interacting 057 * with an LDAP attribute, which is the basic unit of information in an LDAP 058 * entry. 059 */ 060 public class LDAPAttribute 061 extends RawAttribute 062 { 063 /** 064 * The tracer object for the debug logger. 065 */ 066 private static final DebugTracer TRACER = getTracer(); 067 068 // The set of values for this attribute. 069 private ArrayList<ASN1OctetString> values; 070 071 // The attribute type for this attribute. 072 private String attributeType; 073 074 075 076 /** 077 * Creates a new LDAP attribute with the provided type and no values. 078 * 079 * @param attributeType The attribute type for this attribute. 080 */ 081 public LDAPAttribute(String attributeType) 082 { 083 this.attributeType = attributeType; 084 085 values = new ArrayList<ASN1OctetString>(0); 086 } 087 088 089 090 /** 091 * Creates a new LDAP attribute with the provided type and no values. 092 * 093 * @param attributeType The attribute type for this attribute. 094 * @param value The value to use for this attribute. 095 */ 096 public LDAPAttribute(String attributeType, String value) 097 { 098 this.attributeType = attributeType; 099 100 values = new ArrayList<ASN1OctetString>(1); 101 values.add(new ASN1OctetString(value)); 102 } 103 104 105 106 /** 107 * Creates a new LDAP attribute with the provided type and no values. 108 * 109 * @param attributeType The attribute type for this attribute. 110 * @param value The value to use for this attribute. 111 */ 112 public LDAPAttribute(String attributeType, ASN1OctetString value) 113 { 114 this.attributeType = attributeType; 115 116 values = new ArrayList<ASN1OctetString>(1); 117 values.add(value); 118 } 119 120 121 122 /** 123 * Creates a new LDAP attribute with the provided type and values. 124 * 125 * @param attributeType The attribute type for this attribute. 126 * @param values The set of values for this attribute. 127 */ 128 public LDAPAttribute(String attributeType, List<String> values) 129 { 130 this.attributeType = attributeType; 131 132 if (values == null) 133 { 134 this.values = new ArrayList<ASN1OctetString>(0); 135 } 136 else 137 { 138 this.values = new ArrayList<ASN1OctetString>(values.size()); 139 for (String value : values) 140 { 141 this.values.add(new ASN1OctetString(value)); 142 } 143 } 144 } 145 146 147 148 /** 149 * Creates a new LDAP attribute with the provided type and values. 150 * 151 * @param attributeType The attribute type for this attribute. 152 * @param values The set of values for this attribute. 153 */ 154 public LDAPAttribute(String attributeType, ArrayList<ASN1OctetString> values) 155 { 156 this.attributeType = attributeType; 157 158 if (values == null) 159 { 160 this.values = new ArrayList<ASN1OctetString>(0); 161 } 162 else 163 { 164 this.values = values; 165 } 166 } 167 168 169 170 /** 171 * Creates a new LDAP attribute from the provided attribute. 172 * 173 * @param attribute The attribute to use to create this LDAP attribute. 174 */ 175 public LDAPAttribute(Attribute attribute) 176 { 177 if (attribute.hasOptions()) 178 { 179 StringBuilder attrName = new StringBuilder(attribute.getName()); 180 for (String o : attribute.getOptions()) 181 { 182 attrName.append(";"); 183 attrName.append(o); 184 } 185 186 this.attributeType = attrName.toString(); 187 } 188 else 189 { 190 this.attributeType = attribute.getName(); 191 } 192 193 LinkedHashSet<AttributeValue> attrValues = attribute.getValues(); 194 if ((attrValues == null) || attrValues.isEmpty()) 195 { 196 values = new ArrayList<ASN1OctetString>(0); 197 return; 198 } 199 200 values = new ArrayList<ASN1OctetString>(attrValues.size()); 201 for (AttributeValue v : attrValues) 202 { 203 values.add(v.getValue().toASN1OctetString()); 204 } 205 } 206 207 208 209 /** 210 * Retrieves the attribute type for this attribute. 211 * 212 * @return The attribute type for this attribute. 213 */ 214 public String getAttributeType() 215 { 216 return attributeType; 217 } 218 219 220 221 /** 222 * Specifies the attribute type for this attribute. 223 * 224 * @param attributeType The attribute type for this attribute. 225 */ 226 public void setAttributeType(String attributeType) 227 { 228 this.attributeType = attributeType; 229 } 230 231 232 233 /** 234 * Retrieves the set of values for this attribute. The returned list may be 235 * modified by the caller. 236 * 237 * @return The set of values for this attribute. 238 */ 239 public ArrayList<ASN1OctetString> getValues() 240 { 241 return values; 242 } 243 244 245 246 /** 247 * Retrieves a core attribute containing the information for this LDAP 248 * attribute. 249 * 250 * @return A core attribute containing the information for this LDAP 251 * attribute. 252 * 253 * @throws LDAPException If the provided value is invalid according to the 254 * attribute syntax. 255 */ 256 public Attribute toAttribute() 257 throws LDAPException 258 { 259 String baseName; 260 String lowerBaseName; 261 int semicolonPos = attributeType.indexOf(';'); 262 LinkedHashSet<String> options; 263 if (semicolonPos > 0) 264 { 265 baseName = attributeType.substring(0, semicolonPos); 266 options = new LinkedHashSet<String>(); 267 int nextPos = attributeType.indexOf(';', semicolonPos+1); 268 while (nextPos > 0) 269 { 270 String option = attributeType.substring(semicolonPos+1, nextPos); 271 if (option.length() > 0) 272 { 273 options.add(option); 274 } 275 276 semicolonPos = nextPos; 277 nextPos = attributeType.indexOf(';', semicolonPos+1); 278 } 279 280 String option = attributeType.substring(semicolonPos+1); 281 if (option.length() > 0) 282 { 283 options.add(option); 284 } 285 } 286 else 287 { 288 baseName = attributeType; 289 options = new LinkedHashSet<String>(0); 290 } 291 lowerBaseName = toLowerCase(baseName); 292 293 AttributeType attrType = DirectoryServer.getAttributeType(lowerBaseName); 294 if (attrType == null) 295 { 296 attrType = DirectoryServer.getDefaultAttributeType(lowerBaseName); 297 } 298 299 300 LinkedHashSet<AttributeValue> attributeValues = 301 new LinkedHashSet<AttributeValue>(values.size()); 302 for (ASN1OctetString value : values) 303 { 304 if (! attributeValues.add(new AttributeValue(attrType, value))) 305 { 306 Message message = 307 ERR_LDAP_ATTRIBUTE_DUPLICATE_VALUES.get(attributeType); 308 throw new LDAPException( 309 LDAPResultCode.ATTRIBUTE_OR_VALUE_EXISTS, message); 310 } 311 } 312 313 314 return new Attribute(attrType, baseName, options, attributeValues); 315 } 316 317 318 319 /** 320 * Retrieves a string representation of this attribute. 321 * 322 * @return A string representation of this attribute. 323 */ 324 public String toString() 325 { 326 StringBuilder buffer = new StringBuilder(); 327 toString(buffer); 328 return buffer.toString(); 329 } 330 331 332 333 /** 334 * Appends a string representation of this attribute to the provided buffer. 335 * 336 * @param buffer The buffer to which the information should be appended. 337 */ 338 public void toString(StringBuilder buffer) 339 { 340 buffer.append("LDAPAttribute(type="); 341 buffer.append(attributeType); 342 buffer.append(", values={"); 343 344 if (! values.isEmpty()) 345 { 346 Iterator<ASN1OctetString> iterator = values.iterator(); 347 iterator.next().toString(buffer); 348 while (iterator.hasNext()) 349 { 350 buffer.append(", "); 351 iterator.next().toString(buffer); 352 } 353 } 354 355 buffer.append("})"); 356 } 357 358 359 360 /** 361 * Appends a multi-line string representation of this LDAP attribute to the 362 * provided buffer. 363 * 364 * @param buffer The buffer to which the information should be appended. 365 * @param indent The number of spaces from the margin that the lines should 366 * be indented. 367 */ 368 public void toString(StringBuilder buffer, int indent) 369 { 370 StringBuilder indentBuf = new StringBuilder(indent); 371 for (int i=0 ; i < indent; i++) 372 { 373 indentBuf.append(' '); 374 } 375 376 buffer.append(indentBuf); 377 buffer.append("LDAP Attribute"); 378 buffer.append(EOL); 379 380 buffer.append(indentBuf); 381 buffer.append(" Attribute Type: "); 382 buffer.append(attributeType); 383 buffer.append(EOL); 384 385 buffer.append(" Attribute Values:"); 386 buffer.append(EOL); 387 388 for (ASN1OctetString value : values) 389 { 390 value.toString(buffer, indent+4); 391 } 392 } 393 } 394