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