| ProtectedPropertyReader.java |
/*
* $Id: ProtectedPropertyReader.java,v 1.25 2010/09/29 17:21:48 agoubard Exp $
*
* See the COPYRIGHT file for redistribution and use restrictions.
*/
package org.xins.common.collections;
import java.util.HashMap;
import java.util.Iterator;
import org.xins.common.MandatoryArgumentChecker;
/**
* Modifiable <code>PropertyReader</code> implementaton that can be protected
* from unauthorized changes.
*
* <p>A secret key must be passed when constructing a
* <code>ProtectedPropertyReader</code> instance. All modification methods on
* this object then require this same secret key to be passed, otherwise they
* fail with an {@link IncorrectSecretKeyException}.
*
* <p>Note that the secret key equality is always checked before the other
* preconditions. This means that if the secret key is incorrect, then the
* other preconditions will not even be checked. For example, if <code>
* {@link #set(Object,String,String) set}(null, null)</code> is called, then
* an {@link IncorrectSecretKeyException} is thrown for the mismatching secret
* key, and not an instance of the superclass
* {@link IllegalArgumentException}, for the missing <code>name</code>
* argument.
*
* @version $Revision: 1.25 $ $Date: 2010/09/29 17:21:48 $
* @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
*
* @since XINS 1.0.0
*/
public final class ProtectedPropertyReader
extends AbstractPropertyReader {
/**
* The secret key. This field is initialized by the constructor and can
* never be <code>null</code>.
*/
private final Object _secretKey;
/**
* Constructs a new <code>ProtectedPropertyReader</code>.
*
* @param secretKey
* the secret key that must be passed to the modification methods in
* order to be authorized to modify this collection.
*
* @throws IllegalArgumentException
* if <code>secretKey == null</code>.
*/
public ProtectedPropertyReader(Object secretKey)
throws IllegalArgumentException {
super(new HashMap(89));
// Check preconditions
MandatoryArgumentChecker.check("secretKey", secretKey);
_secretKey = secretKey;
}
/**
* Verifies that the specified object matches the secret key. If not, an
* exception is thrown.
*
* @param secretKey
* the secret key, must be identity-equal to the secret key passed to
* the constructor, cannot be <code>null</code>.
*
* @throws IncorrectSecretKeyException
* if <code>secretKey</code> does not match the secret key passed to the
* constructor.
*/
private void checkSecretKey(Object secretKey)
throws IncorrectSecretKeyException {
if (secretKey != _secretKey) {
throw new IncorrectSecretKeyException();
}
}
/**
* Sets the specified property to the specified value.
*
* <p>The correct secret key must be passed. If it is incorrect, then an
* {@link IncorrectSecretKeyException} is thrown. Note that an identity
* check is done, <em>not</em> an equality check. So
* the {@link Object#equals(Object)} method is not used, but the
* <code>==</code> operator is.
*
* <p>If <code>value == null</code>, then the property is removed (assuming
* that the secret key is correct).
*
* @param secretKey
* the secret key, must be identity-equal to the secret key passed to
* the constructor, cannot be <code>null</code>.
*
* @param name
* the name of the property to set or reset, cannot be
* <code>null</code>.
*
* @param value
* the value for the property, can be <code>null</code>.
*
* @throws IncorrectSecretKeyException
* if <code>secretKey</code> does not match the secret key passed to the
* constructor.
*
* @throws IllegalArgumentException
* if <code>name == null</code>.
*/
public void set(Object secretKey, String name, String value)
throws IncorrectSecretKeyException, IllegalArgumentException {
// Check preconditions
checkSecretKey(secretKey);
MandatoryArgumentChecker.check("name", name);
// Remove the current value
if (value == null) {
getPropertiesMap().remove(name);
// Store a new value
} else {
getPropertiesMap().put(name, value);
}
}
/**
* Removes the specified property. If the property is not found, then
* nothing happens.
*
* <p>The correct secret key must be passed. If it is incorrect, then an
* {@link IncorrectSecretKeyException} is thrown. Note that an identity
* check is done, <em>not</em> an equality check. So
* the {@link Object#equals(Object)} method is not used, but the
* <code>==</code> operator is.
*
* @param secretKey
* the secret key, must be identity-equal to the secret key passed to
* the constructor, cannot be <code>null</code>.
*
* @param name
* the name of the property to remove, cannot be <code>null</code>.
*
* @throws IncorrectSecretKeyException
* if <code>secretKey</code> does not match the secret key passed to the
* constructor.
*
* @throws IllegalArgumentException
* if <code>name == null</code>.
*/
public void remove(Object secretKey, String name)
throws IncorrectSecretKeyException, IllegalArgumentException {
// Check preconditions
checkSecretKey(secretKey);
MandatoryArgumentChecker.check("name", name);
// Remove the property
getPropertiesMap().remove(name);
}
/**
* Removes all properties.
*
* <p>The correct secret key must be passed. If it is incorrect, then an
* {@link IncorrectSecretKeyException} is thrown. Note that an identity
* check is done, <em>not</em> an equality check. So
* the {@link Object#equals(Object)} method is not used, but the
* <code>==</code> operator is.
*
* @param secretKey
* the secret key, must be identity-equal to the secret key passed to
* the constructor, cannot be <code>null</code>.
*
* @throws IncorrectSecretKeyException
* if <code>secretKey</code> does not match the secret key passed to the
* constructor.
*
* @since XINS 1.2.0
*/
public void clear(Object secretKey)
throws IncorrectSecretKeyException {
checkSecretKey(secretKey);
getPropertiesMap().clear();
}
/**
* Copies all entries from the specified property reader into this one.
*
* <p>The correct secret key must be passed. If it is incorrect, then an
* {@link IncorrectSecretKeyException} is thrown. Note that an identity
* check is done, <em>not</em> an equality check. So
* the {@link Object#equals(Object)} method is not used, but the
* <code>==</code> operator is.
*
* @param secretKey
* the secret key, must be identity-equal to the secret key passed to
* the constructor, cannot be <code>null</code>.
*
* @param source
* the {@link PropertyReader} containing the key/value pairs to copy to
* this object, cannot be <code>null</code>.
*
* @throws IncorrectSecretKeyException
* if <code>secretKey</code> does not match the secret key passed to the
* constructor.
*
* @throws IllegalArgumentException
* if <code>source == null || source == this</code> or if the specified
* {@link PropertyReader} contains an entry which has the name equal to
* <code>null</code>.
*
* @since XINS 1.2.0
*/
public void copyFrom(Object secretKey, PropertyReader source)
throws IncorrectSecretKeyException, IllegalArgumentException {
// Check preconditions
checkSecretKey(secretKey);
MandatoryArgumentChecker.check("source", source);
if (source == this) {
throw new IllegalArgumentException("source == this");
}
// Copy all entries
Iterator names = source.getNames();
while (names.hasNext()) {
String name = (String) names.next();
set(secretKey, name, source.get(name));
}
}
}