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-2008 Sun Microsystems, Inc.
015 * Portions Copyright 2013-2016 ForgeRock AS.
016 */
017package org.opends.server.controls;
018
019
020
021import org.forgerock.i18n.LocalizableMessage;
022
023import java.util.Iterator;
024import java.util.LinkedHashSet;
025import java.util.Set;
026import java.io.IOException;
027
028import org.forgerock.opendj.io.*;
029
030import static org.opends.server.plugins.LDAPADListPlugin.*;
031import org.opends.server.types.*;
032import org.forgerock.opendj.ldap.ResultCode;
033import org.forgerock.opendj.ldap.ByteString;
034import org.forgerock.i18n.slf4j.LocalizedLogger;
035import static org.opends.messages.ProtocolMessages.*;
036import static org.opends.server.util.ServerConstants.*;
037
038
039
040/**
041 * This class implements the pre-read request control as defined in RFC 4527.
042 * This control makes it possible to retrieve an entry in the state that it held
043 * immediately before a modify, delete, or modify DN operation. It may specify a
044 * specific set of attributes that should be included in that entry. The entry
045 * will be encoded in a corresponding response control.
046 */
047public class LDAPPreReadRequestControl extends Control
048{
049  /** ControlDecoder implementation to decode this control from a ByteString. */
050  private static final class Decoder implements
051      ControlDecoder<LDAPPreReadRequestControl>
052  {
053    @Override
054    public LDAPPreReadRequestControl decode(boolean isCritical,
055        ByteString value) throws DirectoryException
056    {
057      if (value == null)
058      {
059        LocalizableMessage message = ERR_PREREADREQ_NO_CONTROL_VALUE.get();
060        throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message);
061      }
062
063      ASN1Reader reader = ASN1.getReader(value);
064      LinkedHashSet<String> rawAttributes = new LinkedHashSet<>();
065      try
066      {
067        reader.readStartSequence();
068        while (reader.hasNextElement())
069        {
070          rawAttributes.add(reader.readOctetStringAsString());
071        }
072        reader.readEndSequence();
073      }
074      catch (Exception ae)
075      {
076        logger.traceException(ae);
077
078        LocalizableMessage message = ERR_PREREADREQ_CANNOT_DECODE_VALUE.get(ae
079            .getMessage());
080        throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, ae);
081      }
082
083      return new LDAPPreReadRequestControl(isCritical, rawAttributes);
084    }
085
086
087
088    @Override
089    public String getOID()
090    {
091      return OID_LDAP_READENTRY_PREREAD;
092    }
093
094  }
095
096
097
098  /** The Control Decoder that can be used to decode this control. */
099  public static final ControlDecoder<LDAPPreReadRequestControl> DECODER =
100      new Decoder();
101  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
102
103  /** The set of raw attributes to return in the entry. */
104  private Set<String> rawAttributes;
105
106  /** The set of processed attributes to return in the entry. */
107  private Set<String> requestedAttributes;
108
109
110
111  /**
112   * Creates a new instance of this LDAP pre-read request control with the
113   * provided information.
114   *
115   * @param isCritical
116   *          Indicates whether support for this control should be considered a
117   *          critical part of the server processing.
118   * @param rawAttributes
119   *          The set of raw attributes to return in the entry. A null or empty
120   *          set will indicates that all user attributes should be returned.
121   */
122  public LDAPPreReadRequestControl(boolean isCritical,
123      Set<String> rawAttributes)
124  {
125    super(OID_LDAP_READENTRY_PREREAD, isCritical);
126    if (rawAttributes == null)
127    {
128      this.rawAttributes = new LinkedHashSet<>(0);
129    }
130    else
131    {
132      this.rawAttributes = rawAttributes;
133    }
134    requestedAttributes = null;
135  }
136
137
138
139  /**
140   * Writes this control's value to an ASN.1 writer. The value (if any) must be
141   * written as an ASN1OctetString.
142   *
143   * @param writer
144   *          The ASN.1 output stream to write to.
145   * @throws IOException
146   *           If a problem occurs while writing to the stream.
147   */
148  @Override
149  public void writeValue(ASN1Writer writer) throws IOException
150  {
151    writer.writeStartSequence(ASN1.UNIVERSAL_OCTET_STRING_TYPE);
152    {
153      writer.writeStartSequence();
154      if (rawAttributes != null)
155      {
156        for (String attr : rawAttributes)
157        {
158          writer.writeOctetString(attr);
159        }
160      }
161      writer.writeEndSequence();
162    }
163    writer.writeEndSequence();
164  }
165
166
167
168  /**
169   * Retrieves the raw, unprocessed set of requested attributes. It must not be
170   * altered by the caller without calling <CODE>setRawAttributes</CODE> with
171   * the updated set.
172   *
173   * @return The raw, unprocessed set of attributes.
174   */
175  public Set<String> getRawAttributes()
176  {
177    return rawAttributes;
178  }
179
180
181
182  /**
183   * Retrieves the set of processed attributes that have been requested for
184   * inclusion in the entry that is returned.
185   *
186   * @return The set of processed attributes that have been requested for
187   *         inclusion in the entry that is returned.
188   */
189  public Set<String> getRequestedAttributes()
190  {
191    if (requestedAttributes == null)
192    {
193      requestedAttributes = normalizedObjectClasses(rawAttributes);
194    }
195    return requestedAttributes;
196  }
197
198
199
200  /**
201   * Appends a string representation of this LDAP pre-read request control to
202   * the provided buffer.
203   *
204   * @param buffer
205   *          The buffer to which the information should be appended.
206   */
207  @Override
208  public void toString(StringBuilder buffer)
209  {
210    buffer.append("LDAPPreReadRequestControl(criticality=");
211    buffer.append(isCritical());
212    buffer.append(",attrs=\"");
213
214    if (!rawAttributes.isEmpty())
215    {
216      Iterator<String> iterator = rawAttributes.iterator();
217      buffer.append(iterator.next());
218
219      while (iterator.hasNext())
220      {
221        buffer.append(",");
222        buffer.append(iterator.next());
223      }
224    }
225
226    buffer.append("\")");
227  }
228}