diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java b/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java index d227e7546f2..de1457b9f62 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java @@ -13,11 +13,9 @@ package org.eclipse.jetty.util; -import java.io.Externalizable; import java.nio.ByteBuffer; import java.util.AbstractMap; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -34,25 +32,25 @@ import java.util.Set; * * This map is NOT synchronized. */ -public class StringMap extends AbstractMap implements Externalizable +public class StringMap extends AbstractMap { public static final boolean CASE_INSENSTIVE=true; protected static final int __HASH_WIDTH=17; /* ------------------------------------------------------------ */ - protected int _width=__HASH_WIDTH; + + private final boolean _ignoreCase; + protected Node _root=new Node<>(); - protected boolean _ignoreCase=false; - protected NullEntry _nullEntry=null; - protected O _nullValue=null; protected HashSet> _entrySet=new HashSet<>(3); - protected Set> _umEntrySet=Collections.unmodifiableSet(_entrySet); /* ------------------------------------------------------------ */ /** Constructor. */ public StringMap() - {} + { + _ignoreCase=false; + } /* ------------------------------------------------------------ */ /** Constructor. @@ -60,71 +58,21 @@ public class StringMap extends AbstractMap implements Externalizabl */ public StringMap(boolean ignoreCase) { - this(); _ignoreCase=ignoreCase; } - - /* ------------------------------------------------------------ */ - /** Constructor. - * @param ignoreCase - * @param width Width of hash tables, larger values are faster but - * use more memory. - */ - public StringMap(boolean ignoreCase,int width) - { - this(); - _ignoreCase=ignoreCase; - _width=width; - } - - /* ------------------------------------------------------------ */ - /** Set the ignoreCase attribute. - * @param ic If true, the map is case insensitive for keys. - */ - public void setIgnoreCase(boolean ic) - { - if (_root._children!=null) - throw new IllegalStateException("Must be set before first put"); - _ignoreCase=ic; - } /* ------------------------------------------------------------ */ public boolean isIgnoreCase() { return _ignoreCase; } - - /* ------------------------------------------------------------ */ - /** Set the hash width. - * @param width Width of hash tables, larger values are faster but - * use more memory. - */ - public void setWidth(int width) - { - _width=width; - } - - /* ------------------------------------------------------------ */ - public int getWidth() - { - return _width; - } /* ------------------------------------------------------------ */ @Override public O put(String key, O value) { if (key==null) - { - O oldValue=_nullValue; - _nullValue=value; - if (_nullEntry==null) - { - _nullEntry=new NullEntry(); - _entrySet.add(_nullEntry); - } - return oldValue; - } + throw new IllegalArgumentException(); Node node = _root; int ni=-1; @@ -143,7 +91,7 @@ public class StringMap extends AbstractMap implements Externalizabl parent=node; prev=null; ni=0; - node=(node._children==null)?null:node._children[c%_width]; + node=(node._children==null)?null:node._children[c%__HASH_WIDTH]; } // Loop through a node chain at the same level @@ -185,10 +133,10 @@ public class StringMap extends AbstractMap implements Externalizabl else if (parent!=null) // add new child { if (parent._children==null) - parent._children=new Node[_width]; - parent._children[c%_width]=node; - int oi=node._ochar[0]%_width; - if (node._ochar!=null && node._char[0]%_width!=oi) + parent._children=new Node[__HASH_WIDTH]; + parent._children[c%__HASH_WIDTH]=node; + int oi=node._ochar[0]%__HASH_WIDTH; + if (node._ochar!=null && node._char[0]%__HASH_WIDTH!=oi) { if (parent._children[oi]==null) parent._children[oi]=node; @@ -227,7 +175,7 @@ public class StringMap extends AbstractMap implements Externalizabl public O get(Object key) { if (key==null) - return _nullValue; + throw new IllegalArgumentException(); return get(key.toString()); } @@ -235,7 +183,7 @@ public class StringMap extends AbstractMap implements Externalizabl public O get(String key) { if (key==null) - return _nullValue; + throw new IllegalArgumentException(); Map.Entry entry = getEntry(key,0,key.length()); if (entry==null) @@ -263,7 +211,7 @@ public class StringMap extends AbstractMap implements Externalizabl public Map.Entry getEntry(String key,int offset, int length) { if (key==null) - return _nullEntry; + throw new IllegalArgumentException(); Node node = _root; int ni=-1; @@ -278,7 +226,7 @@ public class StringMap extends AbstractMap implements Externalizabl if (ni==-1) { ni=0; - node=(node._children==null)?null:node._children[c%_width]; + node=(node._children==null)?null:node._children[c%__HASH_WIDTH]; } // Look through the node chain @@ -319,7 +267,7 @@ public class StringMap extends AbstractMap implements Externalizabl public Map.Entry getEntry(char[] key,int offset, int length) { if (key==null) - return _nullEntry; + throw new IllegalArgumentException(); Node node = _root; int ni=-1; @@ -334,7 +282,7 @@ public class StringMap extends AbstractMap implements Externalizabl if (ni==-1) { ni=0; - node=(node._children==null)?null:node._children[c%_width]; + node=(node._children==null)?null:node._children[c%__HASH_WIDTH]; } // While we have a node to try @@ -376,7 +324,7 @@ public class StringMap extends AbstractMap implements Externalizabl public Map.Entry getEntry(byte[] key,int offset, int length) { if (key==null) - return _nullEntry; + throw new IllegalArgumentException(); Node node = _root; int ni=-1; @@ -391,7 +339,7 @@ public class StringMap extends AbstractMap implements Externalizabl if (ni==-1) { ni=0; - node=(node._children==null)?null:node._children[c%_width]; + node=(node._children==null)?null:node._children[c%__HASH_WIDTH]; } // While we have a node to try @@ -443,7 +391,7 @@ public class StringMap extends AbstractMap implements Externalizabl public Map.Entry getEntry(ByteBuffer key,int position,int length) { if (key==null) - return _nullEntry; + throw new IllegalArgumentException(); if (!key.isReadOnly() && !key.isDirect()) return getEntry(key.array(),key.position(),key.remaining()); @@ -460,7 +408,7 @@ public class StringMap extends AbstractMap implements Externalizabl if (ni==-1) { ni=0; - node=(node._children==null)?null:node._children[c%_width]; + node=(node._children==null)?null:node._children[c%__HASH_WIDTH]; } // While we have a node to try @@ -504,16 +452,7 @@ public class StringMap extends AbstractMap implements Externalizabl public O remove(String key) { if (key==null) - { - O oldValue=_nullValue; - if (_nullEntry!=null) - { - _entrySet.remove(_nullEntry); - _nullEntry=null; - _nullValue=null; - } - return oldValue; - } + throw new IllegalArgumentException(); Node node = _root; int ni=-1; @@ -528,7 +467,7 @@ public class StringMap extends AbstractMap implements Externalizabl if (ni==-1) { ni=0; - node=(node._children==null)?null:node._children[c%_width]; + node=(node._children==null)?null:node._children[c%__HASH_WIDTH]; } // While we have a node to try @@ -568,7 +507,7 @@ public class StringMap extends AbstractMap implements Externalizabl @Override public Set> entrySet() { - return _umEntrySet; + return Collections.unmodifiableSet(_entrySet); } /* ------------------------------------------------------------ */ @@ -590,7 +529,7 @@ public class StringMap extends AbstractMap implements Externalizabl public boolean containsKey(Object key) { if (key==null) - return _nullEntry!=null; + return false; return getEntry(key.toString(),0,key==null?0:key.toString().length())!=null; } @@ -600,8 +539,6 @@ public class StringMap extends AbstractMap implements Externalizabl public void clear() { _root=new Node(); - _nullEntry=null; - _nullValue=null; _entrySet.clear(); } @@ -669,10 +606,10 @@ public class StringMap extends AbstractMap implements Externalizabl map._entrySet.add(split); split._children=this._children; - this._children=new Node[map._width]; - this._children[split._char[0]%map._width]=split; - if (split._ochar!=null && this._children[split._ochar[0]%map._width]!=split) - this._children[split._ochar[0]%map._width]=split; + this._children=new Node[map.__HASH_WIDTH]; + this._children[split._char[0]%map.__HASH_WIDTH]=split; + if (split._ochar!=null && this._children[split._ochar[0]%map.__HASH_WIDTH]!=split) + this._children[split._ochar[0]%map.__HASH_WIDTH]=split; return split; } @@ -721,34 +658,4 @@ public class StringMap extends AbstractMap implements Externalizabl } } - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - private class NullEntry implements Map.Entry - { - public String getKey(){return null;} - public O getValue(){return _nullValue;} - public O setValue(O o) - {O old=_nullValue;_nullValue=o;return old;} - @Override - public String toString(){return "[:null="+_nullValue+"]";} - } - - /* ------------------------------------------------------------ */ - public void writeExternal(java.io.ObjectOutput out) - throws java.io.IOException - { - HashMap map = new HashMap(this); - out.writeBoolean(_ignoreCase); - out.writeObject(map); - } - - /* ------------------------------------------------------------ */ - public void readExternal(java.io.ObjectInput in) - throws java.io.IOException, ClassNotFoundException - { - boolean ic=in.readBoolean(); - HashMap map = (HashMap)in.readObject(); - setIgnoreCase(ic); - this.putAll(map); - } } diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/StringMapTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/StringMapTest.java index 126167e046b..d53bec17e5f 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/StringMapTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/StringMapTest.java @@ -58,11 +58,9 @@ public class StringMapTest m5.put("bbb", "4"); m5i=new StringMap(true); - m5i.put(null, "0"); m5i.put("ab", "1"); m5i.put("abc", "2"); m5i.put("abb", "3"); - m5i.put("bbb", null); } @Test @@ -71,7 +69,7 @@ public class StringMapTest assertEquals(0, m0.size()); assertEquals(1, m1.size()); assertEquals(5, m5.size()); - assertEquals(5, m5i.size()); + assertEquals(3, m5i.size()); m1.remove("abc"); m5.remove("abc"); @@ -80,7 +78,7 @@ public class StringMapTest assertEquals(0, m0.size()); assertEquals(0, m1.size()); assertEquals(4, m5.size()); - assertEquals(5, m5i.size()); + assertEquals(3, m5i.size()); } @Test @@ -120,7 +118,6 @@ public class StringMapTest assertEquals("2",m5i.get("abc")); assertEquals("2",m5i.get("aBc")); - m5.put(null,"x"); m5.put("aBc", "x"); m5i.put("AbC", "x"); @@ -131,8 +128,6 @@ public class StringMapTest assertEquals("x",m5i.get((Object)"abc")); assertEquals("x",m5i.get("aBc")); - assertEquals("x",m5.get(null)); - assertEquals("0",m5i.get(null)); } @@ -159,12 +154,6 @@ public class StringMapTest entry.setValue("x"); assertEquals("{[c:abc=x]}",entry.toString()); - entry=m5i.getEntry((String)null,0,0); - assertTrue(entry!=null); - assertEquals(null,entry.getKey()); - assertEquals("0",entry.getValue()); - entry.setValue("x"); - assertEquals("[:null=x]",entry.toString()); } @@ -203,17 +192,15 @@ public class StringMapTest m5.remove("aBc"); m5.remove("bbb"); m5i.remove("aBc"); - m5i.remove(null); assertEquals(0, m0.size()); assertEquals(0, m1.size()); assertEquals(4, m5.size()); - assertEquals(3, m5i.size()); + assertEquals(2, m5i.size()); assertEquals("2",m5.get("abc")); assertEquals(null,m5.get("bbb")); assertEquals(null,m5i.get("AbC")); - assertEquals(null,m5i.get(null)); } /* @@ -241,41 +228,11 @@ public class StringMapTest assertTrue(m5.containsKey("bbb")); assertTrue(!m5.containsKey("xyz")); - assertTrue(m5i.containsKey(null)); assertTrue(m5i.containsKey("abc")); assertTrue(m5i.containsKey("aBc")); assertTrue(m5i.containsKey("ABC")); } - @Test - public void testWriteExternal() - throws Exception - { - ByteArrayOutputStream bout= new ByteArrayOutputStream(); - ObjectOutputStream oo=new ObjectOutputStream(bout); - ObjectInputStream oi; - - oo.writeObject(m0); - oo.writeObject(m1); - oo.writeObject(m5); - oo.writeObject(m5i); - - oi=new ObjectInputStream(new ByteArrayInputStream(bout.toByteArray())); - m0=(StringMap)oi.readObject(); - m1=(StringMap)oi.readObject(); - m5=(StringMap)oi.readObject(); - m5i=(StringMap)oi.readObject(); - testSize(); - - oi=new ObjectInputStream(new ByteArrayInputStream(bout.toByteArray())); - m0=(StringMap)oi.readObject(); - m1=(StringMap)oi.readObject(); - m5=(StringMap)oi.readObject(); - m5i=(StringMap)oi.readObject(); - testPutGet(); - - } - @Test public void testToString() {