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 pre-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 a modify, delete, or modify DN operation. 053 */ 054 public class LDAPPreReadResponseControl 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 pre-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 LDAPPreReadResponseControl(SearchResultEntry searchEntry) 078 { 079 super(OID_LDAP_READENTRY_PREREAD, false, 080 encodeEntry(searchEntry)); 081 082 083 this.searchEntry = searchEntry; 084 } 085 086 087 088 /** 089 * Creates a new instance of this LDAP pre-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 LDAPPreReadResponseControl(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 pre-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 LDAPPreReadResponseControl(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 pre-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 pre-read response control. 138 * 139 * @return The LDAP pre-read response control decoded from the provided 140 * control. 141 * 142 * @throws LDAPException If this control cannot be decoded as a valid LDAP 143 * pre-read response control. 144 */ 145 public static LDAPPreReadResponseControl decodeControl(Control control) 146 throws LDAPException 147 { 148 if (! control.hasValue()) 149 { 150 Message message = ERR_PREREADRESP_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_PREREADRESP_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_PREREADRESP_CANNOT_DECODE_VALUE.get(le.getMessage()); 185 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message, 186 le); 187 } 188 189 return new LDAPPreReadResponseControl(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 pre-read response 214 * control. 215 * 216 * @return The search result entry associated with this pre-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 pre-read response 228 * control. 229 * 230 * @param searchEntry The search result entry for use with this pre-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 pre-read response control. 243 * 244 * @return A string representation of this LDAP pre-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 pre-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("LDAPPreReadResponseControl(criticality="); 264 buffer.append(isCritical()); 265 buffer.append(",entry="); 266 searchEntry.toSingleLineString(buffer); 267 buffer.append(")"); 268 } 269 } 270