package eu.medsea.mimeutil.detector; import java.util.HashMap; import java.util.Map; /** * Quote from <a href="http://linux.die.net/man/5/magic">http://linux.die.net/man/5/magic</a>: * <p> * Numeric values may be preceded by a character indicating the operation to be performed. * It may be =, to specify that the value from the file must equal the specified value, <, * to specify that the value from the file must be less than the specified value, >, to * specify that the value from the file must be greater than the specified value, &, to * specify that the value from the file must have set all of the bits that are set in the * specified value, ^, to specify that the value from the file must have clear any of the * bits that are set in the specified value, or ~, the value specified after is negated before * tested. x, to specify that any value will match. If the character is omitted, it is assumed * to be =. For all tests except string and regex, operation ! specifies that the line matches * if the test does not succeed. * </p> * <p> * For string values, the byte string from the file must match the specified byte string. The * operators =, < and > (but not &) can be applied to strings. The length used for * matching is that of the string argument in the magic file. This means that a line can match any * string, and then presumably print that string, by doing >\0 (because all strings are greater * than the null string). * </p> * * @author marco schulze - marco at nightlabs dot de */ final class MagicMimeEntryOperation { private static final Map operationID2operation = new HashMap(); public static final MagicMimeEntryOperation EQUALS = new MagicMimeEntryOperation('='); public static final MagicMimeEntryOperation LESS_THAN = new MagicMimeEntryOperation('<'); public static final MagicMimeEntryOperation GREATER_THAN = new MagicMimeEntryOperation('>'); public static final MagicMimeEntryOperation AND = new MagicMimeEntryOperation('&'); public static final MagicMimeEntryOperation CLEAR = new MagicMimeEntryOperation('^'); public static final MagicMimeEntryOperation NEGATED = new MagicMimeEntryOperation('~'); public static final MagicMimeEntryOperation ANY = new MagicMimeEntryOperation('x'); public static final MagicMimeEntryOperation NOT_EQUALS = new MagicMimeEntryOperation('!'); public static MagicMimeEntryOperation getOperation(char operationID) { Character operationIDCharacter = new Character(operationID); return (MagicMimeEntryOperation) operationID2operation.get(operationIDCharacter); } public static MagicMimeEntryOperation getOperationForStringField(String content) { MagicMimeEntryOperation operation = getOperation(content); // String and regex do only support a subset of the operations => filter. if (EQUALS.equals(operation) || LESS_THAN.equals(operation) || GREATER_THAN.equals(operation)) return operation; else return EQUALS; } public static MagicMimeEntryOperation getOperationForNumberField(String content) { return getOperation(content); } private static MagicMimeEntryOperation getOperation(String content) { if (content.length() == 0) return EQUALS; MagicMimeEntryOperation operation = getOperation(content.charAt(0)); if (operation == null) return EQUALS; else return operation; } private static void registerOperation(MagicMimeEntryOperation operation) { Character operationIDCharacter = new Character(operation.getOperationID()); if (operationID2operation.containsKey(operationIDCharacter)) throw new IllegalStateException("Duplicate registration of operation " + operationIDCharacter); operationID2operation.put(operationIDCharacter, operation); } private final char operationID; MagicMimeEntryOperation(char operationID) { this.operationID = operationID; registerOperation(this); } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + operationID; return result; } public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; MagicMimeEntryOperation other = (MagicMimeEntryOperation) obj; return this.operationID == other.operationID; } public final char getOperationID() { return operationID; } public String toString() { return this.getClass().getName() + '[' + operationID + ']'; } }