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