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.controls;
028    import org.opends.messages.Message;
029    
030    
031    
032    import org.opends.server.protocols.asn1.ASN1Element;
033    import org.opends.server.protocols.asn1.ASN1Exception;
034    import org.opends.server.protocols.asn1.ASN1OctetString;
035    import org.opends.server.protocols.ldap.LDAPResultCode;
036    import org.opends.server.protocols.ldap.SearchResultEntryProtocolOp;
037    import org.opends.server.types.Control;
038    import org.opends.server.types.SearchResultEntry;
039    import org.opends.server.types.DebugLogLevel;
040    import org.opends.server.types.LDAPException;
041    
042    import static org.opends.server.loggers.debug.DebugLogger.*;
043    import org.opends.server.loggers.debug.DebugTracer;
044    import static org.opends.messages.ProtocolMessages.*;
045    import static org.opends.server.util.ServerConstants.*;
046    
047    
048    
049    /**
050     * This class implements the post-read response control as defined in RFC 4527.
051     * This control holds the search result entry representing the state of the
052     * entry immediately before an add, modify, or modify DN operation.
053     */
054    public class LDAPPostReadResponseControl
055           extends Control
056    {
057      /**
058       * The tracer object for the debug logger.
059       */
060      private static final DebugTracer TRACER = getTracer();
061    
062    
063    
064    
065      // The search result entry to include in the response control.
066      private SearchResultEntry searchEntry;
067    
068    
069    
070      /**
071       * Creates a new instance of this LDAP post-read response control with the
072       * provided information.
073       *
074       * @param  searchEntry  The search result entry to include in the response
075       *                      control.
076       */
077      public LDAPPostReadResponseControl(SearchResultEntry searchEntry)
078      {
079        super(OID_LDAP_READENTRY_POSTREAD, false,
080              encodeEntry(searchEntry));
081    
082    
083        this.searchEntry = searchEntry;
084      }
085    
086    
087    
088      /**
089       * Creates a new instance of this LDAP post-read response control with the
090       * provided information.
091       *
092       * @param  oid          The OID to use for this control.
093       * @param  isCritical   Indicates whether support for this control should be
094       *                      considered a critical part of the server processing.
095       * @param  searchEntry  The search result entry to include in the response
096       *                      control.
097       */
098      public LDAPPostReadResponseControl(String oid, boolean isCritical,
099                                        SearchResultEntry searchEntry)
100      {
101        super(oid, isCritical, encodeEntry(searchEntry));
102    
103    
104        this.searchEntry = searchEntry;
105      }
106    
107    
108    
109      /**
110       * Creates a new instance of this LDAP post-read response control with the
111       * provided information.
112       *
113       * @param  oid           The OID to use for this control.
114       * @param  isCritical    Indicates whether support for this control should be
115       *                       considered a critical part of the server processing.
116       * @param  searchEntry   The search result entry to include in the response
117       *                       control.
118       * @param  encodedValue  The pre-encoded value for this control.
119       */
120      private LDAPPostReadResponseControl(String oid, boolean isCritical,
121                                          SearchResultEntry searchEntry,
122                                          ASN1OctetString encodedValue)
123      {
124        super(oid, isCritical, encodedValue);
125    
126    
127        this.searchEntry = searchEntry;
128      }
129    
130    
131    
132      /**
133       * Creates a new LDAP post-read response control from the contents of the
134       * provided control.
135       *
136       * @param  control  The generic control containing the information to use to
137       *                  create this LDAP post-read response control.
138       *
139       * @return  The LDAP post-read response control decoded from the provided
140       *          control.
141       *
142       * @throws  LDAPException  If this control cannot be decoded as a valid LDAP
143       *                         post-read response control.
144       */
145      public static LDAPPostReadResponseControl decodeControl(Control control)
146             throws LDAPException
147      {
148        if (! control.hasValue())
149        {
150          Message message = ERR_POSTREADRESP_NO_CONTROL_VALUE.get();
151          throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
152        }
153    
154    
155        ASN1OctetString controlValue = control.getValue();
156        SearchResultEntry searchEntry;
157        try
158        {
159          ASN1Element element = ASN1Element.decode(controlValue.value());
160          SearchResultEntryProtocolOp searchResultEntryProtocolOp =
161               SearchResultEntryProtocolOp.decodeSearchEntry(element);
162          searchEntry = searchResultEntryProtocolOp.toSearchResultEntry();
163        }
164        catch (ASN1Exception ae)
165        {
166          if (debugEnabled())
167          {
168            TRACER.debugCaught(DebugLogLevel.ERROR, ae);
169          }
170    
171          Message message =
172              ERR_POSTREADRESP_CANNOT_DECODE_VALUE.get(ae.getMessage());
173          throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message,
174                                  ae);
175        }
176        catch (LDAPException le)
177        {
178          if (debugEnabled())
179          {
180            TRACER.debugCaught(DebugLogLevel.ERROR, le);
181          }
182    
183          Message message =
184              ERR_POSTREADRESP_CANNOT_DECODE_VALUE.get(le.getMessage());
185          throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message,
186                                  le);
187        }
188    
189        return new LDAPPostReadResponseControl(control.getOID(),
190                                               control.isCritical(), searchEntry,
191                                               controlValue);
192      }
193    
194    
195    
196      /**
197       * Encodes the provided search result entry for use as an attribute value.
198       *
199       * @param  searchEntry  The search result entry to be encoded.
200       *
201       * @return  The ASN.1 octet string containing the encoded control value.
202       */
203      private static ASN1OctetString encodeEntry(SearchResultEntry searchEntry)
204      {
205        SearchResultEntryProtocolOp protocolOp =
206             new SearchResultEntryProtocolOp(searchEntry);
207        return new ASN1OctetString(protocolOp.encode().encode());
208      }
209    
210    
211    
212      /**
213       * Retrieves the search result entry associated with this post-read response
214       * control.
215       *
216       * @return  The search result entry associated with this post-read response
217       *          control.
218       */
219      public SearchResultEntry getSearchEntry()
220      {
221        return searchEntry;
222      }
223    
224    
225    
226      /**
227       * Specifies the search result entry for use with this post-read response
228       * control.
229       *
230       * @param  searchEntry  The search result entry for use with this post-read
231       *                      response control.
232       */
233      public void setSearchEntry(SearchResultEntry searchEntry)
234      {
235        this.searchEntry = searchEntry;
236        setValue(encodeEntry(searchEntry));
237      }
238    
239    
240    
241      /**
242       * Retrieves a string representation of this LDAP post-read response control.
243       *
244       * @return  A string representation of this LDAP post-read response control.
245       */
246      public String toString()
247      {
248        StringBuilder buffer = new StringBuilder();
249        toString(buffer);
250        return buffer.toString();
251      }
252    
253    
254    
255      /**
256       * Appends a string representation of this LDAP post-read response control to
257       * the provided buffer.
258       *
259       * @param  buffer  The buffer to which the information should be appended.
260       */
261      public void toString(StringBuilder buffer)
262      {
263        buffer.append("LDAPPostReadResponseControl(criticality=");
264        buffer.append(isCritical());
265        buffer.append(",entry=");
266        searchEntry.toSingleLineString(buffer);
267        buffer.append(")");
268      }
269    }
270