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.types;
028    import org.opends.messages.Message;
029    
030    
031    
032    import java.util.ArrayList;
033    import java.util.List;
034    
035    import org.opends.server.protocols.asn1.ASN1Element;
036    import org.opends.server.protocols.asn1.ASN1OctetString;
037    import org.opends.server.protocols.asn1.ASN1Sequence;
038    import org.opends.server.protocols.asn1.ASN1Set;
039    import org.opends.server.protocols.ldap.LDAPAttribute;
040    
041    import static org.opends.server.loggers.debug.DebugLogger.*;
042    import org.opends.server.loggers.debug.DebugTracer;
043    import static org.opends.messages.ProtocolMessages.*;
044    import static org.opends.server.protocols.ldap.LDAPResultCode.*;
045    import static org.opends.server.util.Validator.*;
046    
047    
048    
049    /**
050     * This class defines a raw attribute, which has a type (which may
051     * include zero or more options), and zero or more values.  It is an
052     * unprocessed element, so it will not have undergone any syntax or
053     * other forms of validity checking.
054     */
055    @org.opends.server.types.PublicAPI(
056         stability=org.opends.server.types.StabilityLevel.UNCOMMITTED,
057         mayInstantiate=true,
058         mayExtend=false,
059         mayInvoke=true)
060    public abstract class RawAttribute
061    {
062      /**
063       * The tracer object for the debug logger.
064       */
065      private static final DebugTracer TRACER = getTracer();
066    
067    
068    
069      /**
070       * Creates a new raw attribute with the provided type and no values.
071       *
072       * @param  attributeType  The attribute type for this attribute.  It
073       *                        must not be {@code null}.
074       *
075       * @return  The created raw attribute.
076       */
077      public static RawAttribute create(String attributeType)
078      {
079        ensureNotNull(attributeType);
080    
081        return new LDAPAttribute(attributeType);
082      }
083    
084    
085    
086      /**
087       * Creates a new raw attribute with the provided type value.
088       *
089       * @param  attributeType  The attribute type for this attribute.  It
090       *                        must not be {@code null}.
091       * @param  value          The value to use for this attribute.  It
092       *                        must not be {@code null}.
093       *
094       * @return  The created raw attribute.
095       */
096      public static RawAttribute create(String attributeType,
097                                        String value)
098      {
099        ensureNotNull(attributeType, value);
100    
101        return new LDAPAttribute(attributeType, value);
102      }
103    
104    
105    
106      /**
107       * Creates a new raw attribute with the provided type value.
108       *
109       * @param  attributeType  The attribute type for this attribute.  It
110       *                        must not be {@code null}.
111       * @param  value          The value to use for this attribute.  It
112       *                        must not be {@code null}.
113       *
114       * @return  The created raw attribute.
115       */
116      public static RawAttribute create(String attributeType,
117                                        ByteString value)
118      {
119        ensureNotNull(attributeType);
120    
121        return new LDAPAttribute(attributeType,
122                                 value.toASN1OctetString());
123      }
124    
125    
126    
127      /**
128       * Creates a new raw attribute with the provided type and values.
129       *
130       * @param  attributeType  The attribute type for this attribute.  It
131       *                        must not be {@code null}.
132       * @param  values         The set of values for this attribute.
133       *
134       * @return  The created raw attribute.
135       */
136      public static RawAttribute create(String attributeType,
137                                        List<ByteString> values)
138      {
139        ensureNotNull(attributeType);
140    
141        return new LDAPAttribute(attributeType, convertValues(values));
142      }
143    
144    
145    
146      /**
147       * Creates a new raw attribute from the provided attribute.
148       *
149       * @param  attribute  The attribute to use to create this raw
150       *                    attribute.  It must not be {@code null}.
151       *
152       * @return  The created raw attribute.
153       */
154      public static RawAttribute create(Attribute attribute)
155      {
156        ensureNotNull(attribute);
157    
158        return new LDAPAttribute(attribute);
159      }
160    
161    
162    
163      /**
164       * Converts the provided <CODE>List&lt;ByteString&gt;</CODE> to an
165       * <CODE>ArrayList&lt;ASN1OctetString&gt;</CODE>.
166       *
167       * @param  values  The list to be converted.
168       *
169       * @return  The converted {@code ArrayList} object.
170       */
171      private static ArrayList<ASN1OctetString>
172                          convertValues(List<ByteString> values)
173      {
174        if (values == null)
175        {
176          return null;
177        }
178    
179        ArrayList<ASN1OctetString> convertedList =
180             new ArrayList<ASN1OctetString>(values.size());
181        for (ByteString s : values)
182        {
183          convertedList.add(s.toASN1OctetString());
184        }
185    
186        return convertedList;
187      }
188    
189    
190    
191      /**
192       * Retrieves the attribute type for this attribute.
193       *
194       * @return  The attribute type for this attribute.
195       */
196      public abstract String getAttributeType();
197    
198    
199    
200      /**
201       * Specifies the attribute type for this attribute.
202       *
203       * @param  attributeType  The attribute type for this attribute.
204       */
205      public abstract void setAttributeType(String attributeType);
206    
207    
208    
209      /**
210       * Retrieves the set of values for this attribute.  The returned
211       * list may be modified by the caller.
212       *
213       * @return  The set of values for this attribute.
214       */
215      public abstract ArrayList<ASN1OctetString> getValues();
216    
217    
218    
219      /**
220       * Retrieves a core attribute containing the information for this
221       * raw attribute.
222       *
223       * @return  A core attribute containing the information for this raw
224       *          attribute.
225       *
226       * @throws  LDAPException  If the provided value is invalid
227       *                         according to the attribute syntax.
228       */
229      public abstract Attribute toAttribute()
230             throws LDAPException;
231    
232    
233    
234      /**
235       * Encodes this attribute to an ASN.1 element.
236       *
237       * @return  The ASN.1 element containing the encoded attribute.
238       */
239      public final ASN1Element encode()
240      {
241        ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
242        elements.add(new ASN1OctetString(getAttributeType()));
243    
244        ArrayList<ASN1OctetString> values = getValues();
245        if ((values == null) || values.isEmpty())
246        {
247          elements.add(new ASN1Set());
248        }
249        else
250        {
251          elements.add(new ASN1Set(new ArrayList<ASN1Element>(values)));
252        }
253    
254        return new ASN1Sequence(elements);
255      }
256    
257    
258    
259      /**
260       * Decodes the provided ASN.1 element as an LDAP attribute.
261       *
262       * @param  element  The ASN.1 element to decode.
263       *
264       * @return  The decoded LDAP attribute.
265       *
266       * @throws  LDAPException  If a problem occurs while trying to
267       *                         decode the provided ASN.1 element as a
268       *                         raw attribute.
269       */
270      public static LDAPAttribute decode(ASN1Element element)
271             throws LDAPException
272      {
273        ArrayList<ASN1Element> elements;
274        try
275        {
276          elements = element.decodeAsSequence().elements();
277        }
278        catch (Exception e)
279        {
280          if (debugEnabled())
281          {
282            TRACER.debugCaught(DebugLogLevel.ERROR, e);
283          }
284    
285          Message message =
286              ERR_LDAP_ATTRIBUTE_DECODE_SEQUENCE.get(String.valueOf(e));
287          throw new LDAPException(PROTOCOL_ERROR, message, e);
288        }
289    
290    
291        int numElements = elements.size();
292        if (numElements != 2)
293        {
294          Message message =
295              ERR_LDAP_ATTRIBUTE_DECODE_INVALID_ELEMENT_COUNT.
296                get(numElements);
297          throw new LDAPException(PROTOCOL_ERROR, message);
298        }
299    
300    
301        String attributeType;
302        try
303        {
304          attributeType =
305               elements.get(0).decodeAsOctetString().stringValue();
306        }
307        catch (Exception e)
308        {
309          if (debugEnabled())
310          {
311            TRACER.debugCaught(DebugLogLevel.ERROR, e);
312          }
313    
314          Message message =
315              ERR_LDAP_ATTRIBUTE_DECODE_TYPE.get(String.valueOf(e));
316          throw new LDAPException(PROTOCOL_ERROR, message, e);
317        }
318    
319    
320        ArrayList<ASN1OctetString> values;
321        try
322        {
323          ArrayList<ASN1Element> valueElements =
324               elements.get(1).decodeAsSet().elements();
325          values = new ArrayList<ASN1OctetString>(valueElements.size());
326          for (ASN1Element e : valueElements)
327          {
328            values.add(e.decodeAsOctetString());
329          }
330        }
331        catch (Exception e)
332        {
333          if (debugEnabled())
334          {
335            TRACER.debugCaught(DebugLogLevel.ERROR, e);
336          }
337    
338          Message message =
339              ERR_LDAP_ATTRIBUTE_DECODE_VALUES.get(String.valueOf(e));
340          throw new LDAPException(PROTOCOL_ERROR, message, e);
341        }
342    
343        return new LDAPAttribute(attributeType, values);
344      }
345    
346    
347    
348      /**
349       * Retrieves a string representation of this attribute.
350       *
351       * @return  A string representation of this attribute.
352       */
353      public String toString()
354      {
355        StringBuilder buffer = new StringBuilder();
356        toString(buffer);
357        return buffer.toString();
358      }
359    
360    
361    
362      /**
363       * Appends a string representation of this attribute to the provided
364       * buffer.
365       *
366       * @param  buffer  The buffer to which the information should be
367       *                 appended.
368       */
369      public abstract void toString(StringBuilder buffer);
370    
371    
372    
373      /**
374       * Appends a multi-line string representation of this LDAP attribute
375       * to the provided buffer.
376       *
377       * @param  buffer  The buffer to which the information should be
378       *                 appended.
379       * @param  indent  The number of spaces from the margin that the
380       *                 lines should be indented.
381       */
382      public abstract void toString(StringBuilder buffer, int indent);
383    }
384