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.forgerock.i18n.slf4j.LocalizedLogger; 032import org.opends.server.types.*; 033import org.forgerock.opendj.ldap.ResultCode; 034import org.forgerock.opendj.ldap.ByteString; 035import static org.opends.messages.ProtocolMessages.*; 036import static org.opends.server.util.ServerConstants.*; 037 038 039 040/** 041 * This class implements the post-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 after an add, modify, 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 LDAPPostReadRequestControl extends Control 048{ 049 /** ControlDecoder implementation to decode this control from a ByteString. */ 050 private static final class Decoder implements 051 ControlDecoder<LDAPPostReadRequestControl> 052 { 053 @Override 054 public LDAPPostReadRequestControl decode(boolean isCritical, 055 ByteString value) throws DirectoryException 056 { 057 if (value == null) 058 { 059 LocalizableMessage message = ERR_POSTREADREQ_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_POSTREADREQ_CANNOT_DECODE_VALUE.get(ae 079 .getMessage()); 080 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, ae); 081 } 082 083 return new LDAPPostReadRequestControl(isCritical, rawAttributes); 084 } 085 086 087 088 @Override 089 public String getOID() 090 { 091 return OID_LDAP_READENTRY_POSTREAD; 092 } 093 094 } 095 096 097 098 /** The Control Decoder that can be used to decode this control. */ 099 public static final ControlDecoder<LDAPPostReadRequestControl> 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 post-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 LDAPPostReadRequestControl(boolean isCritical, 123 Set<String> rawAttributes) 124 { 125 super(OID_LDAP_READENTRY_POSTREAD, 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 * Creates a new instance of this LDAP post-read request control with the 141 * provided information. 142 * 143 * @param oid 144 * The OID to use for this control. 145 * @param isCritical 146 * Indicates whether support for this control should be considered a 147 * critical part of the server processing. 148 * @param rawAttributes 149 * The set of raw attributes to return in the entry. A null or empty 150 * set will indicates that all user attributes should be returned. 151 */ 152 public LDAPPostReadRequestControl(String oid, boolean isCritical, 153 Set<String> rawAttributes) 154 { 155 super(oid, isCritical); 156 if (rawAttributes == null) 157 { 158 this.rawAttributes = new LinkedHashSet<>(0); 159 } 160 else 161 { 162 this.rawAttributes = rawAttributes; 163 } 164 requestedAttributes = null; 165 } 166 167 168 169 /** 170 * Writes this control's value to an ASN.1 writer. The value (if any) must be 171 * written as an ASN1OctetString. 172 * 173 * @param writer 174 * The ASN.1 output stream to write to. 175 * @throws IOException 176 * If a problem occurs while writing to the stream. 177 */ 178 @Override 179 public void writeValue(ASN1Writer writer) throws IOException 180 { 181 writer.writeStartSequence(ASN1.UNIVERSAL_OCTET_STRING_TYPE); 182 { 183 writer.writeStartSequence(); 184 if (rawAttributes != null) 185 { 186 for (String attr : rawAttributes) 187 { 188 writer.writeOctetString(attr); 189 } 190 } 191 writer.writeEndSequence(); 192 } 193 writer.writeEndSequence(); 194 } 195 196 197 198 /** 199 * Retrieves the raw, unprocessed set of requested attributes. It must not be 200 * altered by the caller without calling <CODE>setRawAttributes</CODE> with 201 * the updated set. 202 * 203 * @return The raw, unprocessed set of attributes. 204 */ 205 public Set<String> getRawAttributes() 206 { 207 return rawAttributes; 208 } 209 210 211 212 /** 213 * Retrieves the set of processed attributes that have been requested for 214 * inclusion in the entry that is returned. 215 * 216 * @return The set of processed attributes that have been requested for 217 * inclusion in the entry that is returned. 218 */ 219 public Set<String> getRequestedAttributes() 220 { 221 if (requestedAttributes == null) 222 { 223 requestedAttributes = normalizedObjectClasses(rawAttributes); 224 } 225 return requestedAttributes; 226 } 227 228 229 230 /** 231 * Appends a string representation of this LDAP post-read request control to 232 * the provided buffer. 233 * 234 * @param buffer 235 * The buffer to which the information should be appended. 236 */ 237 @Override 238 public void toString(StringBuilder buffer) 239 { 240 buffer.append("LDAPPostReadRequestControl(criticality="); 241 buffer.append(isCritical()); 242 buffer.append(",attrs=\""); 243 244 if (!rawAttributes.isEmpty()) 245 { 246 Iterator<String> iterator = rawAttributes.iterator(); 247 buffer.append(iterator.next()); 248 249 while (iterator.hasNext()) 250 { 251 buffer.append(","); 252 buffer.append(iterator.next()); 253 } 254 } 255 256 buffer.append("\")"); 257 } 258}