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