001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.api.ldap.model.message.extended; 021 022 023import org.apache.directory.api.i18n.I18n; 024import org.apache.directory.api.ldap.model.message.AbstractExtendedResponse; 025import org.apache.directory.api.ldap.model.message.ResultCodeEnum; 026import org.apache.directory.api.util.Strings; 027 028 029/** 030 * An extended operation intended for notifying clients of upcoming 031 * disconnection. Here's what <a 032 * href="http://www.faqs.org/rfcs/rfc2251.html">RFC 2251</a> has to say about 033 * it: 034 * 035 * <pre> 036 * Section 4.1.1 (Small snippet on sending NoD) 037 * 038 * If the server receives a PDU from the client in which the LDAPMessage 039 * SEQUENCE tag cannot be recognized, the messageID cannot be parsed, 040 * the tag of the protocolOp is not recognized as a request, or the 041 * encoding structures or lengths of data fields are found to be 042 * incorrect, then the server MUST return the notice of disconnection 043 * described in section 4.4.1, with resultCode protocolError, and 044 * immediately close the connection. In other cases that the server 045 * cannot parse the request received by the client, the server MUST 046 * return an appropriate response to the request, with the resultCode 047 * set to protocolError. 048 * 049 * ... 050 * 051 * 4.4. Unsolicited Notification 052 * 053 * An unsolicited notification is an LDAPMessage sent from the server to 054 * the client which is not in response to any LDAPMessage received by 055 * the server. It is used to signal an extraordinary condition in the 056 * server or in the connection between the client and the server. The 057 * notification is of an advisory nature, and the server will not expect 058 * any response to be returned from the client. 059 * 060 * The unsolicited notification is structured as an LDAPMessage in which 061 * the messageID is 0 and protocolOp is of the extendedResp form. The 062 * responseName field of the ExtendedResponse is present. The LDAPOID 063 * value MUST be unique for this notification, and not be used in any 064 * other situation. 065 * 066 * One unsolicited notification is defined in this document. 067 * 068 * 4.4.1. Notice of Disconnection 069 * 070 * This notification may be used by the server to advise the client that 071 * the server is about to close the connection due to an error 072 * condition. Note that this notification is NOT a response to an 073 * unbind requested by the client: the server MUST follow the procedures 074 * of section 4.3. This notification is intended to assist clients in 075 * distinguishing between an error condition and a transient network 076 * failure. As with a connection close due to network failure, the 077 * client MUST NOT assume that any outstanding requests which modified 078 * the directory have succeeded or failed. 079 * 080 * The responseName is 1.3.6.1.4.1.1466.20036, the response field is 081 * absent, and the resultCode is used to indicate the reason for the 082 * disconnection. 083 * 084 * The following resultCode values are to be used in this notification: 085 * 086 * - protocolError: The server has received data from the client in 087 * which the LDAPMessage structure could not be parsed. 088 * 089 * - strongAuthRequired: The server has detected that an established 090 * underlying security association protecting communication between 091 * the client and server has unexpectedly failed or been compromised. 092 * 093 * - unavailable: This server will stop accepting new connections and 094 * operations on all existing connections, and be unavailable for an 095 * extended period of time. The client may make use of an alternative 096 * server. 097 * 098 * After sending this notice, the server MUST close the connection. 099 * After receiving this notice, the client MUST NOT transmit any further 100 * on the connection, and may abruptly close the connection. 101 * </pre> 102 * 103 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 104 */ 105public final class NoticeOfDisconnect extends AbstractExtendedResponse 106{ 107 /** The OID of the NotiveOfDisconnect extended operation. */ 108 public static final String EXTENSION_OID = "1.3.6.1.4.1.1466.20036"; 109 110 /** The single instance with unavailable result code. */ 111 public static final NoticeOfDisconnect UNAVAILABLE = new NoticeOfDisconnect( ResultCodeEnum.UNAVAILABLE ); 112 113 /** The single instance with protocolError result code. */ 114 public static final NoticeOfDisconnect PROTOCOLERROR = new NoticeOfDisconnect( ResultCodeEnum.PROTOCOL_ERROR ); 115 116 /** The single instance with strongAuthRequired result code. */ 117 public static final NoticeOfDisconnect STRONGAUTHREQUIRED = new NoticeOfDisconnect( 118 ResultCodeEnum.STRONG_AUTH_REQUIRED ); 119 120 121 /** 122 * Creates a new instance of NoticeOfDisconnect. 123 * 124 * @param rcode The result code 125 */ 126 private NoticeOfDisconnect( ResultCodeEnum rcode ) 127 { 128 super( 0, EXTENSION_OID ); 129 130 switch ( rcode ) 131 { 132 case UNAVAILABLE: 133 break; 134 135 case PROTOCOL_ERROR: 136 break; 137 138 case STRONG_AUTH_REQUIRED: 139 break; 140 141 default: 142 throw new IllegalArgumentException( I18n.err( I18n.ERR_13503_RESULT_CODE_SHOULD_BE_IN, ResultCodeEnum.UNAVAILABLE, 143 ResultCodeEnum.PROTOCOL_ERROR, ResultCodeEnum.STRONG_AUTH_REQUIRED ) ); 144 } 145 146 super.getLdapResult().setDiagnosticMessage( rcode.toString() + ": The server will disconnect!" ); 147 super.getLdapResult().setMatchedDn( null ); 148 super.getLdapResult().setResultCode( rcode ); 149 } 150 151 152 /** 153 * Create a NoD associated with a result code enum 154 * 155 * @param rcode The result code 156 * @return The created NoticeOfDisconnect 157 */ 158 public static NoticeOfDisconnect createNoticeOfDisconnect( ResultCodeEnum rcode ) 159 { 160 NoticeOfDisconnect nod; 161 162 switch ( rcode ) 163 { 164 case UNAVAILABLE: 165 nod = UNAVAILABLE; 166 break; 167 168 case PROTOCOL_ERROR: 169 nod = PROTOCOLERROR; 170 break; 171 172 case STRONG_AUTH_REQUIRED: 173 nod = STRONGAUTHREQUIRED; 174 break; 175 176 default: 177 nod = new NoticeOfDisconnect( rcode ); 178 break; 179 } 180 181 nod.getLdapResult().setDiagnosticMessage( rcode.toString() + ": The server will disconnect!" ); 182 nod.getLdapResult().setMatchedDn( null ); 183 nod.getLdapResult().setResultCode( rcode ); 184 185 return nod; 186 } 187 188 189 // ------------------------------------------------------------------------ 190 // ExtendedResponse Interface Method Implementations 191 // ------------------------------------------------------------------------ 192 193 /** 194 * Gets the reponse OID specific encoded response values. 195 * 196 * @return the response specific encoded response values. 197 */ 198 public byte[] getResponse() 199 { 200 return Strings.EMPTY_BYTES; 201 } 202 203 204 /** 205 * Sets the response OID specific encoded response values. 206 * 207 * @param value the response specific encoded response values. 208 */ 209 public void setResponse( byte[] value ) 210 { 211 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13505_HARDCODED_ZERO_LENGTH_RESPONSE ) ); 212 } 213 214 215 /** 216 * Sets the OID uniquely identifying this extended response (a.k.a. its 217 * name). 218 * 219 * @param oid the OID of the extended response type. 220 */ 221 @Override 222 public void setResponseName( String oid ) 223 { 224 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13504_FIX_OID, EXTENSION_OID ) ); 225 } 226 227 228 /** 229 * {@inheritDoc} 230 */ 231 @Override 232 public int hashCode() 233 { 234 int hash = 37; 235 // Seems simple but look at the equals() method ... 236 hash = hash * 17 + getClass().getName().hashCode(); 237 238 return hash; 239 } 240 241 242 /** 243 * {@inheritDoc} 244 */ 245 @Override 246 public boolean equals( Object obj ) 247 { 248 if ( obj == this ) 249 { 250 return true; 251 } 252 253 return obj instanceof NoticeOfDisconnect; 254 } 255}