You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2018/02/01 21:49:59 UTC
[directory-ldap-api] branch master updated: o Added the
EndTransactionResponse implementation o Fixed some I28n name (adding some
text after the error number)
This is an automated email from the ASF dual-hosted git repository.
elecharny pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/directory-ldap-api.git
The following commit(s) were added to refs/heads/master by this push:
new eed35a5 o Added the EndTransactionResponse implementation o Fixed some I28n name (adding some text after the error number)
eed35a5 is described below
commit eed35a509543563524b9ce44ae2f615af7edf1f5
Author: Emmanuel Lécharny <el...@symas.com>
AuthorDate: Thu Feb 1 22:49:47 2018 +0100
o Added the EndTransactionResponse implementation
o Fixed some I28n name (adding some text after the error number)
---
.../java/org/apache/directory/api/i18n/I18n.java | 11 +-
.../apache/directory/api/i18n/errors.properties | 11 +-
.../api/ldap/codec/actions/CheckLengthNotNull.java | 2 +-
.../ldap/codec/actions/controls/AddControl.java | 9 +-
.../actions/controls/StoreControlCriticality.java | 8 +-
.../directory/api/ldap/codec/api/LdapEncoder.java | 4 +-
.../endTransaction/EndTransactionResponse.java | 9 +-
.../endTransaction/EndTransactionResponseImpl.java | 4 +-
.../extended/endTransaction/UpdateControls.java | 4 +-
.../EndTransactionRequestContainer.java | 2 +-
.../EndTransactionRequestGrammar.java | 42 +--
...sEnum.java => EndTransactionRequestStates.java} | 4 +-
.../EndTransactionResponseContainer.java | 113 +++++++
.../EndTransactionResponseDecoder.java | 60 ++++
.../EndTransactionResponseDecorator.java | 247 ++++++++++++++-
.../EndTransactionResponseGrammar.java | 330 +++++++++++++++++++++
...Enum.java => EndTransactionResponseStates.java} | 29 +-
.../endTransaction/controls/ControlsContainer.java | 104 +++++++
.../endTransaction/controls/ControlsGrammar.java | 219 ++++++++++++++
.../ControlsStates.java} | 29 +-
.../controls/actions}/AddControl.java | 30 +-
.../controls/actions}/StoreControlCriticality.java | 19 +-
.../controls/actions/StoreControlValue.java | 94 ++++++
.../endTransaction/EndTransactionResponseTest.java | 262 ++++++++++++++++
24 files changed, 1541 insertions(+), 105 deletions(-)
diff --git a/i18n/src/main/java/org/apache/directory/api/i18n/I18n.java b/i18n/src/main/java/org/apache/directory/api/i18n/I18n.java
index e9f31bd..2697950 100644
--- a/i18n/src/main/java/org/apache/directory/api/i18n/I18n.java
+++ b/i18n/src/main/java/org/apache/directory/api/i18n/I18n.java
@@ -234,11 +234,11 @@ public enum I18n
ERR_04093("ERR_04093"),
ERR_04094("ERR_04094"),
ERR_04095("ERR_04095"),
- ERR_04096("ERR_04096"),
- ERR_04097("ERR_04097"),
- ERR_04098("ERR_04098"),
- ERR_04099("ERR_04099"),
- ERR_04100("ERR_04100"),
+ ERR_04096_NULL_CONTROL_LENGTH("ERR_04096_NULL_CONTROL_LENGTH"),
+ ERR_04097_NULL_CONTROL_OID("ERR_04097_NULL_CONTROL_OID"),
+ ERR_04098_INVALID_CONTROL_OID("ERR_04098_INVALID_CONTROL_OID"),
+ ERR_04099_INVALID_CONTROL_LIST("ERR_04099_INVALID_CONTROL_LIST"),
+ ERR_04100_BAD_CONTROL_CRITICALITY("ERR_04100_BAD_CONTROL_CRITICALITY"),
ERR_04101("ERR_04101"),
ERR_04102("ERR_04102"),
ERR_04103("ERR_04103"),
@@ -629,6 +629,7 @@ public enum I18n
ERR_04488_NULL_ATTRIBUTE_TYPE("ERR_04488_NULL_ATTRIBUTE_TYPE"),
ERR_04489_SYNTAX_INVALID("ERR_04489_SYNTAX_INVALID"),
ERR_04490_BAD_END_TRANSACTION_COMMIT("ERR_04490_BAD_END_TRANSACTION_COMMIT"),
+ ERR_04491_BAD_END_TRANSACTION_MESSAGE_ID("ERR_04490_BAD_END_TRANSACTION_MESSAGE_ID"),
// ldap-constants
ERR_05001_UNKNOWN_AUTHENT_LEVEL("ERR_05001_UNKNOWN_AUTHENT_LEVEL"),
diff --git a/i18n/src/main/resources/org/apache/directory/api/i18n/errors.properties b/i18n/src/main/resources/org/apache/directory/api/i18n/errors.properties
index c4df656..c3f1ae4 100644
--- a/i18n/src/main/resources/org/apache/directory/api/i18n/errors.properties
+++ b/i18n/src/main/resources/org/apache/directory/api/i18n/errors.properties
@@ -221,11 +221,11 @@ ERR_04092=The new superior must not be null if the flag ''delete old DN'' is set
ERR_04093=The attribute description must not be null
ERR_04094=The CompareResponse must not be null
ERR_04095=The name must not be null
-ERR_04096=The length of a control must not be null
-ERR_04097=The OID must not be null
-ERR_04098=The control type {0} is not a valid OID
-ERR_04099=Invalid control OID : {0}
-ERR_04100=The control criticality flag {0} is invalid : {1}. It should be 0 or 255
+ERR_04096_NULL_CONTROL_LENGTH=The length of a control must not be null
+ERR_04097_NULL_CONTROL_OID=The OID must not be null
+ERR_04098_INVALID_CONTROL_OID=The control type {0} is not a valid OID
+ERR_04099_INVALID_CONTROL_LIST=Invalid control list {0} : {1}
+ERR_04100_BAD_CONTROL_CRITICALITY=The control criticality flag {0} is invalid : {1}. It should be 0 or 255
ERR_04101=The scope is not in [0..2] : {0}
ERR_04102=The derefAlias is not in [0..3] : {0}
ERR_04103=The sizeLimit is not a valid Integer: {0}
@@ -616,6 +616,7 @@ ERR_04487_ATTRIBUTE_IS_SINGLE_VALUED=The attribute ''{0}'' is single valued, we
ERR_04488_NULL_ATTRIBUTE_TYPE=The AttributeType cannot be null
ERR_04489_SYNTAX_INVALID=Syntax invalid for ''{0}''
ERR_04490_BAD_END_TRANSACTION_COMMIT=The EndTransactionRequest Commit value {0} is invalid: {1}. It should be 0 or 255
+ERR_04490_BAD_END_TRANSACTION_MESSAGE_ID=The endTransactionResponse UpdateControl MessageID value {0} is invalid: {1}. It should be a numeric value
# ldap-constants
ERR_05001_UNKNOWN_AUTHENT_LEVEL=Unknown AuthenticationLevel {0}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/CheckLengthNotNull.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/CheckLengthNotNull.java
index 1fdc2f3..ed23577 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/CheckLengthNotNull.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/CheckLengthNotNull.java
@@ -62,7 +62,7 @@ public class CheckLengthNotNull extends GrammarAction<LdapMessageContainer<Messa
// The Length should be null
if ( expectedLength == 0 )
{
- String msg = I18n.err( I18n.ERR_04096 );
+ String msg = I18n.err( I18n.ERR_04096_NULL_CONTROL_LENGTH );
LOG.error( msg );
// This will generate a PROTOCOL_ERROR
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/AddControl.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/AddControl.java
index d9f0a99..4a89e2a 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/AddControl.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/AddControl.java
@@ -73,7 +73,7 @@ public class AddControl extends GrammarAction<LdapMessageContainer<MessageDecora
// We have to handle the special case of a 0 length OID
if ( tlv.getLength() == 0 )
{
- String msg = I18n.err( I18n.ERR_04097 );
+ String msg = I18n.err( I18n.ERR_04097_NULL_CONTROL_OID );
LOG.error( msg );
// This will generate a PROTOCOL_ERROR
@@ -86,10 +86,11 @@ public class AddControl extends GrammarAction<LdapMessageContainer<MessageDecora
// The OID is encoded as a String, not an Object Id
if ( !Oid.isOid( oidValue ) )
{
- LOG.error( I18n.err( I18n.ERR_04098, Strings.dumpBytes( value ) ) );
+ String msg = I18n.err( I18n.ERR_04098_INVALID_CONTROL_OID, oidValue );
+ LOG.error( msg );
// This will generate a PROTOCOL_ERROR
- throw new DecoderException( I18n.err( I18n.ERR_04099, oidValue ) );
+ throw new DecoderException( msg );
}
Message message = container.getMessage();
@@ -103,7 +104,7 @@ public class AddControl extends GrammarAction<LdapMessageContainer<MessageDecora
if ( IS_DEBUG )
{
- LOG.debug( "Control OID : " + oidValue );
+ LOG.debug( "Control OID : {}", oidValue );
}
}
}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlCriticality.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlCriticality.java
index c221fe0..582434a 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlCriticality.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlCriticality.java
@@ -73,10 +73,8 @@ public class StoreControlCriticality extends GrammarAction<LdapMessageContainer<
TLV tlv = container.getCurrentTLV();
// Get the current control
- Control control;
-
MessageDecorator<? extends Message> message = container.getMessage();
- control = message.getCurrentControl();
+ Control control = message.getCurrentControl();
// Store the criticality
// We get the value. If it's a 0, it's a FALSE. If it's
@@ -94,7 +92,7 @@ public class StoreControlCriticality extends GrammarAction<LdapMessageContainer<
catch ( BooleanDecoderException bde )
{
LOG.error( I18n
- .err( I18n.ERR_04100, Strings.dumpBytes( value.getData() ), bde.getMessage() ) );
+ .err( I18n.ERR_04100_BAD_CONTROL_CRITICALITY, Strings.dumpBytes( value.getData() ), bde.getMessage() ) );
// This will generate a PROTOCOL_ERROR
throw new DecoderException( bde.getMessage(), bde );
@@ -105,7 +103,7 @@ public class StoreControlCriticality extends GrammarAction<LdapMessageContainer<
if ( IS_DEBUG )
{
- LOG.debug( "Control criticality : " + control.isCritical() );
+ LOG.debug( "Control criticality : {}", control.isCritical() );
}
}
}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapEncoder.java b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapEncoder.java
index da795c0..911a545 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapEncoder.java
+++ b/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/api/LdapEncoder.java
@@ -67,7 +67,7 @@ public class LdapEncoder
/**
* Compute the control's encoded length
*/
- private int computeControlLength( Control control )
+ public static int computeControlLength( Control control )
{
// First, compute the control's value length
int controlValueLength = ( ( CodecControl<?> ) control ).computeLength();
@@ -96,7 +96,7 @@ public class LdapEncoder
/**
* Encode a control to a byte[]
*/
- private ByteBuffer encodeControl( ByteBuffer buffer, Control control ) throws EncoderException
+ public static ByteBuffer encodeControl( ByteBuffer buffer, Control control ) throws EncoderException
{
if ( buffer == null )
{
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/endTransaction/EndTransactionResponse.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/endTransaction/EndTransactionResponse.java
index eac3f1f..4b92a89 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/endTransaction/EndTransactionResponse.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/endTransaction/EndTransactionResponse.java
@@ -59,10 +59,17 @@ public interface EndTransactionResponse extends ExtendedResponse
/**
- * @return The Message ID if failire
+ * @return The Message ID if failure
*/
int getFailedMessageId();
+
+ /**
+ * @param failedMessageId The messageId that causes the failure
+ */
+ void setFailedMessageId( int failedMessageId );
+
+
/**
* @return the list of <messageId, Controls> processed within the transaction
*/
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/endTransaction/EndTransactionResponseImpl.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/endTransaction/EndTransactionResponseImpl.java
index a0efe68..e3a5fa1 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/endTransaction/EndTransactionResponseImpl.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/endTransaction/EndTransactionResponseImpl.java
@@ -57,7 +57,7 @@ import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
public class EndTransactionResponseImpl extends ExtendedResponseImpl implements EndTransactionResponse
{
/** The faulty Message ID, if any */
- private int failedMessageId;
+ private int failedMessageId = -1;
/** The list of update controls for the message processed in the transaction */
private List<UpdateControls> updateControls = new ArrayList<>();
@@ -137,6 +137,7 @@ public class EndTransactionResponseImpl extends ExtendedResponseImpl implements
/**
* {@inheritDoc}
*/
+ @Override
public void setFailedMessageId( int failedMessageId )
{
this.failedMessageId = failedMessageId;
@@ -145,6 +146,7 @@ public class EndTransactionResponseImpl extends ExtendedResponseImpl implements
/**
* @return the updateControls
*/
+ @Override
public List<UpdateControls> getUpdateControls()
{
return updateControls;
diff --git a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/endTransaction/UpdateControls.java b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/endTransaction/UpdateControls.java
index 6962ef9..46c23df 100644
--- a/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/endTransaction/UpdateControls.java
+++ b/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/endTransaction/UpdateControls.java
@@ -22,7 +22,7 @@ package org.apache.directory.api.ldap.extras.extended.endTransaction;
import java.util.ArrayList;
import java.util.List;
-import javax.naming.ldap.Control;
+import org.apache.directory.api.ldap.model.message.Control;
/**
* The interface for End Transaction Extended Response UpdateControl. It's described in RFC 5805 :
@@ -180,7 +180,7 @@ public class UpdateControls
sb.append( ", " );
}
- sb.append( control.getID() );
+ sb.append( control.getOid() );
}
sb.append( ']' );
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestContainer.java
index 14b48cf..573a048 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestContainer.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestContainer.java
@@ -42,7 +42,7 @@ public class EndTransactionRequestContainer extends AbstractContainer
{
super();
setGrammar( EndTransactionRequestGrammar.getInstance() );
- setTransition( EndTransactionRequestStatesEnum.START_STATE );
+ setTransition( EndTransactionRequestStates.START_STATE );
}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestGrammar.java
index f012f10..610e8d5 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestGrammar.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestGrammar.java
@@ -28,7 +28,6 @@ import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
import org.apache.directory.api.asn1.ber.tlv.BerValue;
import org.apache.directory.api.asn1.ber.tlv.BooleanDecoder;
import org.apache.directory.api.asn1.ber.tlv.BooleanDecoderException;
-import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
import org.apache.directory.api.i18n.I18n;
import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
import org.apache.directory.api.ldap.extras.extended.endTransaction.EndTransactionRequestImpl;
@@ -36,6 +35,9 @@ import org.apache.directory.api.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static org.apache.directory.api.asn1.ber.tlv.UniversalTag.BOOLEAN;
+import static org.apache.directory.api.asn1.ber.tlv.UniversalTag.OCTET_STRING;
+import static org.apache.directory.api.asn1.ber.tlv.UniversalTag.SEQUENCE;
/**
* This class implements the EndTransactionRequest extended operation's ASN.1 grammar.
@@ -73,7 +75,7 @@ public class EndTransactionRequestGrammar extends AbstractGrammar<EndTransaction
setName( EndTransactionRequestGrammar.class.getName() );
// Create the transitions table
- super.transitions = new GrammarTransition[EndTransactionRequestStatesEnum.LAST_STATE
+ super.transitions = new GrammarTransition[EndTransactionRequestStates.LAST_STATE
.ordinal()][256];
/**
@@ -84,11 +86,11 @@ public class EndTransactionRequestGrammar extends AbstractGrammar<EndTransaction
*
* Creates the EndTransactionRequest object
*/
- super.transitions[EndTransactionRequestStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
+ super.transitions[EndTransactionRequestStates.START_STATE.ordinal()][SEQUENCE.getValue()] =
new GrammarTransition<EndTransactionRequestContainer>(
- EndTransactionRequestStatesEnum.START_STATE,
- EndTransactionRequestStatesEnum.SEQUENCE_STATE,
- UniversalTag.SEQUENCE.getValue(),
+ EndTransactionRequestStates.START_STATE,
+ EndTransactionRequestStates.SEQUENCE_STATE,
+ SEQUENCE,
new GrammarAction<EndTransactionRequestContainer>( "Init EndTransactionRequest" )
{
public void action( EndTransactionRequestContainer container )
@@ -108,11 +110,11 @@ public class EndTransactionRequestGrammar extends AbstractGrammar<EndTransaction
*
* Set the commit flag into the EndTransactionRequest instance.
*/
- super.transitions[EndTransactionRequestStatesEnum.SEQUENCE_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
+ super.transitions[EndTransactionRequestStates.SEQUENCE_STATE.ordinal()][BOOLEAN.getValue()] =
new GrammarTransition<EndTransactionRequestContainer>(
- EndTransactionRequestStatesEnum.SEQUENCE_STATE,
- EndTransactionRequestStatesEnum.COMMIT_STATE,
- UniversalTag.BOOLEAN.getValue(),
+ EndTransactionRequestStates.SEQUENCE_STATE,
+ EndTransactionRequestStates.COMMIT_STATE,
+ BOOLEAN,
new GrammarAction<EndTransactionRequestContainer>( "Set EndTransactionRequest commit flag" )
{
public void action( EndTransactionRequestContainer container ) throws DecoderException
@@ -142,14 +144,14 @@ public class EndTransactionRequestGrammar extends AbstractGrammar<EndTransaction
*
* Set the commit flag into the EndTransactionRequest instance.
*/
- super.transitions[EndTransactionRequestStatesEnum.SEQUENCE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
+ super.transitions[EndTransactionRequestStates.SEQUENCE_STATE.ordinal()][OCTET_STRING.getValue()] =
new GrammarTransition<EndTransactionRequestContainer>(
- EndTransactionRequestStatesEnum.SEQUENCE_STATE,
- EndTransactionRequestStatesEnum.IDENTFIER_STATE,
- UniversalTag.OCTET_STRING.getValue(),
+ EndTransactionRequestStates.SEQUENCE_STATE,
+ EndTransactionRequestStates.IDENTFIER_STATE,
+ OCTET_STRING,
new GrammarAction<EndTransactionRequestContainer>( "Set EndTransactionRequest identifier" )
{
- public void action( EndTransactionRequestContainer container ) throws DecoderException
+ public void action( EndTransactionRequestContainer container )
{
BerValue value = container.getCurrentTLV().getValue();
@@ -181,14 +183,14 @@ public class EndTransactionRequestGrammar extends AbstractGrammar<EndTransaction
*
* Set the identifier into the EndTransactionRequest instance.
*/
- super.transitions[EndTransactionRequestStatesEnum.COMMIT_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
+ super.transitions[EndTransactionRequestStates.COMMIT_STATE.ordinal()][OCTET_STRING.getValue()] =
new GrammarTransition<EndTransactionRequestContainer>(
- EndTransactionRequestStatesEnum.COMMIT_STATE,
- EndTransactionRequestStatesEnum.IDENTFIER_STATE,
- UniversalTag.OCTET_STRING.getValue(),
+ EndTransactionRequestStates.COMMIT_STATE,
+ EndTransactionRequestStates.IDENTFIER_STATE,
+ OCTET_STRING,
new GrammarAction<EndTransactionRequestContainer>( "Set EndTransactionRequest identifier" )
{
- public void action( EndTransactionRequestContainer container ) throws DecoderException
+ public void action( EndTransactionRequestContainer container )
{
BerValue value = container.getCurrentTLV().getValue();
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestStatesEnum.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestStates.java
similarity index 94%
copy from ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestStatesEnum.java
copy to ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestStates.java
index 9fc8b5f..8c42f64 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestStatesEnum.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestStates.java
@@ -29,7 +29,7 @@ import org.apache.directory.api.asn1.ber.grammar.States;
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
-public enum EndTransactionRequestStatesEnum implements States
+public enum EndTransactionRequestStates implements States
{
/** The END_STATE */
END_STATE,
@@ -87,7 +87,7 @@ public enum EndTransactionRequestStatesEnum implements States
* {@inheritDoc}
*/
@Override
- public EndTransactionRequestStatesEnum getStartState()
+ public EndTransactionRequestStates getStartState()
{
return START_STATE;
}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseContainer.java
new file mode 100644
index 0000000..6b13145
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseContainer.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.directory.api.ldap.extras.extended.ads_impl.endTransaction;
+
+
+import java.nio.ByteBuffer;
+import java.util.List;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.AbstractContainer;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.asn1.ber.tlv.TLVStateEnum;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls.ControlsContainer;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls.ControlsStates;
+import org.apache.directory.api.ldap.model.message.Control;
+
+
+/**
+ * A container for EndTransactionResponse codec.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class EndTransactionResponseContainer extends AbstractContainer
+{
+ /** EndTransactionResponse decorator*/
+ private EndTransactionResponseDecorator endTransactionResponse;
+
+ private static final Asn1Decoder DECODER = new Asn1Decoder();
+
+ /**
+ * Creates a new EndTransactionResponseContainer object. We will store one
+ * grammar, it's enough ...
+ */
+ public EndTransactionResponseContainer()
+ {
+ super();
+ setGrammar( EndTransactionResponseGrammar.getInstance() );
+ setTransition( EndTransactionResponseStates.START_STATE );
+ }
+
+
+ /**
+ * @return Returns the EndTransactionResponse instance.
+ */
+ public EndTransactionResponseDecorator getEndTransactionResponse()
+ {
+ return endTransactionResponse;
+ }
+
+
+ /**
+ * Set a EndTransactionResponse Object into the container. It will be completed by
+ * the ldapDecoder.
+ *
+ * @param endTransactionResponseDecorator the EndTransactionResponse to set.
+ */
+ public void setEndTransactionResponse( EndTransactionResponseDecorator endTransactionResponseDecorator )
+ {
+ this.endTransactionResponse = endTransactionResponseDecorator;
+ }
+
+
+ /**
+ * Clean the container for the next decoding.
+ */
+ @Override
+ public void clean()
+ {
+ super.clean();
+ endTransactionResponse = null;
+ }
+
+
+ /**
+ * Decodes raw ASN.1 encoded bytes into an Asn1Object for the controls.
+ *
+ * @param controlsBytes the encoded controls bytes
+ * @return the decoded controls
+ * @throws DecoderException if anything goes wrong
+ */
+ public static List<Control> decode( byte[] controlsBytes ) throws DecoderException
+ {
+ ByteBuffer bb = ByteBuffer.wrap( controlsBytes );
+ ControlsContainer container = new ControlsContainer();
+
+ // Loop on all the contained controls
+ while ( bb.hasRemaining() )
+ {
+ DECODER.decode( bb, container );
+ container.setState( TLVStateEnum.TAG_STATE_START );
+ container.setTransition( ControlsStates.START_STATE );
+ }
+
+ return container.getControls();
+ }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseDecoder.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseDecoder.java
new file mode 100644
index 0000000..75a8189
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseDecoder.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.directory.api.ldap.extras.extended.ads_impl.endTransaction;
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.ldap.extras.extended.endTransaction.EndTransactionResponse;
+
+
+/**
+ * A decoder for EndTransactionResponse.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class EndTransactionResponseDecoder extends Asn1Decoder
+{
+ /** The decoder */
+ private static final Asn1Decoder DECODER = new Asn1Decoder();
+
+ /**
+ * Decode a PDU which must contain a EndTransactionResponse extended operation.
+ * Note that the stream of bytes much contain a full PDU, not a partial one.
+ *
+ * @param stream The bytes to be decoded
+ * @return a EndTransactionResponse object
+ * @throws org.apache.directory.api.asn1.DecoderException If the decoding failed
+ */
+ public EndTransactionResponse decode( byte[] stream ) throws DecoderException
+ {
+ ByteBuffer bb = ByteBuffer.wrap( stream );
+ EndTransactionResponseContainer container = new EndTransactionResponseContainer();
+ DECODER.decode( bb, container );
+ EndTransactionResponseDecorator endTransactionResponse = container.getEndTransactionResponse();
+
+ // Clean the container for the next decoding
+ container.clean();
+
+ return endTransactionResponse;
+ }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseDecorator.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseDecorator.java
index 0d194c2..e87e4fb 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseDecorator.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseDecorator.java
@@ -20,13 +20,24 @@
package org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction;
+import java.nio.ByteBuffer;
import java.util.List;
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
+import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.codec.api.CodecControl;
import org.apache.directory.api.ldap.codec.api.ExtendedResponseDecorator;
import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.codec.api.LdapEncoder;
import org.apache.directory.api.ldap.extras.extended.endTransaction.EndTransactionResponse;
import org.apache.directory.api.ldap.extras.extended.endTransaction.UpdateControls;
-import org.apache.directory.api.util.Strings;
+import org.apache.directory.api.ldap.model.message.Control;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
@@ -36,11 +47,28 @@ import org.apache.directory.api.util.Strings;
*/
public class EndTransactionResponseDecorator extends ExtendedResponseDecorator<EndTransactionResponse> implements EndTransactionResponse
{
+ private static final Logger LOG = LoggerFactory.getLogger( EndTransactionResponseDecorator.class );
+
/** The endTransaction response */
private EndTransactionResponse endTransactionResponse;
- /** stores the length of the request*/
- private int requestLength = 0;
+ /** The current UpdateControls */
+ private UpdateControls currentUpdateControls;
+
+ /** Stores the length of the request*/
+ private int globalSequenceLength = 0;
+
+ /** Stores the length of the updateControls part */
+ private int updateSequenceLength = 0;
+
+ /** Stores the length of updateControls */
+ private int[] updateControlsLength;
+
+ /** Stores the Controls global lengths */
+ private int[] controlsLengths;
+
+ /** The message controls' lengths */
+ private int[][] controlLengths;
/**
* Creates a new instance of EndTransactionResponseDecorator.
@@ -61,7 +89,27 @@ public class EndTransactionResponseDecorator extends ExtendedResponseDecorator<E
@Override
public void setResponseValue( byte[] responseValue )
{
- this.responseValue = Strings.copy( responseValue );
+ EndTransactionResponseDecoder decoder = new EndTransactionResponseDecoder();
+
+ try
+ {
+ if ( responseValue != null )
+ {
+ endTransactionResponse = decoder.decode( responseValue );
+
+ this.responseValue = new byte[responseValue.length];
+ System.arraycopy( responseValue, 0, this.responseValue, 0, responseValue.length );
+ }
+ else
+ {
+ this.responseValue = null;
+ }
+ }
+ catch ( DecoderException e )
+ {
+ LOG.error( I18n.err( I18n.ERR_04165_PAYLOAD_DECODING_ERROR ), e );
+ throw new RuntimeException( e );
+ }
}
@@ -75,9 +123,200 @@ public class EndTransactionResponseDecorator extends ExtendedResponseDecorator<E
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setFailedMessageId( int failedMessageId )
+ {
+ endTransactionResponse.setFailedMessageId( failedMessageId );
+ }
+
+
@Override
public List<UpdateControls> getUpdateControls()
{
return endTransactionResponse.getUpdateControls();
}
+
+
+ /**
+ * @return the currentUpdateControls
+ */
+ public UpdateControls getCurrentUpdateControls()
+ {
+ return currentUpdateControls;
+ }
+
+
+ /**
+ * @param currentUpdateControls the currentUpdateControls to set
+ */
+ public void setCurrentControls( UpdateControls currentUpdateControls )
+ {
+ this.currentUpdateControls = currentUpdateControls;
+ }
+
+
+ /**
+ * Compute the EndTransactionResponse extended operation length
+ * <pre>
+ * 0x30 L1
+ * |
+ * [+-- 0x02 L2 failed message ID]
+ * [+-- 0x30 L3 updateControls SEQUENCE OF
+ * |
+ * +-- 0x30 L4 updateControls SEQUENCE
+ * |
+ * +-- 0x02 L5 messageID
+ * +-- <controls>]
+ *
+ * </pre>
+ */
+ /* No qualifier */int computeLengthInternal()
+ {
+ globalSequenceLength = 0;
+
+ if ( endTransactionResponse.getFailedMessageId() >= 0 )
+ {
+ // We have had a failure, there is no updateControls just the failed MessageID
+ globalSequenceLength = 1 + 1 + BerValue.getNbBytes( endTransactionResponse.getFailedMessageId() );
+
+ // The message ID length is always below 128, so we only need 1 byte for the global length
+ return 1 + 1 + globalSequenceLength;
+ }
+ else
+ {
+ // If it's a success, we won't have a messageId, just update controls (if any)
+ int updateControlsSize = getUpdateControls().size();
+
+ if ( updateControlsSize > 0 )
+ {
+ updateControlsLength = new int[updateControlsSize];
+ controlsLengths = new int[updateControlsSize];
+ controlLengths = new int[updateControlsSize][];
+ int messageControlsCount = 0;
+ updateSequenceLength = 0;
+
+ // Ok, process the updateControls
+ for ( UpdateControls updateControls : getUpdateControls() )
+ {
+ // The message ID, 0x02 LL and the ID
+ updateControlsLength[messageControlsCount] = 1 + 1 + BerValue.getNbBytes( updateControls.getMessageId() );
+
+ // The controls
+ int controlNumber = updateControls.getControls().size();
+
+ if ( controlNumber > 0 )
+ {
+ int controlCount = 0;
+ controlLengths[messageControlsCount] = new int[controlNumber];
+
+ for ( Control control : updateControls.getControls() )
+ {
+ controlLengths[messageControlsCount][controlCount] = LdapEncoder.computeControlLength( control );
+ controlsLengths[messageControlsCount] += 1 + TLV.getNbBytes( controlLengths[messageControlsCount][controlCount] ) + controlLengths[messageControlsCount][controlCount];
+ controlCount++;
+ }
+
+ int controlsLength = controlsLengths[messageControlsCount];
+ updateControlsLength[messageControlsCount] += 1 + TLV.getNbBytes( controlsLength ) + controlsLength;
+ }
+
+ updateSequenceLength += 1 + TLV.getNbBytes( updateControlsLength[messageControlsCount] )
+ + updateControlsLength[messageControlsCount];
+
+ messageControlsCount++;
+ }
+
+ globalSequenceLength = 1 + TLV.getNbBytes( updateSequenceLength ) + updateSequenceLength;
+
+ return 1 + TLV.getNbBytes( globalSequenceLength ) + globalSequenceLength;
+ }
+ else
+ {
+ // No update control, return immediately
+ return 0;
+ }
+ }
+ }
+
+
+ /**
+ * Encodes the EndTransactionResponse extended operation.
+ *
+ * @return A ByteBuffer that contains the encoded PDU
+ * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong.
+ */
+ /* No qualifier */ByteBuffer encodeInternal() throws EncoderException
+ {
+ ByteBuffer bb = ByteBuffer.allocate( computeLengthInternal() );
+
+ bb.put( UniversalTag.SEQUENCE.getValue() );
+ bb.put( TLV.getBytes( globalSequenceLength ) );
+
+ // The failed message id, if any
+ if ( getFailedMessageId() >= 0 )
+ {
+ // We have had an error, just encode the messageId
+ BerValue.encode( bb, getFailedMessageId() );
+ }
+ else
+ {
+ // No error, just updateControls
+ bb.put( UniversalTag.SEQUENCE.getValue() );
+ bb.put( TLV.getBytes( updateSequenceLength ) );
+
+ int updateControlsNb = 0;
+
+ for ( UpdateControls updateControls : getUpdateControls() )
+ {
+ // The updateControls length
+ bb.put( UniversalTag.SEQUENCE.getValue() );
+ bb.put( TLV.getBytes( updateControlsLength[updateControlsNb] ) );
+
+ // The message ID
+ BerValue.encode( bb, updateControls.getMessageId() );
+
+ // The controls sequence
+ bb.put( UniversalTag.SEQUENCE.getValue() );
+ bb.put( TLV.getBytes( controlsLengths[updateControlsNb] ) );
+
+ // The controls
+ int controlNb = 0;
+
+ for ( Control control : updateControls.getControls() )
+ {
+ // The control SEQUENCE
+ bb.put( UniversalTag.SEQUENCE.getValue() );
+ bb.put( TLV.getBytes( controlLengths[updateControlsNb][controlNb] ) );
+
+ // The control OID
+ BerValue.encode( bb, control.getOid() );
+
+ // The criticality, if true
+ if ( control.isCritical() )
+ {
+ BerValue.encode( bb, true );
+ }
+
+ // compute the value length
+ int valueLength = ( ( CodecControl<?> ) control ).computeLength();
+
+ if ( valueLength > 0 )
+ {
+ bb.put( UniversalTag.OCTET_STRING.getValue() );
+ bb.put( TLV.getBytes( valueLength ) );
+ ( ( CodecControl<?> ) control ).encode( bb );
+ }
+
+ controlNb++;
+ }
+
+ updateControlsNb++;
+ }
+ }
+
+ return bb;
+ }
}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseGrammar.java
new file mode 100644
index 0000000..1a570f0
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseGrammar.java
@@ -0,0 +1,330 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.directory.api.ldap.extras.extended.ads_impl.endTransaction;
+
+
+import static org.apache.directory.api.asn1.ber.tlv.UniversalTag.SEQUENCE;
+
+import java.util.List;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
+import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.IntegerDecoder;
+import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
+import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
+import org.apache.directory.api.ldap.extras.extended.endTransaction.EndTransactionResponseImpl;
+import org.apache.directory.api.ldap.extras.extended.endTransaction.UpdateControls;
+import org.apache.directory.api.ldap.model.message.Control;
+import org.apache.directory.api.util.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.directory.api.asn1.ber.tlv.UniversalTag.INTEGER;
+
+/**
+ * This class implements the EndTransactionResponse extended operation's ASN.1 grammar.
+ * All the actions are declared in this class. As it is a singleton,
+ * these declaration are only done once. The grammar is :
+ *
+ * <pre>
+ * txnEndRes ::= SEQUENCE {
+ * messageID MessageID OPTIONAL,
+ * -- msgid associated with non-success resultCode
+ * updatesControls SEQUENCE OF updateControl SEQUENCE {
+ * messageID MessageID,
+ * -- msgid associated with controls
+ * controls Controls
+ * } OPTIONAL
+ * }
+ * </pre>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class EndTransactionResponseGrammar extends AbstractGrammar<EndTransactionResponseContainer>
+{
+ /** logger */
+ private static final Logger LOG = LoggerFactory.getLogger( EndTransactionResponseGrammar.class );
+
+ /** Speedup for logs */
+ static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+ /** The instance of grammar. EndTransactionResponseGrammar is a singleton */
+ private static Grammar<EndTransactionResponseContainer> instance = new EndTransactionResponseGrammar();
+
+
+ /**
+ * Creates a new EndTransactionResponseGrammar object.
+ */
+ @SuppressWarnings("unchecked")
+ public EndTransactionResponseGrammar()
+ {
+ setName( EndTransactionResponseGrammar.class.getName() );
+
+ // Create the transitions table
+ super.transitions = new GrammarTransition[EndTransactionResponseStates.LAST_STATE
+ .ordinal()][256];
+
+ /**
+ * Transition from init state to EndTransactionResponse Sequence
+ *
+ * txnEndRes ::= SEQUENCE {
+ * ...
+ *
+ * Creates the EndTransactionResponse object
+ */
+ super.transitions[EndTransactionResponseStates.START_STATE.ordinal()][SEQUENCE.getValue()] =
+ new GrammarTransition<EndTransactionResponseContainer>(
+ EndTransactionResponseStates.START_STATE,
+ EndTransactionResponseStates.END_TRANSACTION_SEQUENCE_STATE,
+ SEQUENCE,
+ new GrammarAction<EndTransactionResponseContainer>( "Init EndTransactionResponse" )
+ {
+ public void action( EndTransactionResponseContainer container )
+ {
+ // Create the decorator, and stores it in the container
+ EndTransactionResponseDecorator endTransactionResponseDecorator = new EndTransactionResponseDecorator(
+ LdapApiServiceFactory.getSingleton(), new EndTransactionResponseImpl() );
+ container.setEndTransactionResponse( endTransactionResponseDecorator );
+ }
+ } );
+
+ /**
+ * Transition from Sequence to messageId
+ *
+ * txnEndReq ::= SEQUENCE {
+ * messageID MessageID OPTIONAL,
+ * -- msgid associated with non-success resultCode
+ * ...
+ *
+ * Set the messageId into the EndTransactionResponse instance, if it's not SUCCESS.
+ */
+ super.transitions[EndTransactionResponseStates.END_TRANSACTION_SEQUENCE_STATE.ordinal()][INTEGER.getValue()] =
+ new GrammarTransition<EndTransactionResponseContainer>(
+ EndTransactionResponseStates.END_TRANSACTION_SEQUENCE_STATE,
+ EndTransactionResponseStates.FAILED_MESSAGE_ID_STATE,
+ INTEGER,
+ new GrammarAction<EndTransactionResponseContainer>( "Set EndTransactionResponse failed MessageID" )
+ {
+ public void action( EndTransactionResponseContainer container ) throws DecoderException
+ {
+ BerValue value = container.getCurrentTLV().getValue();
+
+ try
+ {
+ int failedMessageId = IntegerDecoder.parse( value );
+
+ if ( failedMessageId > 0 )
+ {
+ container.getEndTransactionResponse().setFailedMessageId( failedMessageId );
+ }
+
+ // We may have nothing left
+ container.setGrammarEndAllowed( true );
+ }
+ catch ( IntegerDecoderException ide )
+ {
+ LOG.error( I18n
+ .err( I18n.ERR_04490_BAD_END_TRANSACTION_COMMIT, Strings.dumpBytes( value.getData() ), ide.getMessage() ) );
+
+ // This will generate a PROTOCOL_ERROR
+ throw new DecoderException( ide.getMessage(), ide );
+ }
+ }
+ } );
+
+
+ /**
+ * Transition from Sequence to updateControls
+ *
+ * txnEndReq ::= SEQUENCE {
+ * ...
+ * updatesControls SEQUENCE OF updateControls SEQUENCE {
+ *
+ * Nothing to do, just transitionning
+ */
+ super.transitions[EndTransactionResponseStates.END_TRANSACTION_SEQUENCE_STATE.ordinal()][SEQUENCE.getValue()] =
+ new GrammarTransition<EndTransactionResponseContainer>(
+ EndTransactionResponseStates.END_TRANSACTION_SEQUENCE_STATE,
+ EndTransactionResponseStates.UPDATE_CONTROLS_SEQ_STATE,
+ SEQUENCE );
+
+
+ /**
+ * Transition from updateControls to updateControl
+ *
+ * txnEndReq ::= SEQUENCE {
+ * ...updateControls SEQUENCE {
+ *
+ * Create a new UpdateControls instane
+ */
+ super.transitions[EndTransactionResponseStates.UPDATE_CONTROLS_SEQ_STATE.ordinal()][SEQUENCE.getValue()] =
+ new GrammarTransition<EndTransactionResponseContainer>(
+ EndTransactionResponseStates.UPDATE_CONTROLS_SEQ_STATE,
+ EndTransactionResponseStates.UPDATE_CONTROL_SEQ_STATE,
+ SEQUENCE,
+ new GrammarAction<EndTransactionResponseContainer>( "Create an updateControl" )
+ {
+ public void action( EndTransactionResponseContainer container )
+ {
+ // Create the current UpdateControls
+ UpdateControls currentUpdateControls = new UpdateControls();
+
+ container.getEndTransactionResponse().setCurrentControls( currentUpdateControls );
+ }
+ } );
+
+
+ /**
+ * Transition from updateControl to messageId
+ *
+ * txnEndReq ::= SEQUENCE {
+ * ...
+ * messageID MessageID,
+ *
+ * Set the messageId into the current updateControl
+ */
+ super.transitions[EndTransactionResponseStates.UPDATE_CONTROL_SEQ_STATE.ordinal()][INTEGER.getValue()] =
+ new GrammarTransition<EndTransactionResponseContainer>(
+ EndTransactionResponseStates.UPDATE_CONTROL_SEQ_STATE,
+ EndTransactionResponseStates.CONTROL_MESSAGE_ID_STATE,
+ INTEGER,
+ new GrammarAction<EndTransactionResponseContainer>( "Get the updateControl messageId" )
+ {
+ public void action( EndTransactionResponseContainer container ) throws DecoderException
+ {
+ UpdateControls currentUpdateControls = container.getEndTransactionResponse().getCurrentUpdateControls();
+ BerValue value = container.getCurrentTLV().getValue();
+
+ try
+ {
+ int messageId = IntegerDecoder.parse( value );
+
+ currentUpdateControls.setMessageId( messageId );
+
+ // Make the container gather the following bytes
+ container.setGathering( true );
+ }
+ catch ( IntegerDecoderException ide )
+ {
+ LOG.error( I18n
+ .err( I18n.ERR_04491_BAD_END_TRANSACTION_MESSAGE_ID, Strings.dumpBytes( value.getData() ),
+ ide.getMessage() ) );
+
+ // This will generate a PROTOCOL_ERROR
+ throw new DecoderException( ide.getMessage(), ide );
+ }
+ }
+ } );
+
+
+ /**
+ * ...
+ * messageID MessageID,
+ * -- msgid associated with controls
+ * controls Controls
+ * ...
+ *
+ * Process the controls
+ */
+ super.transitions[EndTransactionResponseStates.CONTROL_MESSAGE_ID_STATE.ordinal()][SEQUENCE.getValue()] =
+ new GrammarTransition<EndTransactionResponseContainer>(
+ EndTransactionResponseStates.CONTROL_MESSAGE_ID_STATE,
+ EndTransactionResponseStates.CONTROLS_STATE,
+ SEQUENCE,
+ new GrammarAction<EndTransactionResponseContainer>( "Process the controls" )
+ {
+ public void action( EndTransactionResponseContainer container ) throws DecoderException
+ {
+ BerValue value = container.getCurrentTLV().getValue();
+
+ container.setGathering( false );
+
+ try
+ {
+ List<Control> controls = EndTransactionResponseContainer.decode( value.getData() );
+
+ // Add the updateControls to the list of updateControls
+ UpdateControls currentUpdateControls = container.getEndTransactionResponse().getCurrentUpdateControls();
+
+ // Add the decoder controls
+ currentUpdateControls.setControls( controls );
+
+ // And add the decoded updateControls to the list of updateControls
+ container.getEndTransactionResponse().getUpdateControls().add( currentUpdateControls );
+ }
+ catch ( DecoderException de )
+ {
+ // Add an error
+ LOG.error( I18n
+ .err( I18n.ERR_04099_INVALID_CONTROL_LIST, Strings.dumpBytes( value.getData() ),
+ de.getMessage() ) );
+
+ // This will generate a PROTOCOL_ERROR
+ throw new DecoderException( de.getMessage(), de );
+ }
+
+ // We may have nothing left
+ container.setGrammarEndAllowed( true );
+ }
+ } );
+
+
+ /**
+ * Transition from controls to updateControl
+ *
+ * txnEndReq ::= SEQUENCE {
+ * ...
+ * messageID MessageID,
+ *
+ * Loop on the updateControl
+ */
+ super.transitions[EndTransactionResponseStates.CONTROLS_STATE.ordinal()][SEQUENCE.getValue()] =
+ new GrammarTransition<EndTransactionResponseContainer>(
+ EndTransactionResponseStates.CONTROLS_STATE,
+ EndTransactionResponseStates.UPDATE_CONTROL_SEQ_STATE,
+ SEQUENCE,
+ new GrammarAction<EndTransactionResponseContainer>( "Get the updateControl messageId" )
+ {
+ public void action( EndTransactionResponseContainer container )
+ {
+ // Create a new current UpdateControl
+ UpdateControls currentUpdateControls = new UpdateControls();
+
+ container.getEndTransactionResponse().setCurrentControls( currentUpdateControls );
+ }
+ } );
+ }
+
+
+ /**
+ * This class is a singleton.
+ *
+ * @return An instance on this grammar
+ */
+ public static Grammar<EndTransactionResponseContainer> getInstance()
+ {
+ return instance;
+ }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestStatesEnum.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseStates.java
similarity index 74%
copy from ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestStatesEnum.java
copy to ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseStates.java
index 9fc8b5f..7be6e9e 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestStatesEnum.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseStates.java
@@ -24,12 +24,12 @@ import org.apache.directory.api.asn1.ber.grammar.States;
/**
- * This class store the EndTransactionRequest's grammar constants. It is also used
+ * This class store the EndTransactionResponse's grammar constants. It is also used
* for debugging purposes.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
-public enum EndTransactionRequestStatesEnum implements States
+public enum EndTransactionResponseStates implements States
{
/** The END_STATE */
END_STATE,
@@ -38,13 +38,22 @@ public enum EndTransactionRequestStatesEnum implements States
START_STATE,
/** The initial SEQUENCE */
- SEQUENCE_STATE,
+ END_TRANSACTION_SEQUENCE_STATE,
- /** The commit flag */
- COMMIT_STATE,
+ /** The failed message ID */
+ FAILED_MESSAGE_ID_STATE,
- /** The identifier state */
- IDENTFIER_STATE,
+ /** The update controls SEQ */
+ UPDATE_CONTROLS_SEQ_STATE,
+
+ /** The update control SEQ */
+ UPDATE_CONTROL_SEQ_STATE,
+
+ /** THe control's message ID state */
+ CONTROL_MESSAGE_ID_STATE,
+
+ /** The control's state */
+ CONTROLS_STATE,
/** Last state */
LAST_STATE;
@@ -57,7 +66,7 @@ public enum EndTransactionRequestStatesEnum implements States
*/
public String getGrammarName()
{
- return "END_TRANSACTION_REQUEST_GRAMMER";
+ return "END_TRANSACTION_RESPONSE_GRAMMER";
}
@@ -69,7 +78,7 @@ public enum EndTransactionRequestStatesEnum implements States
*/
public String getState( int state )
{
- return ( state == END_STATE.ordinal() ) ? "END_TRANSACTION_REQUEST_GRAMMER" : name();
+ return ( state == END_STATE.ordinal() ) ? "END_TRANSACTION_RESPONSE_GRAMMER" : name();
}
@@ -87,7 +96,7 @@ public enum EndTransactionRequestStatesEnum implements States
* {@inheritDoc}
*/
@Override
- public EndTransactionRequestStatesEnum getStartState()
+ public EndTransactionResponseStates getStartState()
{
return START_STATE;
}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/ControlsContainer.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/ControlsContainer.java
new file mode 100644
index 0000000..3d9d748
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/ControlsContainer.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.api.asn1.ber.AbstractContainer;
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.codec.api.LdapApiService;
+import org.apache.directory.api.ldap.codec.osgi.DefaultLdapCodecService;
+import org.apache.directory.api.ldap.model.message.Control;
+
+/**
+ * A container storing decoded controls for a EndTransactionResponse extended operation
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ControlsContainer extends AbstractContainer
+{
+ /** The list of decoded controls */
+ private List<Control> controls = new ArrayList<>();
+
+ /** The current control */
+ private CodecControl<?> currentControl;
+
+ /** The codec service */
+ private final LdapApiService codec;
+
+ /**
+ * A constructor for this container
+ */
+ public ControlsContainer()
+ {
+ super();
+ setGrammar( ControlsGrammar.getInstance() );
+ setTransition( ControlsStates.START_STATE );
+ this.codec = new DefaultLdapCodecService();
+ }
+
+
+ /**
+ * Gets the {@link LdapApiService} associated with this Container.
+ *
+ * @return The LDAP service instance
+ */
+ public LdapApiService getLdapCodecService()
+ {
+ return codec;
+ }
+
+
+ /**
+ * @return the currentControl
+ */
+ public CodecControl<?> getCurrentControl()
+ {
+ return currentControl;
+ }
+
+
+ /**
+ * @param currentControl the currentControl to set
+ */
+ public void setCurrentControl( CodecControl<?> currentControl )
+ {
+ this.currentControl = currentControl;
+ }
+
+
+ /**
+ * @return the controls
+ */
+ public List<Control> getControls()
+ {
+ return controls;
+ }
+
+
+ /**
+ * @param control the controls to add to the list of controls
+ */
+ public void addControl( Control control )
+ {
+ controls.add( control );
+ }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/ControlsGrammar.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/ControlsGrammar.java
new file mode 100644
index 0000000..d9e3b2c
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/ControlsGrammar.java
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
+import org.apache.directory.api.asn1.ber.grammar.Grammar;
+import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
+import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.i18n.I18n;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls.actions.AddControl;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls.actions.StoreControlCriticality;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls.actions.StoreControlValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.directory.api.asn1.ber.tlv.UniversalTag.BOOLEAN;
+import static org.apache.directory.api.asn1.ber.tlv.UniversalTag.OCTET_STRING;
+import static org.apache.directory.api.asn1.ber.tlv.UniversalTag.SEQUENCE;
+
+/**
+ * A grammar to decode controls in a EndTransactionResponse extended operation
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ControlsGrammar extends AbstractGrammar<ControlsContainer>
+{
+ /** logger */
+ private static final Logger LOG = LoggerFactory.getLogger( ControlsGrammar.class );
+
+ /** Speedup for logs */
+ static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+ /** The instance of grammar. ControlsGrammar is a singleton */
+ private static Grammar<ControlsContainer> instance = new ControlsGrammar();
+
+
+ /**
+ * Creates a new ControlsGrammar object.
+ */
+ @SuppressWarnings("unchecked")
+ public ControlsGrammar()
+ {
+ setName( ControlsGrammar.class.getName() );
+
+ // Create the transitions table
+ super.transitions = new GrammarTransition[ControlsStates.LAST_STATE.ordinal()][256];
+
+ /**
+ * Transition from init state to Control Sequence
+ *
+ * Control ::= SEQUENCE {
+ * ...
+ *
+ * Creates the current control instance
+ */
+ super.transitions[ControlsStates.START_STATE.ordinal()][SEQUENCE.getValue()] =
+ new GrammarTransition<ControlsContainer>(
+ ControlsStates.START_STATE,
+ ControlsStates.CONTROL_SEQUENCE_STATE,
+ SEQUENCE,
+ new GrammarAction<ControlsContainer>( "Init Control" )
+ {
+ public void action( ControlsContainer container ) throws DecoderException
+ {
+ TLV tlv = container.getCurrentTLV();
+ int expectedLength = tlv.getLength();
+
+ // The Length should be null
+ if ( expectedLength == 0 )
+ {
+ String msg = I18n.err( I18n.ERR_04096_NULL_CONTROL_LENGTH );
+ LOG.error( msg );
+
+ // This will generate a PROTOCOL_ERROR
+ throw new DecoderException( msg );
+ }
+ }
+ } );
+
+ /**
+ * Transition from controlSequence state to control type
+ *
+ * Control ::= SEQUENCE {
+ * controlType LDAPOID,
+ * ...
+ *
+ * Creates the current control instance
+ */
+ super.transitions[ControlsStates.CONTROL_SEQUENCE_STATE.ordinal()][OCTET_STRING.getValue()] =
+ new GrammarTransition<ControlsContainer>(
+ ControlsStates.CONTROL_SEQUENCE_STATE,
+ ControlsStates.CONTROL_TYPE_STATE,
+ OCTET_STRING,
+ new AddControl() );
+
+ /**
+ * Transition from control type to control criticality
+ *
+ * Control ::= SEQUENCE {
+ * controlType LDAPOID,
+ * criticality BOOLEAN DEFAULT FALSE,
+ * ...
+ *
+ * Store the criticality
+ */
+ super.transitions[ControlsStates.CONTROL_TYPE_STATE.ordinal()][BOOLEAN.getValue()] =
+ new GrammarTransition<ControlsContainer>(
+ ControlsStates.CONTROL_TYPE_STATE,
+ ControlsStates.CONTROL_CRITICALITY_STATE,
+ BOOLEAN,
+ new StoreControlCriticality() );
+
+ /**
+ * Transition from control type to control value
+ *
+ * Control ::= SEQUENCE {
+ * controlType LDAPOID,
+ * ...
+ * controlValue OCTET STRING OPTIONAL }
+ *
+ * Store the value
+ */
+ super.transitions[ControlsStates.CONTROL_TYPE_STATE.ordinal()][OCTET_STRING.getValue()] =
+ new GrammarTransition<ControlsContainer>(
+ ControlsStates.CONTROL_TYPE_STATE,
+ ControlsStates.CONTROL_VALUE_STATE,
+ OCTET_STRING,
+ new StoreControlValue() );
+
+ /**
+ * Transition from control type to control sequence
+ *
+ * Control ::= SEQUENCE {
+ * controlType LDAPOID,
+ *
+ * Nothing to do
+ */
+ super.transitions[ControlsStates.CONTROL_TYPE_STATE.ordinal()][SEQUENCE.getValue()] =
+ new GrammarTransition<ControlsContainer>(
+ ControlsStates.CONTROL_TYPE_STATE,
+ ControlsStates.CONTROL_SEQUENCE_STATE,
+ SEQUENCE );
+
+ /**
+ * Transition from control criticality to control value
+ *
+ * Control ::= SEQUENCE {
+ * ...
+ * criticality BOOLEAN DEFAULT FALSE,
+ * controlValue OCTET STRING OPTIONAL }
+ *
+ * Store the value
+ */
+ super.transitions[ControlsStates.CONTROL_CRITICALITY_STATE.ordinal()][OCTET_STRING.getValue()] =
+ new GrammarTransition<ControlsContainer>(
+ ControlsStates.CONTROL_CRITICALITY_STATE,
+ ControlsStates.CONTROL_VALUE_STATE,
+ OCTET_STRING,
+ new StoreControlValue() );
+
+ /**
+ * Transition from control criticality to control sequence
+ *
+ * Control ::= SEQUENCE {
+ * ...
+ * criticality BOOLEAN DEFAULT FALSE,
+ *
+ * Nothing to do
+ */
+ super.transitions[ControlsStates.CONTROL_CRITICALITY_STATE.ordinal()][SEQUENCE.getValue()] =
+ new GrammarTransition<ControlsContainer>(
+ ControlsStates.CONTROL_CRITICALITY_STATE,
+ ControlsStates.CONTROL_SEQUENCE_STATE,
+ SEQUENCE );
+
+ /**
+ * Transition from control value to control sequence
+ *
+ * Control ::= SEQUENCE {
+ *
+ * Nothing to do
+ */
+ super.transitions[ControlsStates.CONTROL_VALUE_STATE.ordinal()][SEQUENCE.getValue()] =
+ new GrammarTransition<ControlsContainer>(
+ ControlsStates.CONTROL_VALUE_STATE,
+ ControlsStates.CONTROL_SEQUENCE_STATE,
+ SEQUENCE );
+ }
+
+
+ /**
+ * This class is a singleton.
+ *
+ * @return An instance on this grammar
+ */
+ public static Grammar<ControlsContainer> getInstance()
+ {
+ return instance;
+ }
+}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestStatesEnum.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/ControlsStates.java
similarity index 77%
rename from ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestStatesEnum.java
rename to ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/ControlsStates.java
index 9fc8b5f..b0d10fc 100644
--- a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionRequestStatesEnum.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/ControlsStates.java
@@ -17,19 +17,17 @@
* under the License.
*
*/
-package org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction;
-
+package org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls;
import org.apache.directory.api.asn1.ber.grammar.States;
-
/**
- * This class store the EndTransactionRequest's grammar constants. It is also used
+ * This class store the Controls' grammar constants. It is also used
* for debugging purposes.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
-public enum EndTransactionRequestStatesEnum implements States
+public enum ControlsStates implements States
{
/** The END_STATE */
END_STATE,
@@ -37,14 +35,17 @@ public enum EndTransactionRequestStatesEnum implements States
/** start state*/
START_STATE,
- /** The initial SEQUENCE */
- SEQUENCE_STATE,
+ /** The Control SEQUENCE */
+ CONTROL_SEQUENCE_STATE,
+
+ /** The Control type */
+ CONTROL_TYPE_STATE,
- /** The commit flag */
- COMMIT_STATE,
+ /** The criticality */
+ CONTROL_CRITICALITY_STATE,
- /** The identifier state */
- IDENTFIER_STATE,
+ /** The value */
+ CONTROL_VALUE_STATE,
/** Last state */
LAST_STATE;
@@ -57,7 +58,7 @@ public enum EndTransactionRequestStatesEnum implements States
*/
public String getGrammarName()
{
- return "END_TRANSACTION_REQUEST_GRAMMER";
+ return "CONTROLS_GRAMMAR";
}
@@ -69,7 +70,7 @@ public enum EndTransactionRequestStatesEnum implements States
*/
public String getState( int state )
{
- return ( state == END_STATE.ordinal() ) ? "END_TRANSACTION_REQUEST_GRAMMER" : name();
+ return ( state == END_STATE.ordinal() ) ? "CONTROLS_GRAMMER" : name();
}
@@ -87,7 +88,7 @@ public enum EndTransactionRequestStatesEnum implements States
* {@inheritDoc}
*/
@Override
- public EndTransactionRequestStatesEnum getStartState()
+ public ControlsStates getStartState()
{
return START_STATE;
}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/AddControl.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/actions/AddControl.java
similarity index 72%
copy from ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/AddControl.java
copy to ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/actions/AddControl.java
index d9f0a99..37c9451 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/AddControl.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/actions/AddControl.java
@@ -17,7 +17,7 @@
* under the License.
*
*/
-package org.apache.directory.api.ldap.codec.actions.controls;
+package org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls.actions;
import org.apache.directory.api.asn1.DecoderException;
@@ -25,10 +25,8 @@ import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
import org.apache.directory.api.asn1.ber.tlv.TLV;
import org.apache.directory.api.asn1.util.Oid;
import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
-import org.apache.directory.api.ldap.codec.api.MessageDecorator;
-import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.Message;
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls.ControlsContainer;
import org.apache.directory.api.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,7 +42,7 @@ import org.slf4j.LoggerFactory;
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
-public class AddControl extends GrammarAction<LdapMessageContainer<MessageDecorator<? extends Message>>>
+public class AddControl extends GrammarAction<ControlsContainer>
{
/** The logger */
private static final Logger LOG = LoggerFactory.getLogger( AddControl.class );
@@ -65,7 +63,7 @@ public class AddControl extends GrammarAction<LdapMessageContainer<MessageDecora
/**
* {@inheritDoc}
*/
- public void action( LdapMessageContainer<MessageDecorator<? extends Message>> container ) throws DecoderException
+ public void action( ControlsContainer container ) throws DecoderException
{
TLV tlv = container.getCurrentTLV();
@@ -73,7 +71,7 @@ public class AddControl extends GrammarAction<LdapMessageContainer<MessageDecora
// We have to handle the special case of a 0 length OID
if ( tlv.getLength() == 0 )
{
- String msg = I18n.err( I18n.ERR_04097 );
+ String msg = I18n.err( I18n.ERR_04097_NULL_CONTROL_OID );
LOG.error( msg );
// This will generate a PROTOCOL_ERROR
@@ -86,24 +84,24 @@ public class AddControl extends GrammarAction<LdapMessageContainer<MessageDecora
// The OID is encoded as a String, not an Object Id
if ( !Oid.isOid( oidValue ) )
{
- LOG.error( I18n.err( I18n.ERR_04098, Strings.dumpBytes( value ) ) );
+ String msg = I18n.err( I18n.ERR_04098_INVALID_CONTROL_OID, oidValue );
+ LOG.error( msg );
// This will generate a PROTOCOL_ERROR
- throw new DecoderException( I18n.err( I18n.ERR_04099, oidValue ) );
+ throw new DecoderException( msg );
}
- Message message = container.getMessage();
-
- Control control = container.getLdapCodecService().newControl( oidValue );
-
- message.addControl( control );
+ CodecControl<?> control = container.getLdapCodecService().newControl( oidValue );
+ container.setCurrentControl( control );
+ container.addControl( control );
+
// We can have an END transition
container.setGrammarEndAllowed( true );
if ( IS_DEBUG )
{
- LOG.debug( "Control OID : " + oidValue );
+ LOG.debug( "Control OID : {}", oidValue );
}
}
}
diff --git a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlCriticality.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/actions/StoreControlCriticality.java
similarity index 78%
copy from ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlCriticality.java
copy to ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/actions/StoreControlCriticality.java
index c221fe0..ad5fe5a 100644
--- a/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/controls/StoreControlCriticality.java
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/actions/StoreControlCriticality.java
@@ -17,7 +17,7 @@
* under the License.
*
*/
-package org.apache.directory.api.ldap.codec.actions.controls;
+package org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls.actions;
import org.apache.directory.api.asn1.DecoderException;
@@ -27,10 +27,8 @@ import org.apache.directory.api.asn1.ber.tlv.BooleanDecoder;
import org.apache.directory.api.asn1.ber.tlv.BooleanDecoderException;
import org.apache.directory.api.asn1.ber.tlv.TLV;
import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
-import org.apache.directory.api.ldap.codec.api.MessageDecorator;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls.ControlsContainer;
import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.Message;
import org.apache.directory.api.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -47,7 +45,7 @@ import org.slf4j.LoggerFactory;
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
-public class StoreControlCriticality extends GrammarAction<LdapMessageContainer<MessageDecorator<? extends Message>>>
+public class StoreControlCriticality extends GrammarAction<ControlsContainer>
{
/** The logger */
private static final Logger LOG = LoggerFactory.getLogger( StoreControlCriticality.class );
@@ -68,15 +66,12 @@ public class StoreControlCriticality extends GrammarAction<LdapMessageContainer<
/**
* {@inheritDoc}
*/
- public void action( LdapMessageContainer<MessageDecorator<? extends Message>> container ) throws DecoderException
+ public void action( ControlsContainer container ) throws DecoderException
{
TLV tlv = container.getCurrentTLV();
// Get the current control
- Control control;
-
- MessageDecorator<? extends Message> message = container.getMessage();
- control = message.getCurrentControl();
+ Control control = container.getCurrentControl();
// Store the criticality
// We get the value. If it's a 0, it's a FALSE. If it's
@@ -94,7 +89,7 @@ public class StoreControlCriticality extends GrammarAction<LdapMessageContainer<
catch ( BooleanDecoderException bde )
{
LOG.error( I18n
- .err( I18n.ERR_04100, Strings.dumpBytes( value.getData() ), bde.getMessage() ) );
+ .err( I18n.ERR_04100_BAD_CONTROL_CRITICALITY, Strings.dumpBytes( value.getData() ), bde.getMessage() ) );
// This will generate a PROTOCOL_ERROR
throw new DecoderException( bde.getMessage(), bde );
@@ -105,7 +100,7 @@ public class StoreControlCriticality extends GrammarAction<LdapMessageContainer<
if ( IS_DEBUG )
{
- LOG.debug( "Control criticality : " + control.isCritical() );
+ LOG.debug( "Control criticality : {}", control.isCritical() );
}
}
}
diff --git a/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/actions/StoreControlValue.java b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/actions/StoreControlValue.java
new file mode 100644
index 0000000..bbe35a3
--- /dev/null
+++ b/ldap/extras/codec/src/main/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/controls/actions/StoreControlValue.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls.actions;
+
+
+import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
+import org.apache.directory.api.asn1.ber.tlv.BerValue;
+import org.apache.directory.api.asn1.ber.tlv.TLV;
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls.ControlsContainer;
+import org.apache.directory.api.util.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * The action used to set the value of a control. This is an extension point
+ * where different controls can be plugged in (at least eventually). For now we
+ * hard code controls.
+ * <pre>
+ * Control ::= SEQUENCE {
+ * ...
+ * controlValue OCTET STRING OPTIONAL }
+ * </pre>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StoreControlValue extends GrammarAction<ControlsContainer>
+{
+ /** The logger */
+ private static final Logger LOG = LoggerFactory.getLogger( StoreControlValue.class );
+
+ /** Speedup for logs */
+ private static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+
+ /**
+ * Instantiates a new StoreControlValue action.
+ */
+ public StoreControlValue()
+ {
+ super( "Store the control value" );
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void action( ControlsContainer container )
+ {
+ TLV tlv = container.getCurrentTLV();
+
+ CodecControl<?> control = container.getCurrentControl();
+
+ // Get the current control
+ BerValue value = tlv.getValue();
+
+ // Store the value - have to handle the special case of a 0 length value
+ if ( tlv.getLength() == 0 )
+ {
+ control.setValue( Strings.EMPTY_BYTES );
+ }
+ else
+ {
+ control.setValue( value.getData() );
+ }
+
+ // We can have an END transition
+ container.setGrammarEndAllowed( true );
+
+ if ( IS_DEBUG )
+ {
+ LOG.debug( "Control value : {}", Strings.dumpBytes( control.getValue() ) );
+ }
+ }
+}
diff --git a/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseTest.java b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseTest.java
new file mode 100644
index 0000000..57339bc
--- /dev/null
+++ b/ldap/extras/codec/src/test/java/org/apache/directory/api/ldap/extras/extended/ads_impl/endTransaction/EndTransactionResponseTest.java
@@ -0,0 +1,262 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.directory.api.ldap.extras.extended.ads_impl.endTransaction;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.nio.ByteBuffer;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.EncoderException;
+import org.apache.directory.api.asn1.ber.Asn1Decoder;
+import org.apache.directory.api.ldap.codec.api.CodecControl;
+import org.apache.directory.api.ldap.extras.extended.endTransaction.EndTransactionResponse;
+import org.apache.directory.api.ldap.extras.extended.endTransaction.UpdateControls;
+import org.apache.directory.api.ldap.model.message.Control;
+import org.apache.directory.api.util.Strings;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * Test the EndTransactionResponse codec
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class EndTransactionResponseTest
+{
+ /**
+ * Test the decoding of a EndTransactionResponse with nothing in it
+ */
+ @Test( expected=DecoderException.class)
+ public void testDecodeEndTransactionResponseEmpty() throws DecoderException
+ {
+ Asn1Decoder decoder = new Asn1Decoder();
+ ByteBuffer bb = ByteBuffer.allocate( 0x02 );
+ bb.put( new byte[]
+ { 0x30, 0x00, // EndTransactionResponse ::= SEQUENCE {
+ } );
+
+ bb.flip();
+
+ EndTransactionResponseContainer container = new EndTransactionResponseContainer();
+
+ decoder.decode( bb, container );
+ }
+
+
+ /**
+ * Test the decoding of a EndTransactionResponse with a messageId and no updateControls
+ */
+ @Test
+ public void testEndTransactionResponseMessageId() throws DecoderException, EncoderException
+ {
+ Asn1Decoder decoder = new Asn1Decoder();
+ ByteBuffer bb = ByteBuffer.allocate( 0x05 );
+ bb.put( new byte[]
+ { 0x30, 0x03, // EndTransactionResponse ::= SEQUENCE {
+ 0x02, 0x01, 0x04 // MessageId
+ } );
+
+ String decodedPdu = Strings.dumpBytes( bb.array() );
+ bb.flip();
+ EndTransactionResponseContainer container = new EndTransactionResponseContainer();
+
+ try
+ {
+ decoder.decode( bb, container );
+ }
+ catch ( DecoderException de )
+ {
+ de.printStackTrace();
+ fail( de.getMessage() );
+ }
+
+ EndTransactionResponse endTransactionResponse = container.getEndTransactionResponse();
+ assertEquals( 4, endTransactionResponse.getFailedMessageId() );
+ assertEquals( 0, endTransactionResponse.getUpdateControls().size() );
+
+ // Check the length
+ assertEquals( 0x05, ( ( EndTransactionResponseDecorator ) endTransactionResponse ).computeLengthInternal() );
+
+ // Check the encoding
+ ByteBuffer bb1 = ( ( EndTransactionResponseDecorator ) endTransactionResponse ).encodeInternal();
+
+ String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+ assertEquals( encodedPdu, decodedPdu );
+ }
+
+
+ /**
+ * Test the decoding of a EndTransactionResponse with updateControls
+ */
+ @Test
+ public void testEndTransactionResponseUpdateControls() throws DecoderException, EncoderException
+ {
+ Asn1Decoder decoder = new Asn1Decoder();
+ ByteBuffer bb = ByteBuffer.allocate( 0xAC );
+ bb.put( new byte[]
+ { 0x30, (byte)0x81, (byte)0xA9, // EndTransactionResponse ::= SEQUENCE {
+ 0x30, (byte)0x81, (byte)0xA6, // UpdateControls
+ 0x30, 0x5F, // updateControl
+ 0x02, 0x01, 0x01, // messageID
+ 0x30, 0x5A, // controls
+ 0x30, 0x1A, // Control ::= SEQUENCE {
+ 0x04, 0x0D, // controlType LDAPOID,
+ '1', '.', '3', '.', '6', '.', '1', '.', '5', '.', '5', '.', '1',
+ 0x01, 0x01, ( byte ) 0xFF, // criticality BOOLEAN DEFAULT FALSE,
+ 0x04, 0x06, // controlValue OCTET STRING OPTIONAL }
+ 'a', 'b', 'c', 'd', 'e', 'f',
+ 0x30, 0x17, // Control ::= SEQUENCE {
+ 0x04, 0x0D, // controlType LDAPOID,
+ '1', '.', '3', '.', '6', '.', '1', '.', '5', '.', '5', '.', '2',
+ 0x04, 0x06, // controlValue OCTET STRING OPTIONAL }
+ 'g', 'h', 'i', 'j', 'k', 'l',
+ 0x30, 0x12, // Control ::= SEQUENCE {
+ 0x04, 0x0D, // controlType LDAPOID,
+ '1', '.', '3', '.', '6', '.', '1', '.', '5', '.', '5', '.', '3',
+ 0x01, 0x01, ( byte ) 0xFF, // criticality BOOLEAN DEFAULT FALSE}
+ 0x30, 0x0F, // Control ::= SEQUENCE {
+ 0x04, 0x0D, // controlType LDAPOID}
+ '1', '.', '3', '.', '6', '.', '1', '.', '5', '.', '5', '.', '4',
+ 0x30, 0x43, // updateControl
+ 0x02, 0x01, 0x02, // messageID
+ 0x30, 0x3E, // controls
+ 0x30, 0x17, // Control ::= SEQUENCE {
+ 0x04, 0x0D, // controlType LDAPOID,
+ '1', '.', '3', '.', '6', '.', '1', '.', '5', '.', '5', '.', '2',
+ 0x04, 0x06, // controlValue OCTET STRING OPTIONAL }
+ 'g', 'h', 'i', 'j', 'k', 'l',
+ 0x30, 0x12, // Control ::= SEQUENCE {
+ 0x04, 0x0D, // controlType LDAPOID,
+ '1', '.', '3', '.', '6', '.', '1', '.', '5', '.', '5', '.', '3',
+ 0x01, 0x01, ( byte ) 0xFF, // criticality BOOLEAN DEFAULT FALSE}
+ 0x30, 0x0F, // Control ::= SEQUENCE {
+ 0x04, 0x0D, // controlType LDAPOID}
+ '1', '.', '3', '.', '6', '.', '1', '.', '5', '.', '5', '.', '4'
+
+ } );
+
+ String decodedPdu = Strings.dumpBytes( bb.array() );
+ bb.flip();
+ EndTransactionResponseContainer container = new EndTransactionResponseContainer();
+
+ try
+ {
+ decoder.decode( bb, container );
+ }
+ catch ( DecoderException de )
+ {
+ de.printStackTrace();
+ fail( de.getMessage() );
+ }
+
+ EndTransactionResponse endTransactionResponse = container.getEndTransactionResponse();
+ assertEquals( -1, endTransactionResponse.getFailedMessageId() );
+ assertEquals( 2, endTransactionResponse.getUpdateControls().size() );
+
+ UpdateControls updateControls1 = endTransactionResponse.getUpdateControls().get( 0 );
+ assertEquals( 1, updateControls1.getMessageId() );
+ assertNotNull( updateControls1.getControls() );
+ assertEquals( 4, updateControls1.getControls().size() );
+
+ for ( Control control : updateControls1.getControls() )
+ {
+ switch ( control.getOid() )
+ {
+ case "1.3.6.1.5.5.1" :
+ assertTrue( control.isCritical() );
+ assertEquals( "abcdef", Strings.utf8ToString( ( ( CodecControl<?> ) control ).getValue() ) );
+ break;
+
+ case "1.3.6.1.5.5.2" :
+ assertFalse( control.isCritical() );
+ assertEquals( "ghijkl", Strings.utf8ToString( ( ( CodecControl<?> ) control ).getValue() ) );
+ break;
+
+ case "1.3.6.1.5.5.3" :
+ assertTrue( control.isCritical() );
+ assertNull( ( ( CodecControl<?> ) control ).getValue() );
+ break;
+
+ case "1.3.6.1.5.5.4" :
+ assertFalse( control.isCritical() );
+ assertNull( ( ( CodecControl<?> ) control ).getValue() );
+ break;
+
+ default :
+ fail();
+ break;
+ }
+ }
+
+ UpdateControls updateControls2 = endTransactionResponse.getUpdateControls().get( 1 );
+ assertEquals( 2, updateControls2.getMessageId() );
+ assertNotNull( updateControls2.getControls() );
+ assertEquals( 3, updateControls2.getControls().size() );
+
+ for ( Control control : updateControls2.getControls() )
+ {
+ switch ( control.getOid() )
+ {
+ case "1.3.6.1.5.5.2" :
+ assertFalse( control.isCritical() );
+ assertEquals( "ghijkl", Strings.utf8ToString( ( ( CodecControl<?> ) control ).getValue() ) );
+ break;
+
+ case "1.3.6.1.5.5.3" :
+ assertTrue( control.isCritical() );
+ assertNull( ( ( CodecControl<?> ) control ).getValue() );
+ break;
+
+ case "1.3.6.1.5.5.4" :
+ assertFalse( control.isCritical() );
+ assertNull( ( ( CodecControl<?> ) control ).getValue() );
+ break;
+
+ default :
+ fail();
+ break;
+ }
+ }
+
+ // Check the length
+ assertEquals( 0xAC, ( ( EndTransactionResponseDecorator ) endTransactionResponse ).computeLengthInternal() );
+
+ // Check the encoding
+ ByteBuffer bb1 = ( ( EndTransactionResponseDecorator ) endTransactionResponse ).encodeInternal();
+
+ String encodedPdu = Strings.dumpBytes( bb1.array() );
+
+ assertEquals( encodedPdu, decodedPdu );
+ }
+}
--
To stop receiving notification emails like this one, please contact
elecharny@apache.org.