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.ExtendedResponseImpl;
025import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
026
027
028/**
029 * An extended operation intended for notifying clients of upcoming
030 * disconnection. Here's what <a
031 * href="http://www.faqs.org/rfcs/rfc2251.html">RFC 2251</a> has to say about
032 * it:
033 * 
034 * <pre>
035 *  Section 4.1.1 (Small snippet on sending NoD)
036 *  
037 *     If the server receives a PDU from the client in which the LDAPMessage
038 *     SEQUENCE tag cannot be recognized, the messageID cannot be parsed,
039 *     the tag of the protocolOp is not recognized as a request, or the
040 *     encoding structures or lengths of data fields are found to be
041 *     incorrect, then the server MUST return the notice of disconnection
042 *     described in section 4.4.1, with resultCode protocolError, and
043 *     immediately close the connection. In other cases that the server
044 *     cannot parse the request received by the client, the server MUST
045 *     return an appropriate response to the request, with the resultCode
046 *     set to protocolError.
047 *     
048 *  ...   
049 *     
050 *  4.4. Unsolicited Notification
051 *  
052 *     An unsolicited notification is an LDAPMessage sent from the server to
053 *     the client which is not in response to any LDAPMessage received by
054 *     the server. It is used to signal an extraordinary condition in the
055 *     server or in the connection between the client and the server.  The
056 *     notification is of an advisory nature, and the server will not expect
057 *     any response to be returned from the client.
058 *  
059 *     The unsolicited notification is structured as an LDAPMessage in which
060 *     the messageID is 0 and protocolOp is of the extendedResp form.  The
061 *     responseName field of the ExtendedResponse is present. The LDAPOID
062 *     value MUST be unique for this notification, and not be used in any
063 *     other situation.
064 *  
065 *     One unsolicited notification is defined in this document.
066 *  
067 *  4.4.1. Notice of Disconnection
068 *  
069 *     This notification may be used by the server to advise the client that
070 *     the server is about to close the connection due to an error
071 *     condition. Note that this notification is NOT a response to an
072 *     unbind requested by the client: the server MUST follow the procedures
073 *     of section 4.3. This notification is intended to assist clients in
074 *     distinguishing between an error condition and a transient network
075 *     failure. As with a connection close due to network failure, the
076 *     client MUST NOT assume that any outstanding requests which modified
077 *     the directory have succeeded or failed.
078 *  
079 *     The responseName is 1.3.6.1.4.1.1466.20036, the response field is
080 *     absent, and the resultCode is used to indicate the reason for the
081 *     disconnection.
082 *  
083 *     The following resultCode values are to be used in this notification:
084 *  
085 *     - protocolError: The server has received data from the client in
086 *       which the LDAPMessage structure could not be parsed.
087 *  
088 *     - strongAuthRequired: The server has detected that an established
089 *       underlying security association protecting communication between
090 *       the client and server has unexpectedly failed or been compromised.
091 *  
092 *     - unavailable: This server will stop accepting new connections and
093 *       operations on all existing connections, and be unavailable for an
094 *       extended period of time. The client may make use of an alternative
095 *       server.
096 *  
097 *     After sending this notice, the server MUST close the connection.
098 *     After receiving this notice, the client MUST NOT transmit any further
099 *     on the connection, and may abruptly close the connection.
100 * </pre>
101 * 
102 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
103 */
104public final class NoticeOfDisconnect extends ExtendedResponseImpl
105{
106    /** The OID of the NotiveOfDisconnect extended operation. */
107    public static final String EXTENSION_OID = "1.3.6.1.4.1.1466.20036";
108
109    /** The empty response */
110    private static final byte[] EMPTY_RESPONSE = new byte[0];
111
112    /** The single instance with unavailable result code. */
113    public static final NoticeOfDisconnect UNAVAILABLE = new NoticeOfDisconnect( ResultCodeEnum.UNAVAILABLE );
114
115    /** The single instance with protocolError result code. */
116    public static final NoticeOfDisconnect PROTOCOLERROR = new NoticeOfDisconnect( ResultCodeEnum.PROTOCOL_ERROR );
117
118    /** The single instance with strongAuthRequired result code. */
119    public static final NoticeOfDisconnect STRONGAUTHREQUIRED = new NoticeOfDisconnect(
120        ResultCodeEnum.STRONG_AUTH_REQUIRED );
121
122
123    /**
124     * Creates a new instance of NoticeOfDisconnect.
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_04166, 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    // ExtendedResponse Interface Method Implementations
154    // ------------------------------------------------------------------------
155
156    /**
157     * Gets the reponse OID specific encoded response values.
158     * 
159     * @return the response specific encoded response values.
160     */
161    public byte[] getResponse()
162    {
163        return EMPTY_RESPONSE;
164    }
165
166
167    /**
168     * Sets the response OID specific encoded response values.
169     * 
170     * @param value the response specific encoded response values.
171     */
172    public void setResponse( byte[] value )
173    {
174        throw new UnsupportedOperationException( I18n.err( I18n.ERR_04173 ) );
175    }
176
177
178    /**
179     * Gets the OID uniquely identifying this extended response (a.k.a. its
180     * name).
181     * 
182     * @return the OID of the extended response type.
183     */
184    public String getResponseName()
185    {
186        return EXTENSION_OID;
187    }
188
189
190    /**
191     * Sets the OID uniquely identifying this extended response (a.k.a. its
192     * name).
193     * 
194     * @param oid
195     *            the OID of the extended response type.
196     */
197    public void setResponseName( String oid )
198    {
199        throw new UnsupportedOperationException( I18n.err( I18n.ERR_04168, EXTENSION_OID ) );
200    }
201
202
203    /**
204     * {@inheritDoc}
205     */
206    @Override
207    public int hashCode()
208    {
209        int hash = 37;
210        // Seems simple but look at the equals() method ...
211        hash = hash * 17 + getClass().getName().hashCode();
212
213        return hash;
214    }
215
216
217    /**
218     * {@inheritDoc}
219     */
220    @Override
221    public boolean equals( Object obj )
222    {
223        if ( obj == this )
224        {
225            return true;
226        }
227
228        return ( obj instanceof NoticeOfDisconnect );
229    }
230}