001 /*
002 * Copyright 2012-2015 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2015 UnboundID Corp.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021 package com.unboundid.ldap.sdk.unboundidds.controls;
022
023
024
025 import java.util.ArrayList;
026 import java.util.Arrays;
027 import java.util.Collection;
028 import java.util.Collections;
029 import java.util.EnumSet;
030 import java.util.Iterator;
031 import java.util.Set;
032
033 import com.unboundid.asn1.ASN1Element;
034 import com.unboundid.asn1.ASN1Enumerated;
035 import com.unboundid.asn1.ASN1OctetString;
036 import com.unboundid.asn1.ASN1Sequence;
037 import com.unboundid.ldap.sdk.Control;
038 import com.unboundid.ldap.sdk.LDAPException;
039 import com.unboundid.ldap.sdk.ResultCode;
040 import com.unboundid.util.Debug;
041 import com.unboundid.util.NotMutable;
042 import com.unboundid.util.StaticUtils;
043 import com.unboundid.util.ThreadSafety;
044 import com.unboundid.util.ThreadSafetyLevel;
045 import com.unboundid.util.Validator;
046
047 import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*;
048
049
050
051 /**
052 * <BLOCKQUOTE>
053 * <B>NOTE:</B> This class is part of the Commercial Edition of the UnboundID
054 * LDAP SDK for Java. It is not available for use in applications that
055 * include only the Standard Edition of the LDAP SDK, and is not supported for
056 * use in conjunction with non-UnboundID products.
057 * </BLOCKQUOTE>
058 * This class provides an implementation of a control that can be used to
059 * indicate that the server should suppress the update to one or more
060 * operational attributes for the associated request.
061 * <BR><BR>
062 * The request control has an OID of 1.3.6.1.4.1.30221.2.5.27, and the
063 * criticality may be either {@code true} or {@code false}. The control must
064 * have a value with the following encoding:
065 * <PRE>
066 * SuppressOperationalAttributeUpdateRequestValue ::= SEQUENCE {
067 * suppressTypes [0] SEQUENCE OF ENUMERATED {
068 * last-access-time (0),
069 * last-login-time (1),
070 * last-login-ip (2),
071 * lastmod (3),
072 * ... },
073 * ... }
074 * </PRE>
075 */
076 @NotMutable()
077 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
078 public final class SuppressOperationalAttributeUpdateRequestControl
079 extends Control
080 {
081 /**
082 * The OID (1.3.6.1.4.1.30221.2.5.27) for the suppress operational attribute
083 * update request control.
084 */
085 public static final String SUPPRESS_OP_ATTR_UPDATE_REQUEST_OID =
086 "1.3.6.1.4.1.30221.2.5.27";
087
088
089
090 /**
091 * The BER type to use for the set of suppress types.
092 */
093 private static final byte TYPE_SUPPRESS_TYPES = (byte) 0x80;
094
095
096 /**
097 * The serial version UID for this serializable class.
098 */
099 private static final long serialVersionUID = 4603958484615351672L;
100
101
102
103 // The set of suppress types to include in the control.
104 private final Set<SuppressType> suppressTypes;
105
106
107
108 /**
109 * Creates a new instance of this control that will suppress updates to the
110 * specified kinds of operational attributes. It will not be critical.
111 *
112 * @param suppressTypes The set of suppress types to include in the control.
113 * It must not be {@code null} or empty.
114 */
115 public SuppressOperationalAttributeUpdateRequestControl(
116 final SuppressType... suppressTypes)
117 {
118 this(false, suppressTypes);
119 }
120
121
122
123 /**
124 * Creates a new instance of this control that will suppress updates to the
125 * specified kinds of operational attributes. It will not be critical.
126 *
127 * @param suppressTypes The set of suppress types to include in the control.
128 * It must not be {@code null} or empty.
129 */
130 public SuppressOperationalAttributeUpdateRequestControl(
131 final Collection<SuppressType> suppressTypes)
132 {
133 this(false, suppressTypes);
134 }
135
136
137
138 /**
139 * Creates a new instance of this control that will suppress updates to the
140 * specified kinds of operational attributes.
141 *
142 * @param isCritical Indicates whether the control should be considered
143 * critical.
144 * @param suppressTypes The set of suppress types to include in the control.
145 * It must not be {@code null} or empty.
146 */
147 public SuppressOperationalAttributeUpdateRequestControl(
148 final boolean isCritical, final SuppressType... suppressTypes)
149 {
150 this(isCritical, Arrays.asList(suppressTypes));
151 }
152
153
154
155 /**
156 * Creates a new instance of this control that will suppress updates to the
157 * specified kinds of operational attributes.
158 *
159 * @param isCritical Indicates whether the control should be considered
160 * critical.
161 * @param suppressTypes The set of suppress types to include in the control.
162 * It must not be {@code null} or empty.
163 */
164 public SuppressOperationalAttributeUpdateRequestControl(
165 final boolean isCritical,
166 final Collection<SuppressType> suppressTypes)
167 {
168 super(SUPPRESS_OP_ATTR_UPDATE_REQUEST_OID, isCritical,
169 encodeValue(suppressTypes));
170
171 Validator.ensureFalse(suppressTypes.isEmpty());
172
173 final EnumSet<SuppressType> s = EnumSet.noneOf(SuppressType.class);
174 for (final SuppressType t : suppressTypes)
175 {
176 s.add(t);
177 }
178
179 this.suppressTypes = Collections.unmodifiableSet(s);
180 }
181
182
183
184 /**
185 * Decodes the provided generic control as a suppress operational attribute
186 * update request control.
187 *
188 * @param control The generic control to be decoded as a suppress
189 * operational attribute update request control.
190 *
191 * @throws LDAPException If a problem is encountered while attempting to
192 * decode the provided control.
193 */
194 public SuppressOperationalAttributeUpdateRequestControl(final Control control)
195 throws LDAPException
196 {
197 super(control);
198
199 final ASN1OctetString value = control.getValue();
200 if (value == null)
201 {
202 throw new LDAPException(ResultCode.DECODING_ERROR,
203 ERR_SUPPRESS_OP_ATTR_UPDATE_REQUEST_MISSING_VALUE.get());
204 }
205
206 try
207 {
208 final ASN1Sequence valueSequence =
209 ASN1Sequence.decodeAsSequence(value.getValue());
210 final ASN1Sequence suppressTypesSequence =
211 ASN1Sequence.decodeAsSequence(valueSequence.elements()[0]);
212
213 final EnumSet<SuppressType> s = EnumSet.noneOf(SuppressType.class);
214 for (final ASN1Element e : suppressTypesSequence.elements())
215 {
216 final ASN1Enumerated ae = ASN1Enumerated.decodeAsEnumerated(e);
217 final SuppressType t = SuppressType.valueOf(ae.intValue());
218 if (t == null)
219 {
220 throw new LDAPException(ResultCode.DECODING_ERROR,
221 ERR_SUPPRESS_OP_ATTR_UNRECOGNIZED_SUPPRESS_TYPE.get(
222 ae.intValue()));
223 }
224 else
225 {
226 s.add(t);
227 }
228 }
229
230 suppressTypes = Collections.unmodifiableSet(s);
231 }
232 catch (final LDAPException le)
233 {
234 Debug.debugException(le);
235 throw le;
236 }
237 catch (final Exception e)
238 {
239 Debug.debugException(e);
240 throw new LDAPException(ResultCode.DECODING_ERROR,
241 ERR_SUPPRESS_OP_ATTR_UPDATE_REQUEST_CANNOT_DECODE.get(
242 StaticUtils.getExceptionMessage(e)),
243 e);
244 }
245 }
246
247
248
249 /**
250 * Encodes the provided information into an octet string suitable for use as
251 * the value of this control.
252 *
253 * @param suppressTypes The set of suppress types to include in the control.
254 * It must not be {@code null} or empty.
255 *
256 * @return The ASN.1 octet string containing the encoded value.
257 */
258 private static ASN1OctetString encodeValue(
259 final Collection<SuppressType> suppressTypes)
260 {
261 final ArrayList<ASN1Element> suppressTypeElements =
262 new ArrayList<ASN1Element>(suppressTypes.size());
263 for (final SuppressType t : suppressTypes)
264 {
265 suppressTypeElements.add(new ASN1Enumerated(t.intValue()));
266 }
267
268 final ASN1Sequence valueSequence = new ASN1Sequence(
269 new ASN1Sequence(TYPE_SUPPRESS_TYPES, suppressTypeElements));
270 return new ASN1OctetString(valueSequence.encode());
271 }
272
273
274
275 /**
276 * Retrieves the set of suppress types for this control.
277 *
278 * @return The set of suppress types for this control.
279 */
280 public Set<SuppressType> getSuppressTypes()
281 {
282 return suppressTypes;
283 }
284
285
286
287 /**
288 * {@inheritDoc}
289 */
290 @Override()
291 public String getControlName()
292 {
293 return INFO_CONTROL_NAME_SUPPRESS_OP_ATTR_UPDATE_REQUEST.get();
294 }
295
296
297
298 /**
299 * {@inheritDoc}
300 */
301 @Override()
302 public void toString(final StringBuilder buffer)
303 {
304 buffer.append("SuppressOperationalAttributeUpdateRequestControl(" +
305 "isCritical=");
306 buffer.append(isCritical());
307 buffer.append(", suppressTypes={");
308
309 final Iterator<SuppressType> iterator = suppressTypes.iterator();
310 while (iterator.hasNext())
311 {
312 buffer.append(iterator.next().name());
313 if (iterator.hasNext())
314 {
315 buffer.append(',');
316 }
317 }
318
319 buffer.append("})");
320 }
321 }