/**
* TLS-Attacker - A Modular Penetration Testing Framework for TLS
*
* Copyright 2014-2016 Ruhr University Bochum / Hackmanit GmbH
*
* Licensed under Apache License 2.0
* http://www.apache.org/licenses/LICENSE-2.0
*/
package de.rub.nds.tlsattacker.modifiablevariable.util;
import de.rub.nds.tlsattacker.modifiablevariable.ModifiableVariable;
import de.rub.nds.tlsattacker.modifiablevariable.HoldsModifiableVariable;
import de.rub.nds.tlsattacker.util.RandomHelper;
import de.rub.nds.tlsattacker.util.ReflectionHelper;
import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
*
* @author Juraj Somorovsky - juraj.somorovsky@rub.de
*/
public class ModifiableVariableAnalyzer {
private static final Logger LOGGER = LogManager.getLogger(ModifiableVariableAnalyzer.class);
/**
* Lists all the modifiable variables declared in the given class
*
* @param object
* @return
*/
public static List<Field> getAllModifiableVariableFields(Object object) {
return ReflectionHelper.getFieldsUpTo(object.getClass(), null, ModifiableVariable.class);
}
/**
* Returns a random field representing a modifiable variable in the given
* class
*
* @param object
* @return
*/
public static Field getRandomModifiableVariableField(Object object) {
List<Field> fields = getAllModifiableVariableFields(object);
int randomField = RandomHelper.getRandom().nextInt(fields.size());
return fields.get(randomField);
}
/**
* Returns true if the given object contains a modifiable variable
*
* @param object
* @return
*/
public static boolean isModifiableVariableHolder(Object object) {
List<Field> fields = getAllModifiableVariableFields(object);
return !fields.isEmpty();
}
/**
* Returns a list of all ModifiableVariableFields (object-field
* representations) for a given object.
*
* @param object
* @return
*/
public static List<ModifiableVariableField> getAllModifiableVariableFieldsRecursively(Object object) {
List<ModifiableVariableListHolder> holders = getAllModifiableVariableHoldersRecursively(object);
List<ModifiableVariableField> fields = new LinkedList<>();
for (ModifiableVariableListHolder holder : holders) {
for (Field f : holder.getFields()) {
fields.add(new ModifiableVariableField(holder.getObject(), f));
}
}
return fields;
}
/**
* Returns a list of all the modifiable variable holders in the object,
* including this instance.
*
* @param object
* @return
*/
public static List<ModifiableVariableListHolder> getAllModifiableVariableHoldersRecursively(Object object) {
List<ModifiableVariableListHolder> holders = new LinkedList<>();
List<Field> modFields = getAllModifiableVariableFields(object);
if (!modFields.isEmpty()) {
holders.add(new ModifiableVariableListHolder(object, modFields));
}
List<Field> allFields = ReflectionHelper.getFieldsUpTo(object.getClass(), null, null);
for (Field f : allFields) {
try {
HoldsModifiableVariable holdsVariable = f.getAnnotation(HoldsModifiableVariable.class);
f.setAccessible(true);
Object possibleHolder = f.get(object);
if (possibleHolder != null && holdsVariable != null) {
if (possibleHolder instanceof List) {
holders.addAll(getAllModifiableVariableHoldersFromList((List) possibleHolder));
} else if (possibleHolder.getClass().isArray()) {
holders.addAll(getAllModifiableVariableHoldersFromArray((Object[]) possibleHolder));
} else {
holders.addAll(getAllModifiableVariableHoldersRecursively(possibleHolder));
}
}
} catch (IllegalAccessException | IllegalArgumentException ex) {
LOGGER.info("Accessing field {} of type {} not possible: {}", f.getName(), f.getType(), ex.toString());
}
}
return holders;
}
/**
* @param list
* @return
*/
public static List<ModifiableVariableListHolder> getAllModifiableVariableHoldersFromList(List<Object> list) {
List<ModifiableVariableListHolder> result = new LinkedList<>();
for (Object o : list) {
result.addAll(getAllModifiableVariableHoldersRecursively(o));
}
return result;
}
/**
* @param array
* @return
*/
public static List<ModifiableVariableListHolder> getAllModifiableVariableHoldersFromArray(Object[] array) {
List<ModifiableVariableListHolder> result = new LinkedList<>();
for (Object o : array) {
result.addAll(getAllModifiableVariableHoldersRecursively(o));
}
return result;
}
// /**
// * Returns a random modifiable variable holder
// *
// * @return
// */
// public ModifiableVariableListHolder getRandomModifiableVariableHolder() {
// List<ModifiableVariableHolder> holders =
// getAllModifiableVariableHolders();
// int randomHolder = RandomHelper.getRandom().nextInt(holders.size());
// return holders.get(randomHolder);
// }
}