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.protocols.ldap; 018 019import java.io.IOException; 020import java.util.ArrayList; 021import java.util.Iterator; 022import java.util.List; 023 024import org.forgerock.i18n.slf4j.LocalizedLogger; 025import org.forgerock.opendj.io.ASN1Writer; 026import org.forgerock.opendj.ldap.ByteString; 027import org.opends.server.types.RawAttribute; 028import org.opends.server.util.Base64; 029 030import static org.opends.server.protocols.ldap.LDAPConstants.*; 031import static org.opends.server.util.ServerConstants.*; 032import static org.opends.server.util.StaticUtils.*; 033 034/** 035 * This class defines the structures and methods for an LDAP add request 036 * protocol op, which is used to add a new entry to the Directory Server. 037 */ 038public class AddRequestProtocolOp 039 extends ProtocolOp 040{ 041 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 042 043 /** The set of attributes for this add request. */ 044 private List<RawAttribute> attributes; 045 046 /** The DN for this add request. */ 047 private ByteString dn; 048 049 050 051 /** 052 * Creates a new LDAP add request protocol op with the specified DN and no 053 * attributes. 054 * 055 * @param dn The DN for this add request. 056 */ 057 public AddRequestProtocolOp(ByteString dn) 058 { 059 this.dn = dn; 060 this.attributes = new ArrayList<>(); 061 } 062 063 064 065 /** 066 * Creates a new LDAP add request protocol op with the specified DN and set of 067 * attributes. 068 * 069 * @param dn The DN for this add request. 070 * @param attributes The set of attributes for this add request. 071 */ 072 public AddRequestProtocolOp(ByteString dn, List<RawAttribute> attributes) 073 { 074 this.dn = dn; 075 076 if (attributes == null) 077 { 078 this.attributes = new ArrayList<>(); 079 } 080 else 081 { 082 this.attributes = attributes; 083 } 084 } 085 086 087 088 /** 089 * Retrieves the DN for this add request. 090 * 091 * @return The DN for this add request. 092 */ 093 public ByteString getDN() 094 { 095 return dn; 096 } 097 098 099 /** 100 * Retrieves the set of attributes for this add request. The returned list 101 * may be altered by the caller. 102 * 103 * @return The set of attributes for this add request. 104 */ 105 public List<RawAttribute> getAttributes() 106 { 107 return attributes; 108 } 109 110 111 112 /** 113 * Retrieves the BER type for this protocol op. 114 * 115 * @return The BER type for this protocol op. 116 */ 117 @Override 118 public byte getType() 119 { 120 return OP_TYPE_ADD_REQUEST; 121 } 122 123 124 125 /** 126 * Retrieves the name for this protocol op type. 127 * 128 * @return The name for this protocol op type. 129 */ 130 @Override 131 public String getProtocolOpName() 132 { 133 return "Add Request"; 134 } 135 136 /** 137 * Writes this protocol op to an ASN.1 output stream. 138 * 139 * @param stream The ASN.1 output stream to write to. 140 * @throws IOException If a problem occurs while writing to the stream. 141 */ 142 @Override 143 public void write(ASN1Writer stream) throws IOException 144 { 145 stream.writeStartSequence(OP_TYPE_ADD_REQUEST); 146 stream.writeOctetString(dn); 147 148 // Write the attributes 149 stream.writeStartSequence(); 150 for(RawAttribute attr : attributes) 151 { 152 attr.write(stream); 153 } 154 stream.writeEndSequence(); 155 156 stream.writeEndSequence(); 157 } 158 159 160 161 /** 162 * Appends a string representation of this LDAP protocol op to the provided 163 * buffer. 164 * 165 * @param buffer The buffer to which the string should be appended. 166 */ 167 @Override 168 public void toString(StringBuilder buffer) 169 { 170 buffer.append("AddRequest(dn="); 171 buffer.append(dn); 172 buffer.append(", attrs={"); 173 174 if (! attributes.isEmpty()) 175 { 176 Iterator<RawAttribute> iterator = attributes.iterator(); 177 iterator.next().toString(buffer); 178 179 while (iterator.hasNext()) 180 { 181 buffer.append(", "); 182 iterator.next().toString(buffer); 183 } 184 } 185 186 buffer.append("})"); 187 } 188 189 190 191 /** 192 * Appends a multi-line string representation of this LDAP protocol op to the 193 * provided buffer. 194 * 195 * @param buffer The buffer to which the information should be appended. 196 * @param indent The number of spaces from the margin that the lines should 197 * be indented. 198 */ 199 @Override 200 public void toString(StringBuilder buffer, int indent) 201 { 202 StringBuilder indentBuf = new StringBuilder(indent); 203 for (int i=0 ; i < indent; i++) 204 { 205 indentBuf.append(' '); 206 } 207 208 buffer.append(indentBuf); 209 buffer.append("Add Request"); 210 buffer.append(EOL); 211 212 buffer.append(indentBuf); 213 buffer.append(" DN: "); 214 buffer.append(dn); 215 buffer.append(EOL); 216 217 buffer.append(" Attributes:"); 218 buffer.append(EOL); 219 220 for (RawAttribute attribute : attributes) 221 { 222 attribute.toString(buffer, indent+4); 223 } 224 } 225 226 227 228 /** 229 * Appends an LDIF representation of the entry to the provided buffer. 230 * 231 * @param buffer The buffer to which the entry should be appended. 232 * @param wrapColumn The column at which long lines should be wrapped. 233 */ 234 public void toLDIF(StringBuilder buffer, int wrapColumn) 235 { 236 // Add the DN to the buffer. 237 String dnString; 238 int colsRemaining; 239 if (needsBase64Encoding(dn)) 240 { 241 dnString = Base64.encode(dn); 242 buffer.append("dn:: "); 243 244 colsRemaining = wrapColumn - 5; 245 } 246 else 247 { 248 dnString = dn.toString(); 249 buffer.append("dn: "); 250 251 colsRemaining = wrapColumn - 4; 252 } 253 254 int dnLength = dnString.length(); 255 if (dnLength <= colsRemaining || colsRemaining <= 0) 256 { 257 buffer.append(dnString); 258 buffer.append(EOL); 259 } 260 else 261 { 262 buffer.append(dnString, 0, colsRemaining); 263 buffer.append(EOL); 264 265 int startPos = colsRemaining; 266 while (dnLength - startPos > wrapColumn - 1) 267 { 268 buffer.append(" "); 269 buffer.append(dnString, startPos, startPos+wrapColumn-1); 270 buffer.append(EOL); 271 272 startPos += wrapColumn-1; 273 } 274 275 if (startPos < dnLength) 276 { 277 buffer.append(" "); 278 buffer.append(dnString.substring(startPos)); 279 buffer.append(EOL); 280 } 281 } 282 283 284 // Add the attributes to the buffer. 285 for (RawAttribute a : attributes) 286 { 287 String name = a.getAttributeType(); 288 int nameLength = name.length(); 289 290 for (ByteString v : a.getValues()) 291 { 292 String valueString; 293 if (needsBase64Encoding(v)) 294 { 295 valueString = Base64.encode(v); 296 buffer.append(name); 297 buffer.append(":: "); 298 299 colsRemaining = wrapColumn - nameLength - 3; 300 } 301 else 302 { 303 valueString = v.toString(); 304 buffer.append(name); 305 buffer.append(": "); 306 307 colsRemaining = wrapColumn - nameLength - 2; 308 } 309 310 int valueLength = valueString.length(); 311 if (valueLength <= colsRemaining || colsRemaining <= 0) 312 { 313 buffer.append(valueString); 314 buffer.append(EOL); 315 } 316 else 317 { 318 buffer.append(valueString, 0, colsRemaining); 319 buffer.append(EOL); 320 321 int startPos = colsRemaining; 322 while (valueLength - startPos > wrapColumn - 1) 323 { 324 buffer.append(" "); 325 buffer.append(valueString, startPos, startPos+wrapColumn-1); 326 buffer.append(EOL); 327 328 startPos += wrapColumn-1; 329 } 330 331 if (startPos < valueLength) 332 { 333 buffer.append(" "); 334 buffer.append(valueString.substring(startPos)); 335 buffer.append(EOL); 336 } 337 } 338 } 339 } 340 341 342 // Make sure to add an extra blank line to ensure that there will be one 343 // between this entry and the next. 344 buffer.append(EOL); 345 } 346} 347