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 legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2010 Sun Microsystems, Inc. 025 */ 026package org.forgerock.opendj.ldap.controls; 027 028import static com.forgerock.opendj.ldap.CoreMessages.ERR_SUBTREE_DELETE_CONTROL_BAD_OID; 029import static com.forgerock.opendj.ldap.CoreMessages.ERR_SUBTREE_DELETE_INVALID_CONTROL_VALUE; 030 031import org.forgerock.i18n.LocalizableMessage; 032import org.forgerock.opendj.ldap.ByteString; 033import org.forgerock.opendj.ldap.DecodeException; 034import org.forgerock.opendj.ldap.DecodeOptions; 035 036import org.forgerock.util.Reject; 037 038/** 039 * The tree delete request control as defined in draft-armijo-ldap-treedelete. 040 * This control allows a client to delete an entire subtree of a container entry 041 * in a single delete operation. 042 * 043 * <pre> 044 * Connection connection = ...; 045 * String baseDN = ...; 046 * 047 * DeleteRequest request = 048 * Requests.newDeleteRequest(baseDN) 049 * .addControl(SubtreeDeleteRequestControl.newControl(true)); 050 * connection.delete(request); 051 * </pre> 052 * 053 * @see <a 054 * href="http://tools.ietf.org/html/draft-armijo-ldap-treedelete">draft-armijo-ldap-treedelete 055 * - Tree Delete Control </a> 056 */ 057public final class SubtreeDeleteRequestControl implements Control { 058 /** 059 * The OID for the subtree delete request control. 060 */ 061 public static final String OID = "1.2.840.113556.1.4.805"; 062 063 private static final SubtreeDeleteRequestControl CRITICAL_INSTANCE = 064 new SubtreeDeleteRequestControl(true); 065 066 private static final SubtreeDeleteRequestControl NONCRITICAL_INSTANCE = 067 new SubtreeDeleteRequestControl(false); 068 069 /** 070 * A decoder which can be used for decoding the sub-tree delete request 071 * control. 072 */ 073 public static final ControlDecoder<SubtreeDeleteRequestControl> DECODER = 074 new ControlDecoder<SubtreeDeleteRequestControl>() { 075 076 public SubtreeDeleteRequestControl decodeControl(final Control control, 077 final DecodeOptions options) throws DecodeException { 078 Reject.ifNull(control); 079 080 if (control instanceof SubtreeDeleteRequestControl) { 081 return (SubtreeDeleteRequestControl) control; 082 } 083 084 if (!control.getOID().equals(OID)) { 085 final LocalizableMessage message = 086 ERR_SUBTREE_DELETE_CONTROL_BAD_OID.get(control.getOID(), OID); 087 throw DecodeException.error(message); 088 } 089 090 if (control.hasValue()) { 091 final LocalizableMessage message = 092 ERR_SUBTREE_DELETE_INVALID_CONTROL_VALUE.get(); 093 throw DecodeException.error(message); 094 } 095 096 return control.isCritical() ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE; 097 } 098 099 public String getOID() { 100 return OID; 101 } 102 }; 103 104 /** 105 * Creates a new tree delete request control having the provided 106 * criticality. 107 * 108 * @param isCritical 109 * {@code true} if it is unacceptable to perform the operation 110 * without applying the semantics of this control, or 111 * {@code false} if it can be ignored. 112 * @return The new control. 113 */ 114 public static SubtreeDeleteRequestControl newControl(final boolean isCritical) { 115 return isCritical ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE; 116 } 117 118 private final boolean isCritical; 119 120 private SubtreeDeleteRequestControl(final boolean isCritical) { 121 this.isCritical = isCritical; 122 } 123 124 /** {@inheritDoc} */ 125 public String getOID() { 126 return OID; 127 } 128 129 /** {@inheritDoc} */ 130 public ByteString getValue() { 131 return null; 132 } 133 134 /** {@inheritDoc} */ 135 public boolean hasValue() { 136 return false; 137 } 138 139 /** {@inheritDoc} */ 140 public boolean isCritical() { 141 return isCritical; 142 } 143 144 /** {@inheritDoc} */ 145 @Override 146 public String toString() { 147 final StringBuilder builder = new StringBuilder(); 148 builder.append("SubtreeDeleteRequestControl(oid="); 149 builder.append(getOID()); 150 builder.append(", criticality="); 151 builder.append(isCritical()); 152 builder.append(")"); 153 return builder.toString(); 154 } 155 156}