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.i18n.I18n; 031 import org.apache.directory.shared.ldap.codec.extended.operations.gracefulDisconnect.GracefulDisconnectContainer; 032 import org.apache.directory.shared.ldap.codec.extended.operations.gracefulDisconnect.GracefulDisconnectDecoder; 033 import org.apache.directory.shared.ldap.codec.util.LdapURLEncodingException; 034 import org.apache.directory.shared.ldap.message.ExtendedResponseImpl; 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.message.internal.InternalReferral; 038 import org.apache.directory.shared.ldap.util.LdapURL; 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: 912436 $ 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( I18n.err( I18n.ERR_04169 ), 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( I18n.err( I18n.ERR_04170, urlstr ), e ); 149 continue; 150 } 151 codec.addReplicatedContexts( url ); 152 } 153 154 try 155 { 156 super.value = codec.encode().array(); 157 } 158 catch ( EncoderException e ) 159 { 160 log.error( I18n.err( I18n.ERR_04171 ), 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( I18n.err( I18n.ERR_04172 ), 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( I18n.err( I18n.ERR_04168, 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 }