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