You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by de...@apache.org on 2018/05/08 12:49:07 UTC

[myfaces] 08/29: MYFACES-2840 Use a copied Iterator instead of the real Enumeration in AbstractAttributeMap.AbstractAttributeIterator

This is an automated email from the ASF dual-hosted git repository.

deki pushed a commit to branch 1.1.x
in repository https://gitbox.apache.org/repos/asf/myfaces.git

commit dd3c9f457b966b27fd743b605dd51cfccab2b33a
Author: Leonardo Uribe <lu...@apache.org>
AuthorDate: Thu Sep 23 23:02:43 2010 +0000

    MYFACES-2840 Use a copied Iterator instead of the real Enumeration in AbstractAttributeMap.AbstractAttributeIterator
---
 .../myfaces/context/portlet/ApplicationMap.java    |   5 +-
 .../myfaces/context/portlet/InitParameterMap.java  |   3 +-
 .../myfaces/context/portlet/RequestHeaderMap.java  |   4 +-
 .../context/portlet/RequestHeaderValuesMap.java    |   3 +-
 .../apache/myfaces/context/portlet/RequestMap.java |   4 +-
 .../context/portlet/RequestParameterMap.java       |   3 +-
 .../context/portlet/RequestParameterValuesMap.java |   4 +-
 .../apache/myfaces/context/portlet/SessionMap.java |   9 +-
 .../myfaces/context/servlet/ApplicationMap.java    |   4 +-
 .../apache/myfaces/context/servlet/CookieMap.java  |   2 +
 .../myfaces/context/servlet/InitParameterMap.java  |   2 +
 .../myfaces/context/servlet/RequestHeaderMap.java  |   2 +
 .../context/servlet/RequestHeaderValuesMap.java    |   2 +
 .../apache/myfaces/context/servlet/RequestMap.java |   2 +
 .../context/servlet/RequestParameterMap.java       |   2 +
 .../context/servlet/RequestParameterValuesMap.java |   2 +
 .../apache/myfaces/context/servlet/SessionMap.java |  10 +-
 .../servlet => util}/AbstractAttributeMap.java     | 713 ++++++++++----------
 .../AbstractThreadSafeAttributeMap.java}           | 723 ++++++++++-----------
 19 files changed, 758 insertions(+), 741 deletions(-)

diff --git a/impl/src/main/java/org/apache/myfaces/context/portlet/ApplicationMap.java b/impl/src/main/java/org/apache/myfaces/context/portlet/ApplicationMap.java
index 04acb63..db933fa 100644
--- a/impl/src/main/java/org/apache/myfaces/context/portlet/ApplicationMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/portlet/ApplicationMap.java
@@ -20,9 +20,10 @@ package org.apache.myfaces.context.portlet;
 
 import java.util.Enumeration;
 import java.util.Map;
+
 import javax.portlet.PortletContext;
 
-import org.apache.myfaces.context.servlet.AbstractAttributeMap;
+import org.apache.myfaces.util.AbstractThreadSafeAttributeMap;
 
 
 /**
@@ -31,7 +32,7 @@ import org.apache.myfaces.context.servlet.AbstractAttributeMap;
  * @author  Stan Silvert (latest modification by $Author$)
  * @version $Revision$ $Date$
  */
-public class ApplicationMap extends AbstractAttributeMap
+public class ApplicationMap extends AbstractThreadSafeAttributeMap
 {
     final PortletContext _portletContext;
 
diff --git a/impl/src/main/java/org/apache/myfaces/context/portlet/InitParameterMap.java b/impl/src/main/java/org/apache/myfaces/context/portlet/InitParameterMap.java
index 26becaa..d68a894 100644
--- a/impl/src/main/java/org/apache/myfaces/context/portlet/InitParameterMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/portlet/InitParameterMap.java
@@ -24,7 +24,8 @@ import java.util.Enumeration;
 import java.util.Map;
 
 import javax.portlet.PortletContext;
-import org.apache.myfaces.context.servlet.AbstractAttributeMap;
+
+import org.apache.myfaces.util.AbstractAttributeMap;
 
 
 /**
diff --git a/impl/src/main/java/org/apache/myfaces/context/portlet/RequestHeaderMap.java b/impl/src/main/java/org/apache/myfaces/context/portlet/RequestHeaderMap.java
index f6f52c9..3350f7c 100644
--- a/impl/src/main/java/org/apache/myfaces/context/portlet/RequestHeaderMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/portlet/RequestHeaderMap.java
@@ -20,8 +20,10 @@ package org.apache.myfaces.context.portlet;
 
 import java.util.Enumeration;
 import java.util.Map;
+
 import javax.portlet.PortletRequest;
-import org.apache.myfaces.context.servlet.AbstractAttributeMap;
+
+import org.apache.myfaces.util.AbstractAttributeMap;
 
 
 
diff --git a/impl/src/main/java/org/apache/myfaces/context/portlet/RequestHeaderValuesMap.java b/impl/src/main/java/org/apache/myfaces/context/portlet/RequestHeaderValuesMap.java
index d6fd597..43309ae 100644
--- a/impl/src/main/java/org/apache/myfaces/context/portlet/RequestHeaderValuesMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/portlet/RequestHeaderValuesMap.java
@@ -23,9 +23,10 @@ import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+
 import javax.portlet.PortletRequest;
 
-import org.apache.myfaces.context.servlet.AbstractAttributeMap;
+import org.apache.myfaces.util.AbstractAttributeMap;
 
 /**
  * PortletRequest header values (multi-value headers) as Map of String[].
diff --git a/impl/src/main/java/org/apache/myfaces/context/portlet/RequestMap.java b/impl/src/main/java/org/apache/myfaces/context/portlet/RequestMap.java
index 31e3769..b1a1a37 100644
--- a/impl/src/main/java/org/apache/myfaces/context/portlet/RequestMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/portlet/RequestMap.java
@@ -20,8 +20,10 @@ package org.apache.myfaces.context.portlet;
 
 import java.util.Enumeration;
 import java.util.Map;
+
 import javax.portlet.PortletRequest;
-import org.apache.myfaces.context.servlet.AbstractAttributeMap;
+
+import org.apache.myfaces.util.AbstractAttributeMap;
 
 
 /**
diff --git a/impl/src/main/java/org/apache/myfaces/context/portlet/RequestParameterMap.java b/impl/src/main/java/org/apache/myfaces/context/portlet/RequestParameterMap.java
index 5f859bf..96c90a6 100644
--- a/impl/src/main/java/org/apache/myfaces/context/portlet/RequestParameterMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/portlet/RequestParameterMap.java
@@ -19,9 +19,10 @@
 package org.apache.myfaces.context.portlet;
 
 import java.util.Enumeration;
+
 import javax.portlet.PortletRequest;
 
-import org.apache.myfaces.context.servlet.AbstractAttributeMap;
+import org.apache.myfaces.util.AbstractAttributeMap;
 
 /**
  * PortletRequest parameters as Map.
diff --git a/impl/src/main/java/org/apache/myfaces/context/portlet/RequestParameterValuesMap.java b/impl/src/main/java/org/apache/myfaces/context/portlet/RequestParameterValuesMap.java
index 4c19fd9..e72f5de 100644
--- a/impl/src/main/java/org/apache/myfaces/context/portlet/RequestParameterValuesMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/portlet/RequestParameterValuesMap.java
@@ -19,8 +19,10 @@
 package org.apache.myfaces.context.portlet;
 
 import java.util.Enumeration;
+
 import javax.portlet.PortletRequest;
-import org.apache.myfaces.context.servlet.AbstractAttributeMap;
+
+import org.apache.myfaces.util.AbstractAttributeMap;
 
 /**
  * PortletRequest multi-value parameters as Map.
diff --git a/impl/src/main/java/org/apache/myfaces/context/portlet/SessionMap.java b/impl/src/main/java/org/apache/myfaces/context/portlet/SessionMap.java
index e81b6de..002aacd 100644
--- a/impl/src/main/java/org/apache/myfaces/context/portlet/SessionMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/portlet/SessionMap.java
@@ -18,13 +18,14 @@
  */
 package org.apache.myfaces.context.portlet;
 
-import org.apache.myfaces.shared_impl.util.NullEnumeration;
-
 import java.util.Enumeration;
 import java.util.Map;
+
 import javax.portlet.PortletRequest;
 import javax.portlet.PortletSession;
-import org.apache.myfaces.context.servlet.AbstractAttributeMap;
+
+import org.apache.myfaces.shared_impl.util.NullEnumeration;
+import org.apache.myfaces.util.AbstractThreadSafeAttributeMap;
 
 /**
  * Portlet scope PortletSession attibutes as Map.
@@ -32,7 +33,7 @@ import org.apache.myfaces.context.servlet.AbstractAttributeMap;
  * @author  Stan Silvert (latest modification by $Author$)
  * @version $Revision$ $Date$
  */
-public class SessionMap extends AbstractAttributeMap
+public class SessionMap extends AbstractThreadSafeAttributeMap
 {
     private final PortletRequest _portletRequest;
 
diff --git a/impl/src/main/java/org/apache/myfaces/context/servlet/ApplicationMap.java b/impl/src/main/java/org/apache/myfaces/context/servlet/ApplicationMap.java
index 31f05c5..f8e9de4 100755
--- a/impl/src/main/java/org/apache/myfaces/context/servlet/ApplicationMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/servlet/ApplicationMap.java
@@ -23,6 +23,8 @@ import java.util.Map;
 
 import javax.servlet.ServletContext;
 
+import org.apache.myfaces.util.AbstractThreadSafeAttributeMap;
+
 
 /**
  * ServletContext attributes as a Map.
@@ -30,7 +32,7 @@ import javax.servlet.ServletContext;
  * @author Anton Koinov (latest modification by $Author$)
  * @version $Revision$ $Date$
  */
-public class ApplicationMap extends AbstractAttributeMap
+public class ApplicationMap extends AbstractThreadSafeAttributeMap
 {
     final ServletContext _servletContext;
 
diff --git a/impl/src/main/java/org/apache/myfaces/context/servlet/CookieMap.java b/impl/src/main/java/org/apache/myfaces/context/servlet/CookieMap.java
index c3e87c2..1a4b959 100755
--- a/impl/src/main/java/org/apache/myfaces/context/servlet/CookieMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/servlet/CookieMap.java
@@ -24,6 +24,8 @@ import java.util.Map;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.myfaces.util.AbstractAttributeMap;
+
 /**
  * HttpServletRequest Cookies as Map.
  *
diff --git a/impl/src/main/java/org/apache/myfaces/context/servlet/InitParameterMap.java b/impl/src/main/java/org/apache/myfaces/context/servlet/InitParameterMap.java
index 6ff34f1..edfba60 100755
--- a/impl/src/main/java/org/apache/myfaces/context/servlet/InitParameterMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/servlet/InitParameterMap.java
@@ -23,6 +23,8 @@ import java.util.Map;
 
 import javax.servlet.ServletContext;
 
+import org.apache.myfaces.util.AbstractAttributeMap;
+
 
 /**
  * ServletContext init parameters as Map.
diff --git a/impl/src/main/java/org/apache/myfaces/context/servlet/RequestHeaderMap.java b/impl/src/main/java/org/apache/myfaces/context/servlet/RequestHeaderMap.java
index cab0213..080dc5a 100755
--- a/impl/src/main/java/org/apache/myfaces/context/servlet/RequestHeaderMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/servlet/RequestHeaderMap.java
@@ -23,6 +23,8 @@ import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.myfaces.util.AbstractAttributeMap;
+
 
 /**
  * HttpServletRequest headers as Map.
diff --git a/impl/src/main/java/org/apache/myfaces/context/servlet/RequestHeaderValuesMap.java b/impl/src/main/java/org/apache/myfaces/context/servlet/RequestHeaderValuesMap.java
index 493ca08..7b93e93 100755
--- a/impl/src/main/java/org/apache/myfaces/context/servlet/RequestHeaderValuesMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/servlet/RequestHeaderValuesMap.java
@@ -26,6 +26,8 @@ import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.myfaces.util.AbstractAttributeMap;
+
 
 /**
  * HttpServletRequest header values (multi-value headers) as Map of String[].
diff --git a/impl/src/main/java/org/apache/myfaces/context/servlet/RequestMap.java b/impl/src/main/java/org/apache/myfaces/context/servlet/RequestMap.java
index e0f4eb1..90e3dd3 100755
--- a/impl/src/main/java/org/apache/myfaces/context/servlet/RequestMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/servlet/RequestMap.java
@@ -23,6 +23,8 @@ import java.util.Map;
 
 import javax.servlet.ServletRequest;
 
+import org.apache.myfaces.util.AbstractAttributeMap;
+
 
 /**
  * ServletRequest attributes Map.
diff --git a/impl/src/main/java/org/apache/myfaces/context/servlet/RequestParameterMap.java b/impl/src/main/java/org/apache/myfaces/context/servlet/RequestParameterMap.java
index c71493a..30a93b5 100755
--- a/impl/src/main/java/org/apache/myfaces/context/servlet/RequestParameterMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/servlet/RequestParameterMap.java
@@ -22,6 +22,8 @@ import java.util.Enumeration;
 
 import javax.servlet.ServletRequest;
 
+import org.apache.myfaces.util.AbstractAttributeMap;
+
 /**
  * ServletRequest parameters as Map.
  * 
diff --git a/impl/src/main/java/org/apache/myfaces/context/servlet/RequestParameterValuesMap.java b/impl/src/main/java/org/apache/myfaces/context/servlet/RequestParameterValuesMap.java
index 979a2d3..77043a8 100755
--- a/impl/src/main/java/org/apache/myfaces/context/servlet/RequestParameterValuesMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/servlet/RequestParameterValuesMap.java
@@ -22,6 +22,8 @@ import java.util.Enumeration;
 
 import javax.servlet.ServletRequest;
 
+import org.apache.myfaces.util.AbstractAttributeMap;
+
 /**
  * ServletRequest multi-value parameters as Map.
  * 
diff --git a/impl/src/main/java/org/apache/myfaces/context/servlet/SessionMap.java b/impl/src/main/java/org/apache/myfaces/context/servlet/SessionMap.java
index 73c812f..c0cac0c 100755
--- a/impl/src/main/java/org/apache/myfaces/context/servlet/SessionMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/servlet/SessionMap.java
@@ -18,12 +18,14 @@
  */
 package org.apache.myfaces.context.servlet;
 
-import org.apache.myfaces.shared_impl.util.NullEnumeration;
+import java.util.Enumeration;
+import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
-import java.util.Enumeration;
-import java.util.Map;
+
+import org.apache.myfaces.shared_impl.util.NullEnumeration;
+import org.apache.myfaces.util.AbstractThreadSafeAttributeMap;
 
 
 /**
@@ -32,7 +34,7 @@ import java.util.Map;
  * @author Anton Koinov (latest modification by $Author$)
  * @version $Revision$ $Date$
  */
-public class SessionMap extends AbstractAttributeMap
+public class SessionMap extends AbstractThreadSafeAttributeMap
 {
     private final HttpServletRequest _httpRequest;
 
diff --git a/impl/src/main/java/org/apache/myfaces/context/servlet/AbstractAttributeMap.java b/impl/src/main/java/org/apache/myfaces/util/AbstractAttributeMap.java
old mode 100755
new mode 100644
similarity index 88%
copy from impl/src/main/java/org/apache/myfaces/context/servlet/AbstractAttributeMap.java
copy to impl/src/main/java/org/apache/myfaces/util/AbstractAttributeMap.java
index 1ed26cf..e5b9fb0
--- a/impl/src/main/java/org/apache/myfaces/context/servlet/AbstractAttributeMap.java
+++ b/impl/src/main/java/org/apache/myfaces/util/AbstractAttributeMap.java
@@ -1,362 +1,351 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.myfaces.context.servlet;
-
-import java.util.AbstractMap;
-import java.util.AbstractSet;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-
-/**
- * Helper Map implementation for use with different Attribute Maps.
- *
- * @author Anton Koinov (latest modification by $Author$)
- * @version $Revision$ $Date$
- */
-public abstract class AbstractAttributeMap
-    extends AbstractMap
-{
-    private Set              _keySet;
-    private Collection       _values;
-    private Set              _entrySet;
-
-    public void clear()
-    {
-        final List names = _list(getAttributeNames());
-
-        for (Iterator it = names.iterator(); it.hasNext();)
-        {
-            removeAttribute((String) it.next());
-        }
-    }
-
-    public boolean containsKey(Object key)
-    {
-        return getAttribute(key.toString()) != null;
-    }
-
-    public boolean containsValue(Object findValue)
-    {
-        if (findValue == null)
-        {
-            return false;
-        }
-
-        for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
-        {
-            Object value = getAttribute((String) e.nextElement());
-            if (findValue.equals(value))
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public Set entrySet()
-    {
-        return (_entrySet != null) ? _entrySet : (_entrySet = new EntrySet());
-    }
-
-    public Object get(Object key)
-    {
-        return getAttribute(key.toString());
-    }
-
-    public boolean isEmpty()
-    {
-        return !getAttributeNames().hasMoreElements();
-    }
-
-    public Set keySet()
-    {
-        return (_keySet != null) ? _keySet : (_keySet = new KeySet());
-    }
-
-    public Object put(Object key, Object value)
-    {
-        String key_ = key.toString();
-        Object retval = getAttribute(key_);
-        setAttribute(key_, value);
-        return retval;
-    }
-
-    public void putAll(Map t)
-    {
-        for (Iterator it = t.entrySet().iterator(); it.hasNext();)
-        {
-            Entry entry = (Entry) it.next();
-            setAttribute(entry.getKey().toString(), entry.getValue());
-        }
-    }
-
-    public Object remove(Object key)
-    {
-        String key_ = key.toString();
-        Object retval = getAttribute(key_);
-        removeAttribute(key_);
-        return retval;
-    }
-
-    public int size()
-    {
-        int size = 0;
-        for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
-        {
-            size++;
-            e.nextElement();
-        }
-        return size;
-    }
-
-    public Collection values()
-    {
-        return (_values != null) ? _values : (_values = new Values());
-    }
-    
-    /**
-     * Collections.list() from JDK 1.4
-     */
-    private ArrayList _list(Enumeration e) {
-        ArrayList l = new ArrayList();
-        while (e.hasMoreElements())
-        {
-            l.add(e.nextElement());
-        }
-        return l;
-    }
-    
-
-    abstract protected Object getAttribute(String key);
-
-    abstract protected void setAttribute(String key, Object value);
-
-    abstract protected void removeAttribute(String key);
-
-    abstract protected Enumeration getAttributeNames();
-
-
-    private class KeySet extends AbstractSet
-    {
-        public Iterator iterator()
-        {
-            return new KeyIterator();
-        }
-
-        public boolean isEmpty()
-        {
-            return AbstractAttributeMap.this.isEmpty();
-        }
-
-        public int size()
-        {
-            return AbstractAttributeMap.this.size();
-        }
-
-        public boolean contains(Object o)
-        {
-            return AbstractAttributeMap.this.containsKey(o);
-        }
-
-        public boolean remove(Object o)
-        {
-            return AbstractAttributeMap.this.remove(o) != null;
-        }
-
-        public void clear()
-        {
-            AbstractAttributeMap.this.clear();
-        }
-    }
-
-    private class KeyIterator
-        implements Iterator
-    {
-        // We use a copied version of the Enumeration from getAttributeNames()
-        // here, because directly using it might cause a ConcurrentModificationException
-        // when performing remove(). Note that we can do this since the Enumeration
-        // from getAttributeNames() will contain exactly the attribute names from the time
-        // getAttributeNames() was called and it will not be updated if attributes are 
-        // removed or added.
-        protected final Iterator _i = _list(getAttributeNames()).iterator();
-        protected Object _currentKey;
-
-        public void remove()
-        {
-            if (_currentKey == null)
-            {
-                throw new NoSuchElementException(
-                    "You must call next() at least once");
-            }
-            AbstractAttributeMap.this.remove(_currentKey);
-        }
-
-        public boolean hasNext()
-        {
-            return _i.hasNext();
-        }
-
-        public Object next()
-        {
-            return _currentKey = _i.next();
-        }
-    }
-
-    private class Values extends KeySet
-    {
-        public Iterator iterator()
-        {
-            return new ValuesIterator();
-        }
-
-        public boolean contains(Object o)
-        {
-            return AbstractAttributeMap.this.containsValue(o);
-        }
-
-        public boolean remove(Object o)
-        {
-            if (o == null)
-            {
-                return false;
-            }
-
-            for (Iterator it = iterator(); it.hasNext();)
-            {
-                if (o.equals(it.next()))
-                {
-                    it.remove();
-                    return true;
-                }
-            }
-
-            return false;
-        }
-    }
-
-    private class ValuesIterator extends KeyIterator
-    {
-        public Object next()
-        {
-            super.next();
-            return AbstractAttributeMap.this.get(_currentKey);
-        }
-    }
-
-    private class EntrySet extends KeySet
-    {
-        public Iterator iterator() {
-            return new EntryIterator();
-        }
-
-        public boolean contains(Object o) {
-            if (!(o instanceof Entry))
-            {
-                return false;
-            }
-
-            Entry entry = (Entry) o;
-            Object key = entry.getKey();
-            Object value = entry.getValue();
-            if (key == null || value == null)
-            {
-                return false;
-            }
-
-            return value.equals(AbstractAttributeMap.this.get(key));
-        }
-
-        public boolean remove(Object o) {
-            if (!(o instanceof Entry))
-            {
-                return false;
-            }
-
-            Entry entry = (Entry) o;
-            Object key = entry.getKey();
-            Object value = entry.getValue();
-            if (key == null || value == null
-                || !value.equals(AbstractAttributeMap.this.get(key)))
-            {
-                return false;
-            }
-
-            return AbstractAttributeMap.this.remove(((Entry) o).getKey()) != null;
-        }
-    }
-
-    /**
-     * Not very efficient since it generates a new instance of <code>Entry</code>
-     * for each element and still internaly uses the <code>KeyIterator</code>.
-     * It is more efficient to use the <code>KeyIterator</code> directly.
-     */
-    private class EntryIterator extends KeyIterator
-    {
-        public Object next()
-        {
-            super.next();
-            // Must create new Entry every time--value of the entry must stay
-            // linked to the same attribute name
-            return new EntrySetEntry(_currentKey);
-        }
-    }
-
-    private class EntrySetEntry implements Entry
-    {
-        private final Object _currentKey;
-
-        public EntrySetEntry(Object currentKey)
-        {
-            _currentKey = currentKey;
-        }
-
-        public Object getKey()
-        {
-            return _currentKey;
-        }
-
-        public Object getValue()
-        {
-            return AbstractAttributeMap.this.get(_currentKey);
-        }
-
-        public Object setValue(Object value)
-        {
-            return AbstractAttributeMap.this.put(_currentKey, value);
-        }
-
-        public int hashCode() {
-            return _currentKey == null ? 0 : _currentKey.hashCode();
-        }
-
-        public boolean equals(Object obj) {
-            if (!(obj instanceof EntrySetEntry))
-                return false;
-            return _currentKey != null && _currentKey.equals(obj);
-        }
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.myfaces.util;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+
+/**
+ * Helper Map implementation for use with different Attribute Maps.
+ *
+ * @author Anton Koinov (latest modification by $Author: jakobk $)
+ * @version $Revision: 979239 $ $Date: 2010-07-26 06:03:53 -0500 (Lun, 26 Jul 2010) $
+ */
+public abstract class AbstractAttributeMap
+    extends AbstractMap
+{
+    private Set              _keySet;
+    private Collection       _values;
+    private Set              _entrySet;
+
+    public void clear()
+    {
+        List names = new ArrayList();
+        for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
+        {
+            names.add(e.nextElement());
+        }
+
+        for (Iterator it = names.iterator(); it.hasNext();)
+        {
+            removeAttribute((String) it.next());
+        }
+    }
+
+    public boolean containsKey(Object key)
+    {
+        return getAttribute(key.toString()) != null;
+    }
+
+    public boolean containsValue(Object findValue)
+    {
+        if (findValue == null)
+        {
+            return false;
+        }
+
+        for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
+        {
+            Object value = getAttribute((String) e.nextElement());
+            if (findValue.equals(value))
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public Set entrySet()
+    {
+        return (_entrySet != null) ? _entrySet : (_entrySet = new EntrySet());
+    }
+
+    public Object get(Object key)
+    {
+        return getAttribute(key.toString());
+    }
+
+    public boolean isEmpty()
+    {
+        return !getAttributeNames().hasMoreElements();
+    }
+
+    public Set keySet()
+    {
+        return (_keySet != null) ? _keySet : (_keySet = new KeySet());
+    }
+
+    public Object put(Object key, Object value)
+    {
+        String key_ = key.toString();
+        Object retval = getAttribute(key_);
+        setAttribute(key_, value);
+        return retval;
+    }
+
+    public void putAll(Map t)
+    {
+        for (Iterator it = t.entrySet().iterator(); it.hasNext();)
+        {
+            Entry entry = (Entry) it.next();
+            setAttribute(entry.getKey().toString(), entry.getValue());
+        }
+    }
+
+    public Object remove(Object key)
+    {
+        String key_ = key.toString();
+        Object retval = getAttribute(key_);
+        removeAttribute(key_);
+        return retval;
+    }
+
+    public int size()
+    {
+        int size = 0;
+        for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
+        {
+            size++;
+            e.nextElement();
+        }
+        return size;
+    }
+
+    public Collection values()
+    {
+        return (_values != null) ? _values : (_values = new Values());
+    }
+
+
+    abstract protected Object getAttribute(String key);
+
+    abstract protected void setAttribute(String key, Object value);
+
+    abstract protected void removeAttribute(String key);
+
+    abstract protected Enumeration getAttributeNames();
+
+
+    private class KeySet extends AbstractSet
+    {
+        public Iterator iterator()
+        {
+            return new KeyIterator();
+        }
+
+        public boolean isEmpty()
+        {
+            return AbstractAttributeMap.this.isEmpty();
+        }
+
+        public int size()
+        {
+            return AbstractAttributeMap.this.size();
+        }
+
+        public boolean contains(Object o)
+        {
+            return AbstractAttributeMap.this.containsKey(o);
+        }
+
+        public boolean remove(Object o)
+        {
+            return AbstractAttributeMap.this.remove(o) != null;
+        }
+
+        public void clear()
+        {
+            AbstractAttributeMap.this.clear();
+        }
+    }
+
+    private class KeyIterator
+        implements Iterator
+    {
+        protected final Enumeration _e = getAttributeNames();
+        protected Object            _currentKey;
+
+        public void remove()
+        {
+            // remove() may cause ConcurrentModificationException.
+            // We could throw an exception here, but not throwing an exception
+            //   allows one call to remove() to succeed
+            if (_currentKey == null)
+            {
+                throw new NoSuchElementException(
+                    "You must call next() at least once");
+            }
+            AbstractAttributeMap.this.remove(_currentKey);
+        }
+
+        public boolean hasNext()
+        {
+            return _e.hasMoreElements();
+        }
+
+        public Object next()
+        {
+            return _currentKey = _e.nextElement();
+        }
+    }
+
+    private class Values extends KeySet
+    {
+        public Iterator iterator()
+        {
+            return new ValuesIterator();
+        }
+
+        public boolean contains(Object o)
+        {
+            return AbstractAttributeMap.this.containsValue(o);
+        }
+
+        public boolean remove(Object o)
+        {
+            if (o == null)
+            {
+                return false;
+            }
+
+            for (Iterator it = iterator(); it.hasNext();)
+            {
+                if (o.equals(it.next()))
+                {
+                    it.remove();
+                    return true;
+                }
+            }
+
+            return false;
+        }
+    }
+
+    private class ValuesIterator extends KeyIterator
+    {
+        public Object next()
+        {
+            super.next();
+            return AbstractAttributeMap.this.get(_currentKey);
+        }
+    }
+
+    private class EntrySet extends KeySet
+    {
+        public Iterator iterator() {
+            return new EntryIterator();
+        }
+
+        public boolean contains(Object o) {
+            if (!(o instanceof Entry))
+            {
+                return false;
+            }
+
+            Entry entry = (Entry) o;
+            Object key = entry.getKey();
+            Object value = entry.getValue();
+            if (key == null || value == null)
+            {
+                return false;
+            }
+
+            return value.equals(AbstractAttributeMap.this.get(key));
+        }
+
+        public boolean remove(Object o) {
+            if (!(o instanceof Entry))
+            {
+                return false;
+            }
+
+            Entry entry = (Entry) o;
+            Object key = entry.getKey();
+            Object value = entry.getValue();
+            if (key == null || value == null
+                || !value.equals(AbstractAttributeMap.this.get(key)))
+            {
+                return false;
+            }
+
+            return AbstractAttributeMap.this.remove(((Entry) o).getKey()) != null;
+        }
+    }
+
+    /**
+     * Not very efficient since it generates a new instance of <code>Entry</code>
+     * for each element and still internaly uses the <code>KeyIterator</code>.
+     * It is more efficient to use the <code>KeyIterator</code> directly.
+     */
+    private class EntryIterator extends KeyIterator
+    {
+        public Object next()
+        {
+            super.next();
+            // Must create new Entry every time--value of the entry must stay
+            // linked to the same attribute name
+            return new EntrySetEntry(_currentKey);
+        }
+    }
+
+    private class EntrySetEntry implements Entry
+    {
+        private final Object _currentKey;
+
+        public EntrySetEntry(Object currentKey)
+        {
+            _currentKey = currentKey;
+        }
+
+        public Object getKey()
+        {
+            return _currentKey;
+        }
+
+        public Object getValue()
+        {
+            return AbstractAttributeMap.this.get(_currentKey);
+        }
+
+        public Object setValue(Object value)
+        {
+            return AbstractAttributeMap.this.put(_currentKey, value);
+        }
+
+        public int hashCode() {
+            return _currentKey == null ? 0 : _currentKey.hashCode();
+        }
+
+        public boolean equals(Object obj) {
+            if (!(obj instanceof EntrySetEntry))
+                return false;
+            return _currentKey != null && _currentKey.equals(obj);
+        }
+    }
+}
diff --git a/impl/src/main/java/org/apache/myfaces/context/servlet/AbstractAttributeMap.java b/impl/src/main/java/org/apache/myfaces/util/AbstractThreadSafeAttributeMap.java
old mode 100755
new mode 100644
similarity index 84%
rename from impl/src/main/java/org/apache/myfaces/context/servlet/AbstractAttributeMap.java
rename to impl/src/main/java/org/apache/myfaces/util/AbstractThreadSafeAttributeMap.java
index 1ed26cf..9cf1d18
--- a/impl/src/main/java/org/apache/myfaces/context/servlet/AbstractAttributeMap.java
+++ b/impl/src/main/java/org/apache/myfaces/util/AbstractThreadSafeAttributeMap.java
@@ -1,362 +1,361 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.myfaces.context.servlet;
-
-import java.util.AbstractMap;
-import java.util.AbstractSet;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-
-/**
- * Helper Map implementation for use with different Attribute Maps.
- *
- * @author Anton Koinov (latest modification by $Author$)
- * @version $Revision$ $Date$
- */
-public abstract class AbstractAttributeMap
-    extends AbstractMap
-{
-    private Set              _keySet;
-    private Collection       _values;
-    private Set              _entrySet;
-
-    public void clear()
-    {
-        final List names = _list(getAttributeNames());
-
-        for (Iterator it = names.iterator(); it.hasNext();)
-        {
-            removeAttribute((String) it.next());
-        }
-    }
-
-    public boolean containsKey(Object key)
-    {
-        return getAttribute(key.toString()) != null;
-    }
-
-    public boolean containsValue(Object findValue)
-    {
-        if (findValue == null)
-        {
-            return false;
-        }
-
-        for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
-        {
-            Object value = getAttribute((String) e.nextElement());
-            if (findValue.equals(value))
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public Set entrySet()
-    {
-        return (_entrySet != null) ? _entrySet : (_entrySet = new EntrySet());
-    }
-
-    public Object get(Object key)
-    {
-        return getAttribute(key.toString());
-    }
-
-    public boolean isEmpty()
-    {
-        return !getAttributeNames().hasMoreElements();
-    }
-
-    public Set keySet()
-    {
-        return (_keySet != null) ? _keySet : (_keySet = new KeySet());
-    }
-
-    public Object put(Object key, Object value)
-    {
-        String key_ = key.toString();
-        Object retval = getAttribute(key_);
-        setAttribute(key_, value);
-        return retval;
-    }
-
-    public void putAll(Map t)
-    {
-        for (Iterator it = t.entrySet().iterator(); it.hasNext();)
-        {
-            Entry entry = (Entry) it.next();
-            setAttribute(entry.getKey().toString(), entry.getValue());
-        }
-    }
-
-    public Object remove(Object key)
-    {
-        String key_ = key.toString();
-        Object retval = getAttribute(key_);
-        removeAttribute(key_);
-        return retval;
-    }
-
-    public int size()
-    {
-        int size = 0;
-        for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
-        {
-            size++;
-            e.nextElement();
-        }
-        return size;
-    }
-
-    public Collection values()
-    {
-        return (_values != null) ? _values : (_values = new Values());
-    }
-    
-    /**
-     * Collections.list() from JDK 1.4
-     */
-    private ArrayList _list(Enumeration e) {
-        ArrayList l = new ArrayList();
-        while (e.hasMoreElements())
-        {
-            l.add(e.nextElement());
-        }
-        return l;
-    }
-    
-
-    abstract protected Object getAttribute(String key);
-
-    abstract protected void setAttribute(String key, Object value);
-
-    abstract protected void removeAttribute(String key);
-
-    abstract protected Enumeration getAttributeNames();
-
-
-    private class KeySet extends AbstractSet
-    {
-        public Iterator iterator()
-        {
-            return new KeyIterator();
-        }
-
-        public boolean isEmpty()
-        {
-            return AbstractAttributeMap.this.isEmpty();
-        }
-
-        public int size()
-        {
-            return AbstractAttributeMap.this.size();
-        }
-
-        public boolean contains(Object o)
-        {
-            return AbstractAttributeMap.this.containsKey(o);
-        }
-
-        public boolean remove(Object o)
-        {
-            return AbstractAttributeMap.this.remove(o) != null;
-        }
-
-        public void clear()
-        {
-            AbstractAttributeMap.this.clear();
-        }
-    }
-
-    private class KeyIterator
-        implements Iterator
-    {
-        // We use a copied version of the Enumeration from getAttributeNames()
-        // here, because directly using it might cause a ConcurrentModificationException
-        // when performing remove(). Note that we can do this since the Enumeration
-        // from getAttributeNames() will contain exactly the attribute names from the time
-        // getAttributeNames() was called and it will not be updated if attributes are 
-        // removed or added.
-        protected final Iterator _i = _list(getAttributeNames()).iterator();
-        protected Object _currentKey;
-
-        public void remove()
-        {
-            if (_currentKey == null)
-            {
-                throw new NoSuchElementException(
-                    "You must call next() at least once");
-            }
-            AbstractAttributeMap.this.remove(_currentKey);
-        }
-
-        public boolean hasNext()
-        {
-            return _i.hasNext();
-        }
-
-        public Object next()
-        {
-            return _currentKey = _i.next();
-        }
-    }
-
-    private class Values extends KeySet
-    {
-        public Iterator iterator()
-        {
-            return new ValuesIterator();
-        }
-
-        public boolean contains(Object o)
-        {
-            return AbstractAttributeMap.this.containsValue(o);
-        }
-
-        public boolean remove(Object o)
-        {
-            if (o == null)
-            {
-                return false;
-            }
-
-            for (Iterator it = iterator(); it.hasNext();)
-            {
-                if (o.equals(it.next()))
-                {
-                    it.remove();
-                    return true;
-                }
-            }
-
-            return false;
-        }
-    }
-
-    private class ValuesIterator extends KeyIterator
-    {
-        public Object next()
-        {
-            super.next();
-            return AbstractAttributeMap.this.get(_currentKey);
-        }
-    }
-
-    private class EntrySet extends KeySet
-    {
-        public Iterator iterator() {
-            return new EntryIterator();
-        }
-
-        public boolean contains(Object o) {
-            if (!(o instanceof Entry))
-            {
-                return false;
-            }
-
-            Entry entry = (Entry) o;
-            Object key = entry.getKey();
-            Object value = entry.getValue();
-            if (key == null || value == null)
-            {
-                return false;
-            }
-
-            return value.equals(AbstractAttributeMap.this.get(key));
-        }
-
-        public boolean remove(Object o) {
-            if (!(o instanceof Entry))
-            {
-                return false;
-            }
-
-            Entry entry = (Entry) o;
-            Object key = entry.getKey();
-            Object value = entry.getValue();
-            if (key == null || value == null
-                || !value.equals(AbstractAttributeMap.this.get(key)))
-            {
-                return false;
-            }
-
-            return AbstractAttributeMap.this.remove(((Entry) o).getKey()) != null;
-        }
-    }
-
-    /**
-     * Not very efficient since it generates a new instance of <code>Entry</code>
-     * for each element and still internaly uses the <code>KeyIterator</code>.
-     * It is more efficient to use the <code>KeyIterator</code> directly.
-     */
-    private class EntryIterator extends KeyIterator
-    {
-        public Object next()
-        {
-            super.next();
-            // Must create new Entry every time--value of the entry must stay
-            // linked to the same attribute name
-            return new EntrySetEntry(_currentKey);
-        }
-    }
-
-    private class EntrySetEntry implements Entry
-    {
-        private final Object _currentKey;
-
-        public EntrySetEntry(Object currentKey)
-        {
-            _currentKey = currentKey;
-        }
-
-        public Object getKey()
-        {
-            return _currentKey;
-        }
-
-        public Object getValue()
-        {
-            return AbstractAttributeMap.this.get(_currentKey);
-        }
-
-        public Object setValue(Object value)
-        {
-            return AbstractAttributeMap.this.put(_currentKey, value);
-        }
-
-        public int hashCode() {
-            return _currentKey == null ? 0 : _currentKey.hashCode();
-        }
-
-        public boolean equals(Object obj) {
-            if (!(obj instanceof EntrySetEntry))
-                return false;
-            return _currentKey != null && _currentKey.equals(obj);
-        }
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.myfaces.util;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+
+/**
+ * Helper Map implementation for use with different Attribute Maps.
+ * 
+ * @author Anton Koinov (latest modification by $Author: lu4242 $)
+ * @version $Revision: 982465 $ $Date: 2010-08-04 23:39:32 -0500 (MiƩ, 04 Ago 2010) $
+ */
+public abstract class AbstractThreadSafeAttributeMap extends AbstractMap
+{
+    private Set              _keySet;
+    private Collection       _values;
+    private Set              _entrySet;
+
+    public void clear()
+    {
+        final List names = _list(getAttributeNames());
+
+        for (Iterator it = names.iterator(); it.hasNext();)
+        {
+            removeAttribute((String) it.next());
+        }
+    }
+
+    public boolean containsKey(Object key)
+    {
+        return getAttribute(key.toString()) != null;
+    }
+
+    public boolean containsValue(Object findValue)
+    {
+        if (findValue == null)
+        {
+            return false;
+        }
+
+        for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
+        {
+            Object value = getAttribute((String) e.nextElement());
+            if (findValue.equals(value))
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public Set entrySet()
+    {
+        return (_entrySet != null) ? _entrySet : (_entrySet = new EntrySet());
+    }
+
+    public Object get(Object key)
+    {
+        return getAttribute(key.toString());
+    }
+
+    public boolean isEmpty()
+    {
+        return !getAttributeNames().hasMoreElements();
+    }
+
+    public Set keySet()
+    {
+        return (_keySet != null) ? _keySet : (_keySet = new KeySet());
+    }
+
+    public Object put(Object key, Object value)
+    {
+        String key_ = key.toString();
+        Object retval = getAttribute(key_);
+        setAttribute(key_, value);
+        return retval;
+    }
+
+    public void putAll(Map t)
+    {
+        for (Iterator it = t.entrySet().iterator(); it.hasNext();)
+        {
+            Entry entry = (Entry) it.next();
+            setAttribute(entry.getKey().toString(), entry.getValue());
+        }
+    }
+
+    public Object remove(Object key)
+    {
+        String key_ = key.toString();
+        Object retval = getAttribute(key_);
+        removeAttribute(key_);
+        return retval;
+    }
+
+    public int size()
+    {
+        int size = 0;
+        for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
+        {
+            size++;
+            e.nextElement();
+        }
+        return size;
+    }
+
+    public Collection values()
+    {
+        return (_values != null) ? _values : (_values = new Values());
+    }
+    
+    /**
+     * Collections.list() from JDK 1.4
+     */
+    private ArrayList _list(Enumeration e) {
+        ArrayList l = new ArrayList();
+        while (e.hasMoreElements())
+        {
+            l.add(e.nextElement());
+        }
+        return l;
+    }
+    
+
+    abstract protected Object getAttribute(String key);
+
+    abstract protected void setAttribute(String key, Object value);
+
+    abstract protected void removeAttribute(String key);
+
+    abstract protected Enumeration getAttributeNames();
+
+
+    private class KeySet extends AbstractSet
+    {
+        public Iterator iterator()
+        {
+            return new KeyIterator();
+        }
+
+        public boolean isEmpty()
+        {
+            return AbstractThreadSafeAttributeMap.this.isEmpty();
+        }
+
+        public int size()
+        {
+            return AbstractThreadSafeAttributeMap.this.size();
+        }
+
+        public boolean contains(Object o)
+        {
+            return AbstractThreadSafeAttributeMap.this.containsKey(o);
+        }
+
+        public boolean remove(Object o)
+        {
+            return AbstractThreadSafeAttributeMap.this.remove(o) != null;
+        }
+
+        public void clear()
+        {
+            AbstractThreadSafeAttributeMap.this.clear();
+        }
+    }
+
+    private class KeyIterator
+        implements Iterator
+    {
+        // We use a copied version of the Enumeration from getAttributeNames()
+        // here, because directly using it might cause a ConcurrentModificationException
+        // when performing remove(). Note that we can do this since the Enumeration
+        // from getAttributeNames() will contain exactly the attribute names from the time
+        // getAttributeNames() was called and it will not be updated if attributes are 
+        // removed or added.
+        protected final Iterator _i = _list(getAttributeNames()).iterator();
+        protected Object _currentKey;
+
+        public void remove()
+        {
+            if (_currentKey == null)
+            {
+                throw new NoSuchElementException(
+                    "You must call next() at least once");
+            }
+            AbstractThreadSafeAttributeMap.this.remove(_currentKey);
+        }
+
+        public boolean hasNext()
+        {
+            return _i.hasNext();
+        }
+
+        public Object next()
+        {
+            return _currentKey = _i.next();
+        }
+    }
+
+    private class Values extends KeySet
+    {
+        public Iterator iterator()
+        {
+            return new ValuesIterator();
+        }
+
+        public boolean contains(Object o)
+        {
+            return AbstractThreadSafeAttributeMap.this.containsValue(o);
+        }
+
+        public boolean remove(Object o)
+        {
+            if (o == null)
+            {
+                return false;
+            }
+
+            for (Iterator it = iterator(); it.hasNext();)
+            {
+                if (o.equals(it.next()))
+                {
+                    it.remove();
+                    return true;
+                }
+            }
+
+            return false;
+        }
+    }
+
+    private class ValuesIterator extends KeyIterator
+    {
+        public Object next()
+        {
+            super.next();
+            return AbstractThreadSafeAttributeMap.this.get(_currentKey);
+        }
+    }
+
+    private class EntrySet extends KeySet
+    {
+        public Iterator iterator() {
+            return new EntryIterator();
+        }
+
+        public boolean contains(Object o) {
+            if (!(o instanceof Entry))
+            {
+                return false;
+            }
+
+            Entry entry = (Entry) o;
+            Object key = entry.getKey();
+            Object value = entry.getValue();
+            if (key == null || value == null)
+            {
+                return false;
+            }
+
+            return value.equals(AbstractThreadSafeAttributeMap.this.get(key));
+        }
+
+        public boolean remove(Object o) {
+            if (!(o instanceof Entry))
+            {
+                return false;
+            }
+
+            Entry entry = (Entry) o;
+            Object key = entry.getKey();
+            Object value = entry.getValue();
+            if (key == null || value == null
+                || !value.equals(AbstractThreadSafeAttributeMap.this.get(key)))
+            {
+                return false;
+            }
+
+            return AbstractThreadSafeAttributeMap.this.remove(((Entry) o).getKey()) != null;
+        }
+    }
+
+    /**
+     * Not very efficient since it generates a new instance of <code>Entry</code>
+     * for each element and still internaly uses the <code>KeyIterator</code>.
+     * It is more efficient to use the <code>KeyIterator</code> directly.
+     */
+    private class EntryIterator extends KeyIterator
+    {
+        public Object next()
+        {
+            super.next();
+            // Must create new Entry every time--value of the entry must stay
+            // linked to the same attribute name
+            return new EntrySetEntry(_currentKey);
+        }
+    }
+
+    private class EntrySetEntry implements Entry
+    {
+        private final Object _currentKey;
+
+        public EntrySetEntry(Object currentKey)
+        {
+            _currentKey = currentKey;
+        }
+
+        public Object getKey()
+        {
+            return _currentKey;
+        }
+
+        public Object getValue()
+        {
+            return AbstractThreadSafeAttributeMap.this.get(_currentKey);
+        }
+
+        public Object setValue(Object value)
+        {
+            return AbstractThreadSafeAttributeMap.this.put(_currentKey, value);
+        }
+
+        public int hashCode() {
+            return _currentKey == null ? 0 : _currentKey.hashCode();
+        }
+
+        public boolean equals(Object obj) {
+            if (!(obj instanceof EntrySetEntry))
+                return false;
+            return _currentKey != null && _currentKey.equals(obj);
+        }
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
deki@apache.org.