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 */
020 package org.apache.directory.shared.ldap.message.extended;
021
022
023 import java.nio.ByteBuffer;
024 import java.util.Iterator;
025 import java.util.List;
026
027 import org.apache.directory.shared.asn1.ber.Asn1Decoder;
028 import org.apache.directory.shared.asn1.codec.DecoderException;
029 import org.apache.directory.shared.asn1.codec.EncoderException;
030 import org.apache.directory.shared.ldap.codec.extended.operations.gracefulDisconnect.GracefulDisconnectContainer;
031 import org.apache.directory.shared.ldap.codec.extended.operations.gracefulDisconnect.GracefulDisconnectDecoder;
032 import org.apache.directory.shared.ldap.codec.util.LdapURLEncodingException;
033 import org.apache.directory.shared.ldap.message.ExtendedResponseImpl;
034 import org.apache.directory.shared.ldap.message.InternalReferral;
035 import org.apache.directory.shared.ldap.message.ReferralImpl;
036 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
037 import org.apache.directory.shared.ldap.util.LdapURL;
038
039 import org.slf4j.Logger;
040 import org.slf4j.LoggerFactory;
041
042
043 /**
044 * An unsolicited notification, extended response, intended for notifying
045 * clients of upcoming disconnection due to intended service windows. Unlike the
046 * {@link NoticeOfDisconnect} this response contains additional information about
047 * the amount of time the server will be offline and exactly when it intends to
048 * shutdown.
049 *
050 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
051 * @version $Rev: 764131 $
052 */
053 public class GracefulDisconnect extends ExtendedResponseImpl
054 {
055 private static final long serialVersionUID = -4682291068700593492L;
056
057 public static final String EXTENSION_OID = "1.3.6.1.4.1.18060.0.1.5";
058
059 private static final Logger log = LoggerFactory.getLogger( GracefulDisconnect.class );
060
061 /** offline Time after disconnection */
062 private int timeOffline;
063
064 /** Delay before disconnection */
065 private int delay;
066
067 /** String based LDAP URL that may be followed for replicated namingContexts */
068 private InternalReferral replicatedContexts = new ReferralImpl();
069
070
071 public GracefulDisconnect(byte[] value) throws DecoderException
072 {
073 super( 0, EXTENSION_OID );
074 if ( value != null )
075 {
076 this.value = new byte[ value.length ];
077 System.arraycopy( value, 0, this.value, 0, value.length );
078 } else {
079 this.value = null;
080 }
081 decodeValue();
082 }
083
084
085 public GracefulDisconnect(int timeOffline, int delay)
086 {
087 super( 0, EXTENSION_OID );
088 super.oid = EXTENSION_OID;
089 this.timeOffline = timeOffline;
090 this.delay = delay;
091
092 StringBuffer buf = new StringBuffer();
093 buf.append( "The server will disconnect and will be unavailable for " ).append( timeOffline );
094 buf.append( " minutes in " ).append( delay ).append( " seconds." );
095
096 super.getLdapResult().setErrorMessage( buf.toString() );
097 super.getLdapResult().setMatchedDn( null );
098 super.getLdapResult().setResultCode( ResultCodeEnum.UNAVAILABLE );
099
100 encodeResponse();
101 }
102
103
104 private void decodeValue() throws DecoderException
105 {
106 GracefulDisconnectDecoder decoder = new GracefulDisconnectDecoder();
107 org.apache.directory.shared.ldap.codec.extended.operations.gracefulDisconnect.GracefulDisconnect codec = null;
108
109 try
110 {
111 codec = ( org.apache.directory.shared.ldap.codec.extended.operations.gracefulDisconnect.GracefulDisconnect ) decoder
112 .decode( value );
113 this.timeOffline = codec.getTimeOffline();
114 this.delay = codec.getDelay();
115 super.getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );
116 List<LdapURL> contexts = codec.getReplicatedContexts();
117
118 for ( int ii = 0; ii < contexts.size(); ii++ )
119 {
120 replicatedContexts.addLdapUrl( contexts.get( ii ).toString() );
121 }
122 }
123 catch ( DecoderException e )
124 {
125 log.error( "Failed to decode response value", e );
126 throw e;
127 }
128 }
129
130
131 private void encodeResponse()
132 {
133 org.apache.directory.shared.ldap.codec.extended.operations.gracefulDisconnect.GracefulDisconnect codec = new org.apache.directory.shared.ldap.codec.extended.operations.gracefulDisconnect.GracefulDisconnect();
134 codec.setTimeOffline( this.timeOffline );
135 codec.setDelay( this.delay );
136 Iterator<String> contexts = this.replicatedContexts.getLdapUrls().iterator();
137
138 while ( contexts.hasNext() )
139 {
140 String urlstr = ( String ) contexts.next();
141 LdapURL url = null;
142 try
143 {
144 url = new LdapURL( urlstr );
145 }
146 catch ( LdapURLEncodingException e )
147 {
148 log.error( "Failed while parsing LDAP url " + urlstr, e );
149 continue;
150 }
151 codec.addReplicatedContexts( url );
152 }
153
154 try
155 {
156 super.value = codec.encode( null ).array();
157 }
158 catch ( EncoderException e )
159 {
160 log.error( "Failed to encode message value.", e );
161 throw new RuntimeException( e );
162 }
163 }
164
165
166 // ------------------------------------------------------------------------
167 // ExtendedResponse Interface Method Implementations
168 // ------------------------------------------------------------------------
169
170 /**
171 * Gets the reponse OID specific encoded response values.
172 *
173 * @return the response specific encoded response values.
174 */
175 public byte[] getResponse()
176 {
177 if ( value == null )
178 {
179 encodeResponse();
180 }
181
182 final byte[] copy = new byte[ value.length ];
183 System.arraycopy( value, 0, copy, 0, value.length );
184 return copy;
185 }
186
187
188 /**
189 * Sets the reponse OID specific encoded response values.
190 *
191 * @param value
192 * the response specific encoded response values.
193 */
194 public void setResponse( byte[] value )
195 {
196 ByteBuffer bb = ByteBuffer.wrap( value );
197 GracefulDisconnectContainer container = new GracefulDisconnectContainer();
198 Asn1Decoder decoder = new Asn1Decoder();
199 try
200 {
201 decoder.decode( bb, container );
202 }
203 catch ( DecoderException e )
204 {
205 log.error( "Failed while decoding response", e );
206 }
207
208 org.apache.directory.shared.ldap.codec.extended.operations.gracefulDisconnect.GracefulDisconnect codec = container
209 .getGracefulDisconnect();
210 this.delay = codec.getDelay();
211 this.timeOffline = codec.getTimeOffline();
212 List<LdapURL> contexts = codec.getReplicatedContexts();
213
214 for ( int ii = 0; ii < contexts.size(); ii++ )
215 {
216 LdapURL url = contexts.get( ii );
217 replicatedContexts.addLdapUrl( url.toString() );
218 }
219
220 if ( value != null )
221 {
222 this.value = new byte[ value.length ];
223 System.arraycopy( value, 0, this.value, 0, value.length );
224 } else {
225 this.value = null;
226 }
227 }
228
229
230 /**
231 * Gets the OID uniquely identifying this extended response (a.k.a. its
232 * name).
233 *
234 * @return the OID of the extended response type.
235 */
236 public String getResponseName()
237 {
238 return EXTENSION_OID;
239 }
240
241
242 /**
243 * Sets the OID uniquely identifying this extended response (a.k.a. its
244 * name).
245 *
246 * @param oid
247 * the OID of the extended response type.
248 */
249 public void setResponseName( String oid )
250 {
251 throw new UnsupportedOperationException( "the OID is fixed: " + EXTENSION_OID );
252 }
253
254
255 // -----------------------------------------------------------------------
256 // Parameters of the Extended Response Value
257 // -----------------------------------------------------------------------
258
259 public void setDelay( int delay )
260 {
261 this.delay = delay;
262 }
263
264
265 public void setTimeOffline( int timeOffline )
266 {
267 this.timeOffline = timeOffline;
268 }
269
270
271 public int getDelay()
272 {
273 return delay;
274 }
275
276
277 public int getTimeOffline()
278 {
279 return timeOffline;
280 }
281
282
283 public InternalReferral getReplicatedContexts()
284 {
285 return replicatedContexts;
286 }
287 }