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.protocols.ldap; 028 import org.opends.messages.Message; 029 030 031 032 import java.util.ArrayList; 033 import java.util.Iterator; 034 035 import org.opends.server.protocols.asn1.ASN1Element; 036 import org.opends.server.protocols.asn1.ASN1OctetString; 037 import org.opends.server.protocols.asn1.ASN1Sequence; 038 import org.opends.server.types.DebugLogLevel; 039 import org.opends.server.types.LDAPException; 040 import org.opends.server.types.RawModification; 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.protocols.ldap.LDAPConstants.*; 046 import static org.opends.server.protocols.ldap.LDAPResultCode.*; 047 import static org.opends.server.util.ServerConstants.*; 048 049 050 /** 051 * This class defines the structures and methods for an LDAP modify request 052 * protocol op, which is used to alter the contents of an entry in the Directory 053 * Server. 054 */ 055 public class ModifyRequestProtocolOp 056 extends ProtocolOp 057 { 058 /** 059 * The tracer object for the debug logger. 060 */ 061 private static final DebugTracer TRACER = getTracer(); 062 063 // The set of modifications for this modify request. 064 private ArrayList<RawModification> modifications; 065 066 // The DN for this modify request. 067 private ASN1OctetString dn; 068 069 070 071 /** 072 * Creates a new LDAP modify request protocol op with the specified DN and no 073 * modifications. 074 * 075 * @param dn The DN for this modify request. 076 */ 077 public ModifyRequestProtocolOp(ASN1OctetString dn) 078 { 079 this.dn = dn; 080 this.modifications = new ArrayList<RawModification>(); 081 } 082 083 084 085 /** 086 * Creates a new LDAP modify request protocol op with the specified DN and set 087 * of modifications. 088 * 089 * @param dn The DN for this modify request. 090 * @param modifications The set of modifications for this modify request. 091 */ 092 public ModifyRequestProtocolOp(ASN1OctetString dn, 093 ArrayList<RawModification> modifications) 094 { 095 this.dn = dn; 096 097 if (modifications == null) 098 { 099 this.modifications = new ArrayList<RawModification>(); 100 } 101 else 102 { 103 this.modifications = modifications; 104 } 105 } 106 107 108 109 /** 110 * Retrieves the DN for this modify request. 111 * 112 * @return The DN for this modify request. 113 */ 114 public ASN1OctetString getDN() 115 { 116 return dn; 117 } 118 119 120 121 /** 122 * Specifies the DN for this modify request. 123 * 124 * @param dn The DN for this modify request. 125 */ 126 public void setDN(ASN1OctetString dn) 127 { 128 this.dn = dn; 129 } 130 131 132 133 /** 134 * Retrieves the set of modifications for this modify request. The returned 135 * list may be altered by the caller. 136 * 137 * @return The set of modifications for this modify request. 138 */ 139 public ArrayList<RawModification> getModifications() 140 { 141 return modifications; 142 } 143 144 145 146 /** 147 * Retrieves the BER type for this protocol op. 148 * 149 * @return The BER type for this protocol op. 150 */ 151 public byte getType() 152 { 153 return OP_TYPE_MODIFY_REQUEST; 154 } 155 156 157 158 /** 159 * Retrieves the name for this protocol op type. 160 * 161 * @return The name for this protocol op type. 162 */ 163 public String getProtocolOpName() 164 { 165 return "Modify Request"; 166 } 167 168 169 170 /** 171 * Encodes this protocol op to an ASN.1 element suitable for including in an 172 * LDAP message. 173 * 174 * @return The ASN.1 element containing the encoded protocol op. 175 */ 176 public ASN1Element encode() 177 { 178 ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2); 179 elements.add(dn); 180 181 182 ArrayList<ASN1Element> modElements = 183 new ArrayList<ASN1Element>(modifications.size()); 184 for (RawModification mod : modifications) 185 { 186 modElements.add(mod.encode()); 187 } 188 elements.add(new ASN1Sequence(modElements)); 189 190 191 return new ASN1Sequence(OP_TYPE_MODIFY_REQUEST, elements); 192 } 193 194 195 196 /** 197 * Decodes the provided ASN.1 element as an LDAP modify request protocol op. 198 * 199 * @param element The ASN.1 element to be decoded. 200 * 201 * @return The decoded modify request protocol op. 202 * 203 * @throws LDAPException If a problem occurs while decoding the provided 204 * ASN.1 element as an LDAP modify request protocol 205 * op. 206 */ 207 public static ModifyRequestProtocolOp decodeModifyRequest(ASN1Element element) 208 throws LDAPException 209 { 210 ArrayList<ASN1Element> elements; 211 try 212 { 213 elements = element.decodeAsSequence().elements(); 214 } 215 catch (Exception e) 216 { 217 if (debugEnabled()) 218 { 219 TRACER.debugCaught(DebugLogLevel.ERROR, e); 220 } 221 222 Message message = 223 ERR_LDAP_MODIFY_REQUEST_DECODE_SEQUENCE.get(String.valueOf(e)); 224 throw new LDAPException(PROTOCOL_ERROR, message, e); 225 } 226 227 228 int numElements = elements.size(); 229 if (numElements != 2) 230 { 231 Message message = 232 ERR_LDAP_MODIFY_REQUEST_DECODE_INVALID_ELEMENT_COUNT.get(numElements); 233 throw new LDAPException(PROTOCOL_ERROR, message); 234 } 235 236 237 ASN1OctetString dn; 238 try 239 { 240 dn = elements.get(0).decodeAsOctetString(); 241 } 242 catch (Exception e) 243 { 244 if (debugEnabled()) 245 { 246 TRACER.debugCaught(DebugLogLevel.ERROR, e); 247 } 248 249 Message message = 250 ERR_LDAP_MODIFY_REQUEST_DECODE_DN.get(String.valueOf(e)); 251 throw new LDAPException(PROTOCOL_ERROR, message, e); 252 } 253 254 255 256 ArrayList<RawModification> modifications; 257 try 258 { 259 ArrayList<ASN1Element> modElements = 260 elements.get(1).decodeAsSequence().elements(); 261 modifications = new ArrayList<RawModification>(modElements.size()); 262 for (ASN1Element e : modElements) 263 { 264 modifications.add(LDAPModification.decode(e)); 265 } 266 } 267 catch (Exception e) 268 { 269 if (debugEnabled()) 270 { 271 TRACER.debugCaught(DebugLogLevel.ERROR, e); 272 } 273 274 Message message = 275 ERR_LDAP_MODIFY_REQUEST_DECODE_MODS.get(String.valueOf(e)); 276 throw new LDAPException(PROTOCOL_ERROR, message, e); 277 } 278 279 280 return new ModifyRequestProtocolOp(dn, modifications); 281 } 282 283 284 285 /** 286 * Appends a string representation of this LDAP protocol op to the provided 287 * buffer. 288 * 289 * @param buffer The buffer to which the string should be appended. 290 */ 291 public void toString(StringBuilder buffer) 292 { 293 buffer.append("ModifyRequest(dn="); 294 dn.toString(buffer); 295 buffer.append(", mods={"); 296 297 if (! modifications.isEmpty()) 298 { 299 Iterator<RawModification> iterator = modifications.iterator(); 300 iterator.next().toString(buffer); 301 302 while (iterator.hasNext()) 303 { 304 buffer.append(", "); 305 iterator.next().toString(buffer); 306 } 307 } 308 309 buffer.append("})"); 310 } 311 312 313 314 /** 315 * Appends a multi-line string representation of this LDAP protocol op to the 316 * provided buffer. 317 * 318 * @param buffer The buffer to which the information should be appended. 319 * @param indent The number of spaces from the margin that the lines should 320 * be indented. 321 */ 322 public void toString(StringBuilder buffer, int indent) 323 { 324 StringBuilder indentBuf = new StringBuilder(indent); 325 for (int i=0 ; i < indent; i++) 326 { 327 indentBuf.append(' '); 328 } 329 330 buffer.append(indentBuf); 331 buffer.append("Modify Request"); 332 buffer.append(EOL); 333 334 buffer.append(indentBuf); 335 buffer.append(" DN: "); 336 dn.toString(buffer); 337 buffer.append(EOL); 338 339 buffer.append(" Modifications:"); 340 buffer.append(EOL); 341 342 for (RawModification mod : modifications) 343 { 344 mod.toString(buffer, indent+4); 345 } 346 } 347 } 348