From commits-return-7632-apmail-directory-commits-archive=directory.apache.org@directory.apache.org Thu Jan 05 23:18:27 2006 Return-Path: Delivered-To: apmail-directory-commits-archive@www.apache.org Received: (qmail 26691 invoked from network); 5 Jan 2006 23:18:26 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 5 Jan 2006 23:18:26 -0000 Received: (qmail 86563 invoked by uid 500); 5 Jan 2006 23:18:26 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 86505 invoked by uid 500); 5 Jan 2006 23:18:25 -0000 Mailing-List: contact commits-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@directory.apache.org Delivered-To: mailing list commits@directory.apache.org Received: (qmail 86490 invoked by uid 99); 5 Jan 2006 23:18:25 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 05 Jan 2006 15:18:25 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Thu, 05 Jan 2006 15:18:24 -0800 Received: (qmail 26518 invoked by uid 65534); 5 Jan 2006 23:18:03 -0000 Message-ID: <20060105231803.26517.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r366335 - in /directory/trunk/ldap-common/src: main/java/org/apache/ldap/common/codec/search/controls/ test/java/org/apache/ldap/common/codec/search/controls/ Date: Thu, 05 Jan 2006 23:18:02 -0000 To: commits@directory.apache.org From: elecharny@apache.org X-Mailer: svnmailer-1.0.5 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: elecharny Date: Thu Jan 5 15:17:52 2006 New Revision: 366335 URL: http://svn.apache.org/viewcvs?rev=366335&view=rev Log: - Fixed the grammar - Added some checks - Fixed the encoder - Added some testCases Added: directory/trunk/ldap-common/src/test/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlTest.java Modified: directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControl.java directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlGrammar.java directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlStatesEnum.java Modified: directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControl.java URL: http://svn.apache.org/viewcvs/directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControl.java?rev=366335&r1=366334&r2=366335&view=diff ============================================================================== --- directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControl.java (original) +++ directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControl.java Thu Jan 5 15:17:52 2006 @@ -98,19 +98,26 @@ */ public int computeLength() { - int changeTypesLength = 1 + 1 + Value.getNbBytes( changeType.getValue() ); + int changeTypesLength = 1 + 1 + 1; + int previousDnLength = 0; int changeNumberLength = 0; - if ( previousDn != null ) previousDnLength += previousDn.getNbBytes(); - if ( changeNumber != UNDEFINED_CHANGE_NUMBER ) changeNumberLength += Value.getNbBytes( changeNumber ); + if ( previousDn != null ) + { + previousDnLength = 1 + Length.getNbBytes( previousDn.getNbBytes() ) + previousDn.getNbBytes(); + } + + if ( changeNumber != UNDEFINED_CHANGE_NUMBER ) + { + changeNumberLength = 1 + 1 + Value.getNbBytes( changeNumber ); + } eccSeqLength = changeTypesLength + previousDnLength + changeNumberLength; return 1 + Length.getNbBytes( eccSeqLength ) + eccSeqLength; } - /** * Encodes the entry change control. * @@ -125,7 +132,10 @@ bb.put( UniversalTag.SEQUENCE_TAG ); bb.put( Length.getBytes( eccSeqLength ) ); - Value.encode( bb, changeType.getValue() ); + bb.put( UniversalTag.ENUMERATED_TAG ); + bb.put( (byte)1 ); + bb.put( Value.getBytes( changeType.getValue() ) ); + if ( previousDn != null ) { Value.encode( bb, previousDn.getBytes() ); @@ -174,7 +184,7 @@ public String getPreviousDn() { - return previousDn.getString(); + return previousDn == null ? "" : previousDn.getString(); } Modified: directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlGrammar.java URL: http://svn.apache.org/viewcvs/directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlGrammar.java?rev=366335&r1=366334&r2=366335&view=diff ============================================================================== --- directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlGrammar.java (original) +++ directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlGrammar.java Thu Jan 5 15:17:52 2006 @@ -17,6 +17,8 @@ package org.apache.ldap.common.codec.search.controls; +import javax.naming.InvalidNameException; + import org.apache.asn1.ber.IAsn1Container; import org.apache.asn1.ber.grammar.AbstractGrammar; import org.apache.asn1.ber.grammar.GrammarAction; @@ -27,9 +29,8 @@ import org.apache.asn1.codec.DecoderException; import org.apache.asn1.util.IntegerDecoder; import org.apache.asn1.util.IntegerDecoderException; -import org.apache.ldap.common.codec.LdapStatesEnum; -import org.apache.ldap.common.codec.util.LdapString; -import org.apache.ldap.common.codec.util.LdapStringEncodingException; +import org.apache.ldap.common.codec.util.LdapDN; +import org.apache.ldap.common.util.StringTools; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,10 +61,22 @@ // Create the transitions table super.transitions = new GrammarTransition[EntryChangeControlStatesEnum.LAST_EC_STATE][256]; + //============================================================================================ + // Entry Change Control + //============================================================================================ + // EntryChangeNotification ::= SEQUENCE { (Tag) + // ... + // Nothing to do super.transitions[EntryChangeControlStatesEnum.EC_SEQUENCE_TAG][UniversalTag.SEQUENCE_TAG] = new GrammarTransition( EntryChangeControlStatesEnum.EC_SEQUENCE_TAG, EntryChangeControlStatesEnum.EC_SEQUENCE_VALUE, null ); + //============================================================================================ + // Entry Change Control + //============================================================================================ + // EntryChangeNotification ::= SEQUENCE { (Value) + // ... + // Initialization of the structure super.transitions[EntryChangeControlStatesEnum.EC_SEQUENCE_VALUE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition( EntryChangeControlStatesEnum.EC_SEQUENCE_VALUE, EntryChangeControlStatesEnum.CHANGE_TYPE_TAG, @@ -71,34 +84,67 @@ { public void action( IAsn1Container container ) { - EntryChangeControlContainer EntryChangeContainer = ( EntryChangeControlContainer ) container; + EntryChangeControlContainer entryChangeContainer = ( EntryChangeControlContainer ) container; EntryChangeControl control = new EntryChangeControl(); - EntryChangeContainer.setEntryChangeControl( control ); + entryChangeContainer.setEntryChangeControl( control ); } } ); + //============================================================================================ + // Change Type + //============================================================================================ + // EntryChangeNotification ::= SEQUENCE { + // changeType ENUMERATED { (Tag) }, + // ... + // + // Nothing to do super.transitions[EntryChangeControlStatesEnum.CHANGE_TYPE_TAG][UniversalTag.ENUMERATED_TAG] = new GrammarTransition( EntryChangeControlStatesEnum.CHANGE_TYPE_TAG, EntryChangeControlStatesEnum.CHANGE_TYPE_VALUE, null ); + //============================================================================================ + // Change Type + //============================================================================================ + // EntryChangeNotification ::= SEQUENCE { + // changeType ENUMERATED { (Value) }, + // ... + // + // Evaluates the changeType + + // Action associated with the ChangeType transition GrammarAction setChangeTypeAction = new GrammarAction( "Set EntryChangeControl changeType" ) { public void action( IAsn1Container container ) throws DecoderException { - EntryChangeControlContainer EntryChangeContainer = ( EntryChangeControlContainer ) container; - Value value = EntryChangeContainer.getCurrentTLV().getValue(); + EntryChangeControlContainer entryChangeContainer = ( EntryChangeControlContainer ) container; + Value value = entryChangeContainer.getCurrentTLV().getValue(); try { - ChangeType changeType = ChangeType.getChangeType( IntegerDecoder.parse( value ) ); - - if ( log.isDebugEnabled() ) - { - log.debug( "changeType = " + changeType ); - } - - EntryChangeContainer.getEntryChangeControl().setChangeType( changeType ); + int change = IntegerDecoder.parse( value, 1, 8 ); + + switch ( change ) + { + case ChangeType.ADD_VALUE : + case ChangeType.DELETE_VALUE : + case ChangeType.MODDN_VALUE : + case ChangeType.MODIFY_VALUE : + ChangeType changeType = ChangeType.getChangeType( change ); + + if ( log.isDebugEnabled() ) + { + log.debug( "changeType = " + changeType ); + } + + entryChangeContainer.getEntryChangeControl().setChangeType( changeType ); + break; + + default : + String msg = "failed to decode the changeType for EntryChangeControl"; + log.error( msg ); + throw new DecoderException( msg ); + } } catch ( IntegerDecoderException e ) { @@ -109,96 +155,147 @@ } }; - // transition for when we have a previousDN value - super.transitions[EntryChangeControlStatesEnum.CHANGE_TYPE_VALUE][UniversalTag.ENUMERATED_TAG] = - new GrammarTransition( EntryChangeControlStatesEnum.CHANGE_TYPE_VALUE, - EntryChangeControlStatesEnum.PREVIOUS_DN_TAG, setChangeTypeAction ); - - // transition for when we do not have a previousDN value but we do have a changeNumber - super.transitions[EntryChangeControlStatesEnum.CHANGE_TYPE_VALUE][UniversalTag.ENUMERATED_TAG] = - new GrammarTransition( EntryChangeControlStatesEnum.CHANGE_TYPE_VALUE, - EntryChangeControlStatesEnum.CHANGE_NUMBER_TAG, setChangeTypeAction ); - - // transition for when we do not have a previousDN value nor do we have a changeNumber + // ChangeType Transition super.transitions[EntryChangeControlStatesEnum.CHANGE_TYPE_VALUE][UniversalTag.ENUMERATED_TAG] = new GrammarTransition( EntryChangeControlStatesEnum.CHANGE_TYPE_VALUE, - EntryChangeControlStatesEnum.GRAMMAR_END, setChangeTypeAction ); + EntryChangeControlStatesEnum.CHANGE_NUMBER_OR_PREVIOUS_DN_TAG, setChangeTypeAction ); - super.transitions[EntryChangeControlStatesEnum.PREVIOUS_DN_TAG][UniversalTag.OCTET_STRING_TAG] = - new GrammarTransition( EntryChangeControlStatesEnum.PREVIOUS_DN_TAG, + //============================================================================================ + // Previous DN (We have a OCTET_STRING Tag) + //============================================================================================ + // EntryChangeNotification ::= SEQUENCE { + // ... + // previousDN LDAPDN OPTIONAL, (Tag) + // ... + // + // Nothing to do + super.transitions[EntryChangeControlStatesEnum.CHANGE_NUMBER_OR_PREVIOUS_DN_TAG][UniversalTag.OCTET_STRING_TAG] = + new GrammarTransition( EntryChangeControlStatesEnum.CHANGE_NUMBER_OR_PREVIOUS_DN_TAG, EntryChangeControlStatesEnum.PREVIOUS_DN_VALUE, null ); + //============================================================================================ + // Previous DN + //============================================================================================ + // EntryChangeNotification ::= SEQUENCE { + // ... + // previousDN LDAPDN OPTIONAL, (Value) + // ... + // + // Set the previousDN into the structure. We first check that it's a valid DN + + // Action associated with the PreviousDN transition GrammarAction setPreviousDnAction = new GrammarAction( "Set EntryChangeControl previousDN" ) { public void action( IAsn1Container container ) throws DecoderException { - EntryChangeControlContainer EntryChangeContainer = ( EntryChangeControlContainer ) container; - Value value = EntryChangeContainer.getCurrentTLV().getValue(); - LdapString previousDn; - try - { - previousDn = new LdapString( value.getData() ); - } - catch ( LdapStringEncodingException e ) + EntryChangeControlContainer entryChangeContainer = ( EntryChangeControlContainer ) container; + + ChangeType changeType = entryChangeContainer.getEntryChangeControl().getChangeType(); + + if ( changeType != ChangeType.MODDN ) { - throw new DecoderException( "failed to encode string data" ); + log.error( "The previousDN field should not contain anything if the changeType is not MODDN" ); + throw new DecoderException( "Previous DN is not allowed for this change type" ); } - - if ( log.isDebugEnabled() ) + else { - log.debug( "previousDN = " + previousDn ); + Value value = entryChangeContainer.getCurrentTLV().getValue(); + String previousDn; + + try + { + previousDn = StringTools.utf8ToString( value.getData() ); + new LdapDN( previousDn ); + } + catch ( InvalidNameException ine ) + { + log.error( "Bad Previous DN : '" + StringTools.dumpBytes( value.getData() ) ); + throw new DecoderException( "failed to decode the previous DN" ); + } + + if ( log.isDebugEnabled() ) + { + log.debug( "previousDN = " + previousDn ); + } + + entryChangeContainer.getEntryChangeControl().setPreviousDn( previousDn ); } - - EntryChangeContainer.getEntryChangeControl().setPreviousDn( previousDn ); } }; - // transition if we do have an optional changeNumber after this previousDN + // PreviousDN transition super.transitions[EntryChangeControlStatesEnum.PREVIOUS_DN_VALUE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition( EntryChangeControlStatesEnum.PREVIOUS_DN_VALUE, EntryChangeControlStatesEnum.CHANGE_NUMBER_TAG, setPreviousDnAction ); - // transition if we do *NOT* have an optional changeNumber after this previousDN - super.transitions[EntryChangeControlStatesEnum.PREVIOUS_DN_VALUE][UniversalTag.OCTET_STRING_TAG] = - new GrammarTransition( EntryChangeControlStatesEnum.PREVIOUS_DN_VALUE, - EntryChangeControlStatesEnum.GRAMMAR_END, setPreviousDnAction ); + //============================================================================================ + // Change Number from Change Type + //============================================================================================ + // EntryChangeNotification ::= SEQUENCE { + // ... + // changeNumber INTEGER OPTIONAL (Tag) + // } + // + // Nothing to do + super.transitions[EntryChangeControlStatesEnum.CHANGE_NUMBER_OR_PREVIOUS_DN_TAG][UniversalTag.INTEGER_TAG] = + new GrammarTransition( EntryChangeControlStatesEnum.CHANGE_NUMBER_OR_PREVIOUS_DN_TAG, + EntryChangeControlStatesEnum.CHANGE_NUMBER_VALUE, null ); - // transition for processing changeNumber + //============================================================================================ + // Change Number from PreviousDN + //============================================================================================ + // EntryChangeNotification ::= SEQUENCE { + // ... + // changeNumber INTEGER OPTIONAL (Tag) + // } + // + // Nothing to do super.transitions[EntryChangeControlStatesEnum.CHANGE_NUMBER_TAG][UniversalTag.INTEGER_TAG] = new GrammarTransition( EntryChangeControlStatesEnum.CHANGE_NUMBER_TAG, EntryChangeControlStatesEnum.CHANGE_NUMBER_VALUE, null ); - // transition to finish grammar and set the changeNumber - super.transitions[EntryChangeControlStatesEnum.CHANGE_NUMBER_VALUE][UniversalTag.INTEGER_TAG] = - new GrammarTransition( EntryChangeControlStatesEnum.CHANGE_NUMBER_VALUE, - LdapStatesEnum.GRAMMAR_END, - new GrammarAction( "Set EntryChangeControl changeNumber" ) + //============================================================================================ + // Change Number + //============================================================================================ + // EntryChangeNotification ::= SEQUENCE { + // ... + // changeNumber INTEGER OPTIONAL (Value) + // } + // + // Set the changeNumber into the structure + + // Change Number action + GrammarAction setChangeNumberAction = new GrammarAction( "Set EntryChangeControl changeNumber" ) + { + public void action( IAsn1Container container ) throws DecoderException + { + EntryChangeControlContainer entryChangeContainer = ( EntryChangeControlContainer ) container; + Value value = entryChangeContainer.getCurrentTLV().getValue(); + + try { - public void action( IAsn1Container container ) throws DecoderException + int changeNumber = IntegerDecoder.parse( value ); + + if ( log.isDebugEnabled() ) { - EntryChangeControlContainer EntryChangeContainer = ( EntryChangeControlContainer ) container; - Value value = EntryChangeContainer.getCurrentTLV().getValue(); - - try - { - int changeNumber = IntegerDecoder.parse( value ); - - if ( log.isDebugEnabled() ) - { - log.debug( "changeNumber = " + changeNumber ); - } - - EntryChangeContainer.getEntryChangeControl().setChangeNumber( changeNumber ); - } - catch ( IntegerDecoderException e ) - { - String msg = "failed to decode the changeNumber for EntryChangeControl"; - log.error( msg, e ); - throw new DecoderException( msg ); - } + log.debug( "changeNumber = " + changeNumber ); } + + entryChangeContainer.getEntryChangeControl().setChangeNumber( changeNumber ); } - ); + catch ( IntegerDecoderException e ) + { + String msg = "failed to decode the changeNumber for EntryChangeControl"; + log.error( msg, e ); + throw new DecoderException( msg ); + } + } + }; + + // Transition + super.transitions[EntryChangeControlStatesEnum.CHANGE_NUMBER_VALUE][UniversalTag.INTEGER_TAG] = + new GrammarTransition( EntryChangeControlStatesEnum.CHANGE_NUMBER_VALUE, + EntryChangeControlStatesEnum.GRAMMAR_END, setChangeNumberAction ); } /** Modified: directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlStatesEnum.java URL: http://svn.apache.org/viewcvs/directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlStatesEnum.java?rev=366335&r1=366334&r2=366335&view=diff ============================================================================== --- directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlStatesEnum.java (original) +++ directory/trunk/ldap-common/src/main/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlStatesEnum.java Thu Jan 5 15:17:52 2006 @@ -48,7 +48,7 @@ public static int CHANGE_TYPE_VALUE = 3; /** previousDN Tag */ - public static int PREVIOUS_DN_TAG = 4; + public static int CHANGE_NUMBER_OR_PREVIOUS_DN_TAG = 4; /** previousDN Value */ public static int PREVIOUS_DN_VALUE = 5; @@ -90,7 +90,7 @@ "EC_SEQUENCE_VALUE", "CHANGE_TYPE_TAG", "CHANGE_TYPE_VALUE", - "PREVIOUS_DN_TAG", + "CHANGE_NUMBER_OR_PREVIOUS_DN_TAG", "PREVIOUS_DN_VALUE", "CHANGE_NUMBER_TAG", "CHANGE_NUMBER_VALUE" Added: directory/trunk/ldap-common/src/test/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlTest.java URL: http://svn.apache.org/viewcvs/directory/trunk/ldap-common/src/test/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlTest.java?rev=366335&view=auto ============================================================================== --- directory/trunk/ldap-common/src/test/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlTest.java (added) +++ directory/trunk/ldap-common/src/test/java/org/apache/ldap/common/codec/search/controls/EntryChangeControlTest.java Thu Jan 5 15:17:52 2006 @@ -0,0 +1,242 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.ldap.common.codec.search.controls; + +import java.nio.ByteBuffer; + +import javax.naming.NamingException; + +import org.apache.asn1.codec.DecoderException; +import org.apache.asn1.ber.Asn1Decoder; +import org.apache.ldap.common.codec.LdapDecoder; +import org.apache.ldap.common.util.StringTools; + +import junit.framework.Assert; +import junit.framework.TestCase; + +/** + * Test the EntryChangeControlTest codec + * + * @author Apache Directory Project + */ +public class EntryChangeControlTest extends TestCase { + /** + * Test the decoding of a EntryChangeControl + */ + public void testDecodeEntryChangeControlSuccess() throws NamingException + { + Asn1Decoder ldapDecoder = new LdapDecoder(); + ByteBuffer bb = ByteBuffer.allocate( 0x0D ); + bb.put( new byte[] + { + 0x30, 0x0B, // EntryChangeNotification ::= SEQUENCE { + 0x0A, 0x01, 0x08, // changeType ENUMERATED { + // modDN (8) + // } + 0x04, 0x03, 'a', '=', 'b', // previousDN LDAPDN OPTIONAL, -- modifyDN ops. only + 0x02, 0x01, 0x10 // changeNumber INTEGER OPTIONAL -- if supported + // } + } ); + bb.flip(); + + EntryChangeControlContainer container = new EntryChangeControlContainer(); + try + { + ldapDecoder.decode( bb, container ); + } + catch ( DecoderException de ) + { + de.printStackTrace(); + Assert.fail( de.getMessage() ); + } + + EntryChangeControl entryChange = container.getEntryChangeControl(); + assertEquals( ChangeType.MODDN, entryChange.getChangeType() ); + assertEquals( "a=b", entryChange.getPreviousDn() ); + assertEquals( 16, entryChange.getChangeNumber() ); + } + + /** + * Test the decoding of a EntryChangeControl with a add + * and a change number + */ + public void testDecodeEntryChangeControlWithADDAndChangeNumber() throws NamingException + { + Asn1Decoder ldapDecoder = new LdapDecoder(); + ByteBuffer bb = ByteBuffer.allocate( 0x08 ); + bb.put( new byte[] + { + 0x30, 0x06, // EntryChangeNotification ::= SEQUENCE { + 0x0A, 0x01, 0x01, // changeType ENUMERATED { + // Add (1) + // } + 0x02, 0x01, 0x10 // changeNumber INTEGER OPTIONAL -- if supported + // } + } ); + bb.flip(); + + EntryChangeControlContainer container = new EntryChangeControlContainer(); + try + { + ldapDecoder.decode( bb, container ); + } + catch ( DecoderException de ) + { + de.printStackTrace(); + Assert.fail( de.getMessage() ); + } + + EntryChangeControl entryChange = container.getEntryChangeControl(); + assertEquals( ChangeType.ADD, entryChange.getChangeType() ); + assertEquals( "", entryChange.getPreviousDn() ); + assertEquals( 16, entryChange.getChangeNumber() ); + } + + /** + * Test the decoding of a EntryChangeControl with a add + * so we should not have a PreviousDN + */ + public void testDecodeEntryChangeControlWithADDAndPreviousDNBad() throws NamingException + { + Asn1Decoder ldapDecoder = new LdapDecoder(); + ByteBuffer bb = ByteBuffer.allocate( 0x0D ); + bb.put( new byte[] + { + 0x30, 0x0B, // EntryChangeNotification ::= SEQUENCE { + 0x0A, 0x01, 0x01, // changeType ENUMERATED { + // ADD (1) + // } + 0x04, 0x03, 'a', '=', 'b', // previousDN LDAPDN OPTIONAL, -- modifyDN ops. only + 0x02, 0x01, 0x10 // changeNumber INTEGER OPTIONAL -- if supported + // } + } ); + bb.flip(); + + EntryChangeControlContainer container = new EntryChangeControlContainer(); + + try + { + ldapDecoder.decode( bb, container ); + } + catch ( DecoderException de ) + { + // We should fail, because we have a previousDN with a ADD + assertTrue( true ); + return; + } + + Assert.fail( "A ADD operation should not have a PreviousDN" ); + } + + /** + * Test the decoding of a EntryChangeControl with a add + * and nothing else + */ + public void testDecodeEntryChangeControlWithADD() throws NamingException + { + Asn1Decoder ldapDecoder = new LdapDecoder(); + ByteBuffer bb = ByteBuffer.allocate( 0x05 ); + bb.put( new byte[] + { + 0x30, 0x03, // EntryChangeNotification ::= SEQUENCE { + 0x0A, 0x01, 0x01, // changeType ENUMERATED { + // ADD (1) + // } + // } + } ); + bb.flip(); + + EntryChangeControlContainer container = new EntryChangeControlContainer(); + + try + { + ldapDecoder.decode( bb, container ); + } + catch ( DecoderException de ) + { + de.printStackTrace(); + Assert.fail( de.getMessage() ); + } + + EntryChangeControl entryChange = container.getEntryChangeControl(); + assertEquals( ChangeType.ADD, entryChange.getChangeType() ); + assertEquals( "", entryChange.getPreviousDn() ); + assertEquals( EntryChangeControl.UNDEFINED_CHANGE_NUMBER, entryChange.getChangeNumber() ); + } + + /** + * Test the decoding of a EntryChangeControl with a worng changeType + * and nothing else + */ + public void testDecodeEntryChangeControlWithWrongChangeType() throws NamingException + { + Asn1Decoder ldapDecoder = new LdapDecoder(); + ByteBuffer bb = ByteBuffer.allocate( 0x05 ); + bb.put( new byte[] + { + 0x30, 0x03, // EntryChangeNotification ::= SEQUENCE { + 0x0A, 0x01, 0x03, // changeType ENUMERATED { + // BAD Change Type + // } + // } + } ); + bb.flip(); + + EntryChangeControlContainer container = new EntryChangeControlContainer(); + + try + { + ldapDecoder.decode( bb, container ); + } + catch ( DecoderException de ) + { + // We should fail because the ChangeType is not known + assertTrue( true ); + return; + } + + Assert.fail( "The changeType is unknown" ); + } + + /** + * Test encoding of a EntryChangeControl. + */ + public void testEncodeEntryChangeControl() throws Exception + { + ByteBuffer bb = ByteBuffer.allocate( 0x0D ); + bb.put( new byte[] + { + 0x30, 0x0B, // EntryChangeNotification ::= SEQUENCE { + 0x0A, 0x01, 0x08, // changeType ENUMERATED { + // modDN (8) + // } + 0x04, 0x03, 'a', '=', 'b', // previousDN LDAPDN OPTIONAL, -- modifyDN ops. only + 0x02, 0x01, 0x10 // changeNumber INTEGER OPTIONAL -- if supported + } ); + + String expected = StringTools.dumpBytes( bb.array() ); + bb.flip(); + + EntryChangeControl entry = new EntryChangeControl(); + entry.setChangeType( ChangeType.MODDN); + entry.setChangeNumber( 16 ); + entry.setPreviousDn( "a=b" ); + bb = entry.encode( null ); + String decoded = StringTools.dumpBytes( bb.array() ); + assertEquals( expected, decoded ); + } +}