Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
dd82a9c
added javadoc
ic0ns Mar 6, 2025
1eec26f
Fixed JavaDoc errors and added missing comments
ic0ns Mar 6, 2025
57f1d93
fixed javadoc warnings and formatted
ic0ns Mar 6, 2025
df6921f
fixed default constructors
ic0ns Mar 10, 2025
424bdd5
added null checks
ic0ns Mar 10, 2025
233b15a
made documentation more consistent
ic0ns Mar 10, 2025
3fb0270
shortened
ic0ns Mar 10, 2025
42f3827
formatted
ic0ns Mar 10, 2025
230a8cf
fixed javadoc
ic0ns Mar 10, 2025
5884f37
reviewed big integer documentation
ic0ns Mar 10, 2025
699aebc
reviewed modifiableBoolean documentation
ic0ns Mar 10, 2025
7dd295a
better syntax
ic0ns Mar 10, 2025
56f06f6
formatted
ic0ns Mar 10, 2025
30d315b
fixed javadoku and made byte array shuffle use an array of ints inste…
ic0ns Mar 10, 2025
549507f
reviewed documentation
ic0ns Mar 12, 2025
d709b96
formatted javadoc
ic0ns Mar 17, 2025
8cb757d
fixed documentation
ic0ns Mar 17, 2025
750d33e
fixed docu
ic0ns Mar 17, 2025
7a12b70
adjusted documentation for modifiable longs
ic0ns Mar 17, 2025
9f3708b
adjusted java doc for modifiable bytes
ic0ns Mar 17, 2025
78d53db
adjusted behavior in modifications regarding null values
ic0ns Mar 17, 2025
1a1726c
used unboxed values
ic0ns Mar 17, 2025
312bab6
used unboxed values
ic0ns Mar 17, 2025
b899f9a
Fixed Javadoc
ic0ns Mar 17, 2025
d304a75
adjusted to new api
ic0ns Mar 17, 2025
934bf51
adjusted javadoc
ic0ns Mar 17, 2025
f2f5718
formatted
ic0ns Mar 17, 2025
fc35fe7
Removed FileConfigurationException
ic0ns Mar 17, 2025
ccb9c63
documented utility functions
ic0ns Mar 17, 2025
50dd4df
finihsed remaining documentation
ic0ns Mar 17, 2025
d4c59db
formatted
ic0ns Mar 17, 2025
f9c94b4
removed test for deleted code
ic0ns Mar 17, 2025
9ffce14
adjusted tests to api changes
ic0ns Mar 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,24 @@
import java.lang.annotation.Target;

/**
* Annotation interface for modifiable variables holders. A modifiable variable holder is for
* example a TLS protocol message.
* Annotation for fields that contain ModifiableVariable instances or ModifiableVariableHolder
* objects.
*
* <p>This annotation marks fields within a class that reference modifiable variables or objects
* that contain modifiable variables. It is used for reflection-based discovery and manipulation of
* modifiable variables throughout a complex object hierarchy.
*
* <p>By marking fields with this annotation, the framework can identify which fields should be
* included in operations like:
*
* <ul>
* <li>Variable discovery
* <li>Recursive manipulation
* <li>Assertion validation
* <li>Serialization/deserialization
* </ul>
*
* <p>This annotation is retained at runtime and can only be applied to fields.
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
Expand Down
107 changes: 98 additions & 9 deletions src/main/java/de/rub/nds/modifiablevariable/ModifiableVariable.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,46 @@
import java.util.stream.Collectors;

/**
* The base abstract class for modifiable variables, including the getValue function. The class
* needs to be defined transient to allow propOrder definition in subclasses, see: <a
* href="http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html">docs</a>
* The base abstract class for modifiable variables that provides runtime value modification
* capabilities. ModifiableVariable serves as the foundation for all modifiable types in the
* library.
*
* @param <E>
* <p>This class implements the concept of runtime value modifications, where variables can be
* modified through a chain of {@link VariableModification} operations before being accessed. Each
* subclass represents a specific data type that can be modified at runtime.
*
* <p>The class is defined as transient to allow proper XML serialization with propOrder definition
* in subclasses. See: <a
* href="http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html">Ignoring
* Inheritance with XmlTransient</a> for details.
*
* @param <E> The type of value this modifiable variable holds (e.g., Integer, String, byte[])
*/
@XmlTransient
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class ModifiableVariable<E> implements Serializable {

/** The list of modifications that will be applied to the original value when accessed */
@XmlElementWrapper
@XmlAnyElement(lax = true)
private LinkedList<VariableModification<E>> modifications;

/** The expected value for assertion validation */
protected E assertEquals;

/** Default constructor that creates an empty modifiable variable. */
protected ModifiableVariable() {
super();
}

/**
* Copy constructor that creates a new modifiable variable with the same modifications and
* assertions.
*
* <p>Note: Subclasses must ensure proper copying of the respecitve assertEquals field.
*
* @param other The modifiable variable to copy
*/
protected ModifiableVariable(ModifiableVariable<E> other) {
super();
if (other.modifications != null) {
Expand All @@ -46,23 +66,39 @@ protected ModifiableVariable(ModifiableVariable<E> other) {
assertEquals = other.assertEquals;
}

/** Sets multiple modifications, all previously set modifications are removed */
/**
* Sets multiple modifications, replacing any previously set modifications.
*
* @param modifications The list of modifications to apply in sequence
*/
public void setModifications(List<VariableModification<E>> modifications) {
this.modifications = new LinkedList<>(modifications);
}

/** Sets multiple modifications, all previously set modifications are removed */
/**
* Sets multiple modifications, replacing any previously set modifications.
*
* @param modifications The variable arguments list of modifications to apply in sequence
*/
@SafeVarargs
public final void setModifications(VariableModification<E>... modifications) {
this.modifications = new LinkedList<>(List.of(modifications));
}

/** Removes all modifications */
/**
* Removes all modifications from this variable. After calling this method, getValue() will
* return the original value.
*/
public void clearModifications() {
modifications = null;
}

/** Adds a modification to this modifiable variable */
/**
* Adds a modification to the end of this variable's modification chain. The modification will
* be applied after all previously added modifications.
*
* @param modification The modification to add
*/
public void addModification(VariableModification<E> modification) {
if (modification != null) {
if (modifications == null) {
Expand All @@ -72,15 +108,31 @@ public void addModification(VariableModification<E> modification) {
}
}

/** Returns all modifications that are set for this modifiable variable */
/**
* Returns all modifications that are set for this modifiable variable.
*
* @return The list of modifications or null if no modifications are set
*/
public LinkedList<VariableModification<E>> getModifications() {
return modifications;
}

/**
* Returns the modified value of this variable. The original value will be modified by applying
* all registered modifications in sequence.
*
* @return The modified value after applying all modifications
*/
public E getValue() {
return getModifiedValue();
}

/**
* Internal implementation method to compute the modified value. Applies all registered
* modifications to the original value in sequence.
*
* @return The value after applying all modifications
*/
private E getModifiedValue() {
E resultValue = getOriginalValue();
if (modifications != null) {
Expand All @@ -91,20 +143,57 @@ private E getModifiedValue() {
return resultValue;
}

/**
* Returns the original, unmodified value of this variable.
*
* @return The original value
*/
public abstract E getOriginalValue();

/**
* Sets the original value of this variable.
*
* @param originalValue The new original value
*/
public abstract void setOriginalValue(E originalValue);

/**
* Creates a deep copy of this modifiable variable.
*
* @return A new instance with the same original value, modifications, and assertion values
*/
public abstract ModifiableVariable<E> createCopy();

/**
* Checks if the modified value differs from the original value.
*
* @return true if the modified value is different from the original, false otherwise
* @throws IllegalStateException If the original value is not set
*/
public abstract boolean isOriginalValueModified();

/**
* Validates whether the modified value matches the expected value (if set).
*
* @return true if no assertions are set or if all assertions pass, false otherwise
*/
public abstract boolean validateAssertions();

/**
* Checks if this variable has an assertion value set.
*
* @return true if an assertEquals value is set, false otherwise
*/
public boolean containsAssertion() {
return assertEquals != null;
}

/**
* Helper method for toString() implementations in subclasses. Provides a string representation
* of modifications and assertions.
*
* @return A string containing the modifications and assertions
*/
protected String innerToString() {
StringBuilder result = new StringBuilder();
if (modifications != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,21 @@
import de.rub.nds.modifiablevariable.string.ModifiableString;
import java.math.BigInteger;

/**
* Factory class for creating modifiable variables of different types.
*
* <p>This factory provides methods to safely set values on existing or new modifiable variables.
* The factory ensures that null modifiable variables are properly initialized when setting values.
*/
public final class ModifiableVariableFactory {

public static ModifiableBigInteger createBigIntegerModifiableVariable() {
return new ModifiableBigInteger();
}

public static ModifiableInteger createIntegerModifiableVariable() {
return new ModifiableInteger();
}

public static ModifiableByte createByteModifiableVariable() {
return new ModifiableByte();
}

public static ModifiableByteArray createByteArrayModifiableVariable() {
return new ModifiableByteArray();
}

public static ModifiableLong createLongModifiableVariable() {
return new ModifiableLong();
}

public static ModifiableBoolean createBooleanModifiableVariable() {
return new ModifiableBoolean();
}

public static ModifiableString createStringModifiableVariable() {
return new ModifiableString();
}

/**
* Safely sets a value on a ModifiableBigInteger, creating a new instance if necessary.
*
* @param mv The ModifiableBigInteger to set the value on, or null to create a new one
* @param value The BigInteger value to set
* @return The ModifiableBigInteger with the value set
*/
public static ModifiableBigInteger safelySetValue(ModifiableBigInteger mv, BigInteger value) {
if (mv == null) {
return new ModifiableBigInteger(value);
Expand All @@ -54,6 +39,13 @@ public static ModifiableBigInteger safelySetValue(ModifiableBigInteger mv, BigIn
return mv;
}

/**
* Safely sets a value on a ModifiableString, creating a new instance if necessary.
*
* @param mv The ModifiableString to set the value on, or null to create a new one
* @param value The String value to set
* @return The ModifiableString with the value set
*/
public static ModifiableString safelySetValue(ModifiableString mv, String value) {
if (mv == null) {
return new ModifiableString(value);
Expand All @@ -62,6 +54,13 @@ public static ModifiableString safelySetValue(ModifiableString mv, String value)
return mv;
}

/**
* Safely sets a value on a ModifiableInteger, creating a new instance if necessary.
*
* @param mv The ModifiableInteger to set the value on, or null to create a new one
* @param value The Integer value to set
* @return The ModifiableInteger with the value set
*/
public static ModifiableInteger safelySetValue(ModifiableInteger mv, Integer value) {
if (mv == null) {
return new ModifiableInteger(value);
Expand All @@ -70,6 +69,13 @@ public static ModifiableInteger safelySetValue(ModifiableInteger mv, Integer val
return mv;
}

/**
* Safely sets a value on a ModifiableByte, creating a new instance if necessary.
*
* @param mv The ModifiableByte to set the value on, or null to create a new one
* @param value The Byte value to set
* @return The ModifiableByte with the value set
*/
public static ModifiableByte safelySetValue(ModifiableByte mv, Byte value) {
if (mv == null) {
return new ModifiableByte(value);
Expand All @@ -78,6 +84,13 @@ public static ModifiableByte safelySetValue(ModifiableByte mv, Byte value) {
return mv;
}

/**
* Safely sets a value on a ModifiableByteArray, creating a new instance if necessary.
*
* @param mv The ModifiableByteArray to set the value on, or null to create a new one
* @param value The byte array value to set
* @return The ModifiableByteArray with the value set
*/
public static ModifiableByteArray safelySetValue(ModifiableByteArray mv, byte[] value) {
if (mv == null) {
return new ModifiableByteArray(value);
Expand All @@ -86,6 +99,13 @@ public static ModifiableByteArray safelySetValue(ModifiableByteArray mv, byte[]
return mv;
}

/**
* Safely sets a value on a ModifiableLong, creating a new instance if necessary.
*
* @param mv The ModifiableLong to set the value on, or null to create a new one
* @param value The Long value to set
* @return The ModifiableLong with the value set
*/
public static ModifiableLong safelySetValue(ModifiableLong mv, Long value) {
if (mv == null) {
return new ModifiableLong(value);
Expand All @@ -94,6 +114,13 @@ public static ModifiableLong safelySetValue(ModifiableLong mv, Long value) {
return mv;
}

/**
* Safely sets a value on a ModifiableBoolean, creating a new instance if necessary.
*
* @param mv The ModifiableBoolean to set the value on, or null to create a new one
* @param value The Boolean value to set
* @return The ModifiableBoolean with the value set
*/
public static ModifiableBoolean safelySetValue(ModifiableBoolean mv, Boolean value) {
if (mv == null) {
return new ModifiableBoolean(value);
Expand All @@ -102,6 +129,7 @@ public static ModifiableBoolean safelySetValue(ModifiableBoolean mv, Boolean val
return mv;
}

/** Private constructor to prevent instantiation of utility class. */
private ModifiableVariableFactory() {
super();
}
Expand Down
Loading