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;
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 ExtendedResponseImpl
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    private NoticeOfDisconnect( ResultCodeEnum rcode )
125    {
126        super( 0, EXTENSION_OID );
127
128        switch ( rcode )
129        {
130            case UNAVAILABLE:
131                break;
132
133            case PROTOCOL_ERROR:
134                break;
135
136            case STRONG_AUTH_REQUIRED:
137                break;
138
139            default:
140                throw new IllegalArgumentException( I18n.err( I18n.ERR_04166, ResultCodeEnum.UNAVAILABLE,
141                    ResultCodeEnum.PROTOCOL_ERROR, ResultCodeEnum.STRONG_AUTH_REQUIRED ) );
142        }
143
144        super.getLdapResult().setDiagnosticMessage( rcode.toString() + ": The server will disconnect!" );
145        super.getLdapResult().setMatchedDn( null );
146        super.getLdapResult().setResultCode( rcode );
147    }
148
149
150    // ------------------------------------------------------------------------
151    // ExtendedResponse Interface Method Implementations
152    // ------------------------------------------------------------------------
153
154    /**
155     * Gets the reponse OID specific encoded response values.
156     * 
157     * @return the response specific encoded response values.
158     */
159    public byte[] getResponse()
160    {
161        return Strings.EMPTY_BYTES;
162    }
163
164
165    /**
166     * Sets the response OID specific encoded response values.
167     * 
168     * @param value the response specific encoded response values.
169     */
170    public void setResponse( byte[] value )
171    {
172        throw new UnsupportedOperationException( I18n.err( I18n.ERR_04173 ) );
173    }
174
175
176    /**
177     * Gets the OID uniquely identifying this extended response (a.k.a. its
178     * name).
179     * 
180     * @return the OID of the extended response type.
181     */
182    @Override
183    public String getResponseName()
184    {
185        return EXTENSION_OID;
186    }
187
188
189    /**
190     * Sets the OID uniquely identifying this extended response (a.k.a. its
191     * name).
192     * 
193     * @param oid
194     *            the OID of the extended response type.
195     */
196    @Override
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}