001/* 002 * Copyright 2009-2022 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2009-2022 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-2022 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.sdk.controls; 037 038 039 040import com.unboundid.ldap.sdk.Control; 041import com.unboundid.ldap.sdk.LDAPException; 042import com.unboundid.ldap.sdk.ResultCode; 043import com.unboundid.util.NotMutable; 044import com.unboundid.util.NotNull; 045import com.unboundid.util.ThreadSafety; 046import com.unboundid.util.ThreadSafetyLevel; 047 048import static com.unboundid.ldap.sdk.controls.ControlMessages.*; 049 050 051 052/** 053 * This class provides an implementation of the permissive modify request 054 * control, which is supported by a number of servers and may be included in a 055 * modify request to indicate that the server should not reject a modify 056 * request which attempts to add an attribute value which already exists or 057 * remove an attribute value which does not exist. Normally, such modification 058 * attempts would be rejected. 059 * <BR><BR> 060 * The OID for this control is "1.2.840.113556.1.4.1413". It does not have a 061 * value. 062 * <BR><BR> 063 * <H2>Example</H2> 064 * The following example demonstrates the use of the permissive modify request 065 * control to process a modification that attempts to add an attribute value 066 * to an entry that already contains that value. 067 * <PRE> 068 * // Ensure that we start with a known description value in the test entry 069 * // by using a replace to overwrite any existing value(s). 070 * ModifyRequest replaceRequest = new ModifyRequest( 071 * "uid=test.user,ou=People,dc=example,dc=com", 072 * new Modification(ModificationType.REPLACE, "description", "value")); 073 * LDAPResult replaceResult = connection.modify(replaceRequest); 074 * 075 * // Create a modify request that will attempt to add the value that already 076 * // exists. If we attempt to do this without the permissive modify control, 077 * // the attempt should fail. 078 * ModifyRequest addExistingValueRequest = new ModifyRequest( 079 * "uid=test.user,ou=People,dc=example,dc=com", 080 * new Modification(ModificationType.ADD, "description", "value")); 081 * LDAPResult addExistingValueResultWithoutControl; 082 * try 083 * { 084 * addExistingValueResultWithoutControl = 085 * connection.modify(addExistingValueRequest); 086 * // We shouldn't get here because the attempt to add the existing value 087 * // should fail. 088 * } 089 * catch (LDAPException le) 090 * { 091 * // We expected this failure because the value we're trying to add already 092 * // exists in the entry. 093 * addExistingValueResultWithoutControl = le.toLDAPResult(); 094 * ResultCode resultCode = le.getResultCode(); 095 * String errorMessageFromServer = le.getDiagnosticMessage(); 096 * } 097 * 098 * // Update the modify request to include the permissive modify request 099 * // control, and re-send the request. The operation should now succeed. 100 * addExistingValueRequest.addControl(new PermissiveModifyRequestControl()); 101 * LDAPResult addExistingValueResultWithControl; 102 * try 103 * { 104 * addExistingValueResultWithControl = 105 * connection.modify(addExistingValueRequest); 106 * // If we've gotten here, then the modification was successful. 107 * } 108 * catch (LDAPException le) 109 * { 110 * // If we've gotten here, then the modification failed for some reason. 111 * addExistingValueResultWithControl = le.toLDAPResult(); 112 * ResultCode resultCode = le.getResultCode(); 113 * String errorMessageFromServer = le.getDiagnosticMessage(); 114 * } 115 * </PRE> 116 */ 117@NotMutable() 118@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 119public final class PermissiveModifyRequestControl 120 extends Control 121{ 122 /** 123 * The OID (1.2.840.113556.1.4.1413) for the permissive modify request 124 * control. 125 */ 126 @NotNull public static final String PERMISSIVE_MODIFY_REQUEST_OID = 127 "1.2.840.113556.1.4.1413"; 128 129 130 131 /** 132 * The serial version UID for this serializable class. 133 */ 134 private static final long serialVersionUID = -2599039772002106760L; 135 136 137 138 /** 139 * Creates a new permissive modify request control. The control will not be 140 * marked critical. 141 */ 142 public PermissiveModifyRequestControl() 143 { 144 super(PERMISSIVE_MODIFY_REQUEST_OID, false, null); 145 } 146 147 148 149 /** 150 * Creates a new permissive modify request control. 151 * 152 * @param isCritical Indicates whether the control should be marked 153 * critical. 154 */ 155 public PermissiveModifyRequestControl(final boolean isCritical) 156 { 157 super(PERMISSIVE_MODIFY_REQUEST_OID, isCritical, null); 158 } 159 160 161 162 /** 163 * Creates a new permissive modify request control which is decoded from the 164 * provided generic control. 165 * 166 * @param control The generic control to be decoded as a permissive modify 167 * request control. 168 * 169 * @throws LDAPException If the provided control cannot be decoded as a 170 * permissive modify request control. 171 */ 172 public PermissiveModifyRequestControl(@NotNull final Control control) 173 throws LDAPException 174 { 175 super(control); 176 177 if (control.hasValue()) 178 { 179 throw new LDAPException(ResultCode.DECODING_ERROR, 180 ERR_PERMISSIVE_MODIFY_HAS_VALUE.get()); 181 } 182 } 183 184 185 186 /** 187 * {@inheritDoc} 188 */ 189 @Override() 190 @NotNull() 191 public String getControlName() 192 { 193 return INFO_CONTROL_NAME_PERMISSIVE_MODIFY_REQUEST.get(); 194 } 195 196 197 198 /** 199 * {@inheritDoc} 200 */ 201 @Override() 202 public void toString(@NotNull final StringBuilder buffer) 203 { 204 buffer.append("PermissiveModifyRequestControl(isCritical="); 205 buffer.append(isCritical()); 206 buffer.append(')'); 207 } 208}