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.codec.extended.operations.gracefulDisconnect;
021
022
023 import java.nio.ByteBuffer;
024 import java.util.ArrayList;
025 import java.util.List;
026
027 import org.apache.directory.shared.asn1.ber.tlv.TLV;
028 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
029 import org.apache.directory.shared.asn1.ber.tlv.Value;
030 import org.apache.directory.shared.asn1.codec.EncoderException;
031 import org.apache.directory.shared.ldap.codec.extended.operations.GracefulAction;
032 import org.apache.directory.shared.ldap.codec.extended.operations.GracefulActionConstants;
033 import org.apache.directory.shared.ldap.util.LdapURL;
034
035
036 /**
037 * An extended operation to proceed a graceful disconnect
038 *
039 * <pre>
040 * GracefulDisconnect ::= SEQUENCE
041 * {
042 * timeOffline INTEGER (0..720) DEFAULT 0,
043 * delay [0] INTEGER (0..86400) DEFAULT 0,
044 * replicatedContexts Referral OPTIONAL
045 * }
046 * </pre>
047 *
048 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
049 * @version $Rev: 764131 $, $Date: 2009-04-11 03:03:00 +0200 (Sam, 11 avr 2009) $,
050 */
051 public class GracefulDisconnect extends GracefulAction
052 {
053 /** List of the alternate servers to use */
054 // Two urls will be enough, generally
055 private List<LdapURL> replicatedContexts = new ArrayList<LdapURL>( 2 );
056
057 /** Length of the sequence */
058 private int gracefulDisconnectSequenceLength;
059
060 /** Length of the replicated contexts */
061 private int replicatedContextsLength;
062
063
064 /**
065 * Create a GracefulDisconnect object, with a timeOffline and a delay
066 *
067 * @param timeOffline The time the server will be offline
068 * @param delay The delay before the disconnection
069 */
070 public GracefulDisconnect( int timeOffline, int delay )
071 {
072 super( timeOffline, delay );
073 }
074
075
076 /**
077 * Default constructor.
078 */
079 public GracefulDisconnect()
080 {
081 super();
082 }
083
084
085 /**
086 * Get the list of replicated servers
087 *
088 * @return The list of replicated servers
089 */
090 public List<LdapURL> getReplicatedContexts()
091 {
092 return replicatedContexts;
093 }
094
095
096 /**
097 * Add a new URL of a replicated server
098 *
099 * @param replicatedContext The replictaed server to add.
100 */
101 public void addReplicatedContexts( LdapURL replicatedContext )
102 {
103 replicatedContexts.add( replicatedContext );
104 }
105
106
107 /**
108 * Compute the GracefulDisconnect length
109 *
110 * 0x30 L1
111 * |
112 * +--> [ 0x02 0x0(1-4) [0..720] ]
113 * +--> [ 0x80 0x0(1-3) [0..86400] ]
114 * +--> [ 0x30 L2
115 * |
116 * +--> (0x04 L3 value) + ]
117 */
118 public int computeLength()
119 {
120 gracefulDisconnectSequenceLength = 0;
121
122 if ( timeOffline != 0 )
123 {
124 gracefulDisconnectSequenceLength += 1 + 1 + Value.getNbBytes( timeOffline );
125 }
126
127 if ( delay != 0 )
128 {
129 gracefulDisconnectSequenceLength += 1 + 1 + Value.getNbBytes( delay );
130 }
131
132 if ( replicatedContexts.size() > 0 )
133 {
134 replicatedContextsLength = 0;
135
136 // We may have more than one reference.
137 for ( LdapURL replicatedContext:replicatedContexts )
138 {
139 int ldapUrlLength = replicatedContext.getNbBytes();
140 replicatedContextsLength += 1 + TLV.getNbBytes( ldapUrlLength ) + ldapUrlLength;
141 }
142
143 gracefulDisconnectSequenceLength += 1 + TLV.getNbBytes( replicatedContextsLength )
144 + replicatedContextsLength;
145 }
146
147 return 1 + TLV.getNbBytes( gracefulDisconnectSequenceLength ) + gracefulDisconnectSequenceLength;
148 }
149
150
151 /**
152 * Encodes the gracefulDisconnect extended operation.
153 *
154 * @param buffer The encoded sink
155 * @return A ByteBuffer that contains the encoded PDU
156 * @throws EncoderException If anything goes wrong.
157 */
158 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
159 {
160 // Allocate the bytes buffer.
161 ByteBuffer bb = ByteBuffer.allocate( computeLength() );
162
163 bb.put( UniversalTag.SEQUENCE_TAG );
164 bb.put( TLV.getBytes( gracefulDisconnectSequenceLength ) );
165
166 if ( timeOffline != 0 )
167 {
168 Value.encode( bb, timeOffline );
169 }
170
171 if ( delay != 0 )
172 {
173 bb.put( ( byte ) GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG );
174 bb.put( ( byte ) TLV.getNbBytes( delay ) );
175 bb.put( Value.getBytes( delay ) );
176 }
177
178 if ( replicatedContexts.size() != 0 )
179 {
180 bb.put( UniversalTag.SEQUENCE_TAG );
181 bb.put( TLV.getBytes( replicatedContextsLength ) );
182
183 // We may have more than one reference.
184 for ( LdapURL replicatedContext:replicatedContexts )
185 {
186 Value.encode( bb, replicatedContext.getBytesReference() );
187 }
188 }
189
190 return bb;
191 }
192
193
194 /**
195 * Return a string representation of the graceful disconnect
196 */
197 public String toString()
198 {
199 StringBuffer sb = new StringBuffer();
200
201 sb.append( "Graceful Disconnect extended operation" );
202 sb.append( " TimeOffline : " ).append( timeOffline ).append( '\n' );
203 sb.append( " Delay : " ).append( delay ).append( '\n' );
204
205 if ( ( replicatedContexts != null) && ( replicatedContexts.size() != 0 ) )
206 {
207 sb.append( " Replicated contexts :" );
208
209 // We may have more than one reference.
210 for ( LdapURL url:replicatedContexts )
211 {
212 sb.append( "\n " ).append( url );
213 }
214 }
215
216 return sb.toString();
217 }
218 }