001/* 002 * Copyright 2009-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2009-2020 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2009-2020 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.protocol; 037 038 039 040import java.util.ArrayList; 041import java.util.Collections; 042import java.util.Iterator; 043import java.util.List; 044 045import com.unboundid.asn1.ASN1Buffer; 046import com.unboundid.asn1.ASN1BufferSequence; 047import com.unboundid.asn1.ASN1Element; 048import com.unboundid.asn1.ASN1OctetString; 049import com.unboundid.asn1.ASN1Sequence; 050import com.unboundid.asn1.ASN1StreamReader; 051import com.unboundid.asn1.ASN1StreamReaderSequence; 052import com.unboundid.ldap.sdk.Control; 053import com.unboundid.ldap.sdk.LDAPException; 054import com.unboundid.ldap.sdk.Modification; 055import com.unboundid.ldap.sdk.ModifyRequest; 056import com.unboundid.ldap.sdk.ResultCode; 057import com.unboundid.util.Debug; 058import com.unboundid.util.InternalUseOnly; 059import com.unboundid.util.NotMutable; 060import com.unboundid.util.StaticUtils; 061import com.unboundid.util.ThreadSafety; 062import com.unboundid.util.ThreadSafetyLevel; 063import com.unboundid.util.Validator; 064 065import static com.unboundid.ldap.protocol.ProtocolMessages.*; 066 067 068 069/** 070 * This class provides an implementation of an LDAP modify request protocol op. 071 */ 072@InternalUseOnly() 073@NotMutable() 074@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 075public final class ModifyRequestProtocolOp 076 implements ProtocolOp 077{ 078 /** 079 * The serial version UID for this serializable class. 080 */ 081 private static final long serialVersionUID = -6294739625253826184L; 082 083 084 085 // The list of modifications for this modify request. 086 private final List<Modification> modifications; 087 088 // The entry DN for this modify request. 089 private final String dn; 090 091 092 093 /** 094 * Creates a new modify request protocol op with the provided information. 095 * 096 * @param dn The entry DN for this modify request. 097 * @param modifications The list of modifications to include in this modify 098 * request. 099 */ 100 public ModifyRequestProtocolOp(final String dn, 101 final List<Modification> modifications) 102 { 103 this.dn = dn; 104 this.modifications = Collections.unmodifiableList(modifications); 105 } 106 107 108 109 /** 110 * Creates a new modify request protocol op from the provided modify request 111 * object. 112 * 113 * @param request The modify request object to use to create this protocol 114 * op. 115 */ 116 public ModifyRequestProtocolOp(final ModifyRequest request) 117 { 118 dn = request.getDN(); 119 modifications = request.getModifications(); 120 } 121 122 123 124 /** 125 * Creates a new modify request protocol op read from the provided ASN.1 126 * stream reader. 127 * 128 * @param reader The ASN.1 stream reader from which to read the modify 129 * request protocol op. 130 * 131 * @throws LDAPException If a problem occurs while reading or parsing the 132 * modify request. 133 */ 134 ModifyRequestProtocolOp(final ASN1StreamReader reader) 135 throws LDAPException 136 { 137 try 138 { 139 reader.beginSequence(); 140 dn = reader.readString(); 141 Validator.ensureNotNull(dn); 142 143 final ArrayList<Modification> mods = new ArrayList<>(5); 144 final ASN1StreamReaderSequence modSequence = reader.beginSequence(); 145 while (modSequence.hasMoreElements()) 146 { 147 mods.add(Modification.readFrom(reader)); 148 } 149 150 modifications = Collections.unmodifiableList(mods); 151 } 152 catch (final LDAPException le) 153 { 154 Debug.debugException(le); 155 throw le; 156 } 157 catch (final Exception e) 158 { 159 Debug.debugException(e); 160 161 throw new LDAPException(ResultCode.DECODING_ERROR, 162 ERR_MODIFY_REQUEST_CANNOT_DECODE.get( 163 StaticUtils.getExceptionMessage(e)), 164 e); 165 } 166 } 167 168 169 170 /** 171 * Retrieves the target entry DN for this modify request. 172 * 173 * @return The target entry DN for this modify request. 174 */ 175 public String getDN() 176 { 177 return dn; 178 } 179 180 181 182 /** 183 * Retrieves the list of modifications for this modify request. 184 * 185 * @return The list of modifications for this modify request. 186 */ 187 public List<Modification> getModifications() 188 { 189 return modifications; 190 } 191 192 193 194 /** 195 * {@inheritDoc} 196 */ 197 @Override() 198 public byte getProtocolOpType() 199 { 200 return LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_REQUEST; 201 } 202 203 204 205 /** 206 * {@inheritDoc} 207 */ 208 @Override() 209 public ASN1Element encodeProtocolOp() 210 { 211 final ArrayList<ASN1Element> modElements = 212 new ArrayList<>(modifications.size()); 213 for (final Modification m : modifications) 214 { 215 modElements.add(m.encode()); 216 } 217 218 return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_REQUEST, 219 new ASN1OctetString(dn), 220 new ASN1Sequence(modElements)); 221 } 222 223 224 225 /** 226 * Decodes the provided ASN.1 element as a modify request protocol op. 227 * 228 * @param element The ASN.1 element to be decoded. 229 * 230 * @return The decoded modify request protocol op. 231 * 232 * @throws LDAPException If the provided ASN.1 element cannot be decoded as 233 * a modify request protocol op. 234 */ 235 public static ModifyRequestProtocolOp decodeProtocolOp( 236 final ASN1Element element) 237 throws LDAPException 238 { 239 try 240 { 241 final ASN1Element[] elements = 242 ASN1Sequence.decodeAsSequence(element).elements(); 243 final String dn = 244 ASN1OctetString.decodeAsOctetString(elements[0]).stringValue(); 245 246 final ASN1Element[] modElements = 247 ASN1Sequence.decodeAsSequence(elements[1]).elements(); 248 final ArrayList<Modification> mods = new ArrayList<>(modElements.length); 249 for (final ASN1Element e : modElements) 250 { 251 mods.add(Modification.decode(ASN1Sequence.decodeAsSequence(e))); 252 } 253 254 return new ModifyRequestProtocolOp(dn, mods); 255 } 256 catch (final Exception e) 257 { 258 Debug.debugException(e); 259 throw new LDAPException(ResultCode.DECODING_ERROR, 260 ERR_MODIFY_REQUEST_CANNOT_DECODE.get( 261 StaticUtils.getExceptionMessage(e)), 262 e); 263 } 264 } 265 266 267 268 /** 269 * {@inheritDoc} 270 */ 271 @Override() 272 public void writeTo(final ASN1Buffer writer) 273 { 274 final ASN1BufferSequence opSequence = 275 writer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_REQUEST); 276 writer.addOctetString(dn); 277 278 final ASN1BufferSequence modSequence = writer.beginSequence(); 279 for (final Modification m : modifications) 280 { 281 m.writeTo(writer); 282 } 283 modSequence.end(); 284 opSequence.end(); 285 } 286 287 288 289 /** 290 * Creates a modify request from this protocol op. 291 * 292 * @param controls The set of controls to include in the modify request. 293 * It may be empty or {@code null} if no controls should be 294 * included. 295 * 296 * @return The modify request that was created. 297 */ 298 public ModifyRequest toModifyRequest(final Control... controls) 299 { 300 return new ModifyRequest(dn, modifications, controls); 301 } 302 303 304 305 /** 306 * Retrieves a string representation of this protocol op. 307 * 308 * @return A string representation of this protocol op. 309 */ 310 @Override() 311 public String toString() 312 { 313 final StringBuilder buffer = new StringBuilder(); 314 toString(buffer); 315 return buffer.toString(); 316 } 317 318 319 320 /** 321 * {@inheritDoc} 322 */ 323 @Override() 324 public void toString(final StringBuilder buffer) 325 { 326 buffer.append("ModifyRequestProtocolOp(dn='"); 327 buffer.append(dn); 328 buffer.append("', mods={"); 329 330 final Iterator<Modification> iterator = modifications.iterator(); 331 while (iterator.hasNext()) 332 { 333 iterator.next().toString(buffer); 334 if (iterator.hasNext()) 335 { 336 buffer.append(','); 337 } 338 } 339 340 buffer.append("})"); 341 } 342}