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}