blob: 35d4f1b478bac07ea505a4809bceef1536b9e273 [file] [log] [blame]
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed 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.axis.utils ;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Set;
import java.util.HashSet;
// fixme: Is there a reason to use Hashtable rather than Map here?
/**
* This subclass of the java Hashtable allows individual
* entries to be "locked" so that their values cannot be
* overwritten or removed.
*
* Note, only the put() and remove() methods have been
* overridden. The clear() method still removes all
* entries whether they've been locked or not.
*
* @author James Snell (jasnell@us.ibm.com)
*/
public class LockableHashtable extends Hashtable {
// fixme - we are potentialy synchronizing on /both/ the current Hashtable
// and also the Vector - a non-synchronizing List impl such as ArrayList
// may give better performance. We are doing lots of .contains on this
// Vector - it would probably be better to use a Set impl
/**
* Stores the keys of the locked entries
*/
Vector lockedEntries;
/** Place to look for properties which we don't find locally. */
private Hashtable parent = null;
public LockableHashtable() {
super();
}
public LockableHashtable(int p1, float p2) {
super(p1, p2);
}
public LockableHashtable(java.util.Map p1) {
super(p1);
}
public LockableHashtable(int p1) {
super(p1);
}
/**
* Set the parent Hashtable for this object
*/
public synchronized void setParent(Hashtable parent)
{
this.parent = parent;
}
/**
* Gets the parent Hashtable for this object (if any)
*/
public synchronized Hashtable getParent() {
return parent;
}
/**
* Returns the keys in this hashtable, and its parent chain
*/
public Set getAllKeys() {
HashSet set = new HashSet();
set.addAll(super.keySet());
Hashtable p = parent;
while (p != null) {
set.addAll(p.keySet());
if (p instanceof LockableHashtable) {
p = ((LockableHashtable) p).getParent();
} else {
p = null;
}
}
return set;
}
/**
* Get an entry from this hashtable, and if we don't find anything,
* defer to our parent, if any.
*/
public synchronized Object get(Object key) {
Object ret = super.get(key);
if ((ret == null) && (parent != null)) {
ret = parent.get(key);
}
return ret;
}
/**
* New version of the put() method that allows for explicitly marking
* items added to the hashtable as locked.
*/
public synchronized Object put(Object p1, Object p2, boolean locked) {
if (lockedEntries != null &&
this.containsKey(p1) &&
lockedEntries.contains(p1)) {
return null;
}
if (locked) {
if (lockedEntries == null) {
lockedEntries = new Vector();
}
lockedEntries.add(p1);
}
return super.put(p1, p2);
}
/**
* Overrides the Hashtable.put() method to mark items as not being locked.
*/
public synchronized Object put(Object p1, Object p2) {
return put(p1, p2, false);
}
/**
* Checks to see if an item is locked before it is removed.
*/
public synchronized Object remove(Object p1) {
if (lockedEntries != null && lockedEntries.contains(p1)) {
return null;
}
return super.remove(p1);
}
/**
* Returns true if a given key is in our locked list
*/
public boolean isKeyLocked(Object key)
{
return lockedEntries != null && lockedEntries.contains(key);
}
}