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.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 /** ControlDecoder implementation to decode this control from a ByteString. */ 050 private static final class Decoder implements 051 ControlDecoder<LDAPPreReadRequestControl> 052 { 053 @Override 054 public LDAPPreReadRequestControl decode(boolean isCritical, 055 ByteString value) throws DirectoryException 056 { 057 if (value == null) 058 { 059 LocalizableMessage message = ERR_PREREADREQ_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_PREREADREQ_CANNOT_DECODE_VALUE.get(ae 079 .getMessage()); 080 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, ae); 081 } 082 083 return new LDAPPreReadRequestControl(isCritical, rawAttributes); 084 } 085 086 087 088 @Override 089 public String getOID() 090 { 091 return OID_LDAP_READENTRY_PREREAD; 092 } 093 094 } 095 096 097 098 /** The Control Decoder that can be used to decode this control. */ 099 public static final ControlDecoder<LDAPPreReadRequestControl> 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 pre-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 LDAPPreReadRequestControl(boolean isCritical, 123 Set<String> rawAttributes) 124 { 125 super(OID_LDAP_READENTRY_PREREAD, 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 * Writes this control's value to an ASN.1 writer. The value (if any) must be 141 * written as an ASN1OctetString. 142 * 143 * @param writer 144 * The ASN.1 output stream to write to. 145 * @throws IOException 146 * If a problem occurs while writing to the stream. 147 */ 148 @Override 149 public void writeValue(ASN1Writer writer) throws IOException 150 { 151 writer.writeStartSequence(ASN1.UNIVERSAL_OCTET_STRING_TYPE); 152 { 153 writer.writeStartSequence(); 154 if (rawAttributes != null) 155 { 156 for (String attr : rawAttributes) 157 { 158 writer.writeOctetString(attr); 159 } 160 } 161 writer.writeEndSequence(); 162 } 163 writer.writeEndSequence(); 164 } 165 166 167 168 /** 169 * Retrieves the raw, unprocessed set of requested attributes. It must not be 170 * altered by the caller without calling <CODE>setRawAttributes</CODE> with 171 * the updated set. 172 * 173 * @return The raw, unprocessed set of attributes. 174 */ 175 public Set<String> getRawAttributes() 176 { 177 return rawAttributes; 178 } 179 180 181 182 /** 183 * Retrieves the set of processed attributes that have been requested for 184 * inclusion in the entry that is returned. 185 * 186 * @return The set of processed attributes that have been requested for 187 * inclusion in the entry that is returned. 188 */ 189 public Set<String> getRequestedAttributes() 190 { 191 if (requestedAttributes == null) 192 { 193 requestedAttributes = normalizedObjectClasses(rawAttributes); 194 } 195 return requestedAttributes; 196 } 197 198 199 200 /** 201 * Appends a string representation of this LDAP pre-read request control to 202 * the provided buffer. 203 * 204 * @param buffer 205 * The buffer to which the information should be appended. 206 */ 207 @Override 208 public void toString(StringBuilder buffer) 209 { 210 buffer.append("LDAPPreReadRequestControl(criticality="); 211 buffer.append(isCritical()); 212 buffer.append(",attrs=\""); 213 214 if (!rawAttributes.isEmpty()) 215 { 216 Iterator<String> iterator = rawAttributes.iterator(); 217 buffer.append(iterator.next()); 218 219 while (iterator.hasNext()) 220 { 221 buffer.append(","); 222 buffer.append(iterator.next()); 223 } 224 } 225 226 buffer.append("\")"); 227 } 228}