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_MANAGEDSAIT_CONTROL_BAD_OID; 029import static com.forgerock.opendj.ldap.CoreMessages.ERR_MANAGEDSAIT_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 ManageDsaIT request control as defined in RFC 3296. This control allows 040 * manipulation of referral and other special objects as normal objects. 041 * <p> 042 * When this control is present in the request, the server will not generate a 043 * referral or continuation reference based upon information held in referral 044 * objects and instead will treat the referral object as a normal entry. The 045 * server, however, is still free to return referrals for other reasons. 046 * 047 * <pre> 048 * // "dc=ref,dc=com" holds a referral to something else. 049 * 050 * // Referral without the ManageDsaIT control: 051 * SearchRequest request = Requests.newSearchRequest( 052 * "dc=ref,dc=com", 053 * SearchScope.SUBORDINATES, 054 * "(objectclass=*)", 055 * ""); 056 * 057 * ConnectionEntryReader reader = connection.search(request); 058 * while (reader.hasNext()) { 059 * if (reader.isReference()) { 060 * SearchResultReference ref = reader.readReference(); 061 * // References: ref.getURIs() 062 * } 063 * } 064 * 065 * // Referral with the ManageDsaIT control: 066 * request.addControl(ManageDsaITRequestControl.newControl(true)); 067 * SearchResultEntry entry = connection.searchSingleEntry(request); 068 * // ... 069 * </pre> 070 * 071 * @see <a href="http://tools.ietf.org/html/rfc3296">RFC 3296 - Named 072 * Subordinate References in Lightweight Directory Access Protocol (LDAP) 073 * Directories </a> 074 */ 075public final class ManageDsaITRequestControl implements Control { 076 /** 077 * The OID for the ManageDsaIT request control. 078 */ 079 public static final String OID = "2.16.840.1.113730.3.4.2"; 080 081 private static final ManageDsaITRequestControl CRITICAL_INSTANCE = 082 new ManageDsaITRequestControl(true); 083 private static final ManageDsaITRequestControl NONCRITICAL_INSTANCE = 084 new ManageDsaITRequestControl(false); 085 086 /** 087 * A decoder which can be used for decoding the Manage DsaIT request 088 * control. 089 */ 090 public static final ControlDecoder<ManageDsaITRequestControl> DECODER = 091 new ControlDecoder<ManageDsaITRequestControl>() { 092 093 public ManageDsaITRequestControl decodeControl(final Control control, 094 final DecodeOptions options) throws DecodeException { 095 Reject.ifNull(control); 096 097 if (control instanceof ManageDsaITRequestControl) { 098 return (ManageDsaITRequestControl) control; 099 } 100 101 if (!control.getOID().equals(OID)) { 102 final LocalizableMessage message = 103 ERR_MANAGEDSAIT_CONTROL_BAD_OID.get(control.getOID(), OID); 104 throw DecodeException.error(message); 105 } 106 107 if (control.hasValue()) { 108 final LocalizableMessage message = 109 ERR_MANAGEDSAIT_INVALID_CONTROL_VALUE.get(); 110 throw DecodeException.error(message); 111 } 112 113 return control.isCritical() ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE; 114 } 115 116 public String getOID() { 117 return OID; 118 } 119 }; 120 121 /** 122 * Creates a new ManageDsaIT request control having the provided 123 * criticality. 124 * 125 * @param isCritical 126 * {@code true} if it is unacceptable to perform the operation 127 * without applying the semantics of this control, or 128 * {@code false} if it can be ignored. 129 * @return The new control. 130 */ 131 public static ManageDsaITRequestControl newControl(final boolean isCritical) { 132 return isCritical ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE; 133 } 134 135 private final boolean isCritical; 136 137 private ManageDsaITRequestControl(final boolean isCritical) { 138 this.isCritical = isCritical; 139 } 140 141 /** {@inheritDoc} */ 142 public String getOID() { 143 return OID; 144 } 145 146 /** {@inheritDoc} */ 147 public ByteString getValue() { 148 return null; 149 } 150 151 /** {@inheritDoc} */ 152 public boolean hasValue() { 153 return false; 154 } 155 156 /** {@inheritDoc} */ 157 public boolean isCritical() { 158 return isCritical; 159 } 160 161 /** {@inheritDoc} */ 162 @Override 163 public String toString() { 164 final StringBuilder builder = new StringBuilder(); 165 builder.append("ManageDsaITRequestControl(oid="); 166 builder.append(getOID()); 167 builder.append(", criticality="); 168 builder.append(isCritical()); 169 builder.append(")"); 170 return builder.toString(); 171 } 172 173}