convert MetaData to HttpField as a list

This commit is contained in:
Greg Wilkins 2014-06-11 16:53:17 +02:00
parent bbd61f8e19
commit c319c19125
5 changed files with 216 additions and 119 deletions

View File

@ -18,6 +18,8 @@
package org.eclipse.jetty.http;
import java.util.ArrayList;
import org.eclipse.jetty.util.QuotedStringTokenizer;
@ -68,14 +70,136 @@ public class HttpField
}
public String[] getValues()
{
ArrayList<String> list = new ArrayList<>();
int state = 0;
int start=0;
int end=0;
StringBuilder builder = new StringBuilder();
for (int i=0;i<_value.length();i++)
{
char c = _value.charAt(i);
switch(state)
{
case 0: // initial white space
switch(c)
{
case '"': // open quote
state=2;
break;
case ',': // leading empty field
list.add("");
break;
case ' ': // more white space
case '\t':
break;
default: // character
start=i;
end=i;
state=1;
}
break;
case 1: // In token
switch(c)
{
case ',': // next field
list.add(_value.substring(start,end+1));
state=0;
break;
case ' ': // more white space
case '\t':
break;
default:
end=i;
}
break;
case 2: // In Quoted
switch(c)
{
case '\\': // next field
state=3;
break;
case '"': // end quote
list.add(builder.toString());
builder.setLength(0);
state=4;
break;
default:
builder.append(c);
}
break;
case 3: // In Quoted Quoted
builder.append(c);
state=2;
break;
case 4: // WS after end quote
switch(c)
{
case ' ': // white space
case '\t': // white space
break;
case ',': // white space
state=0;
break;
default:
throw new IllegalArgumentException("c="+(int)c);
}
break;
}
}
switch(state)
{
case 0:
break;
case 1:
list.add(_value.substring(start,end+1));
break;
case 4:
break;
default:
throw new IllegalArgumentException("state="+state);
}
return list.toArray(new String[list.size()]);
}
/* ------------------------------------------------------------ */
/** Look for a value in a possible multi valued field
* @param value
* @return True iff the value is contained in the field value entirely or
* as an element of a quoted comma separated list
*/
public boolean contains(String value)
{
QuotedStringTokenizer tok = new QuotedStringTokenizer(_value, ",", false, false);
tok.setSingle(false);
String[] v = new String[tok.countTokens()];
int t=0;
while(tok.hasMoreTokens())
v[t++]=tok.nextToken();
return v;
if (_value==null)
return value==null;
if (_value.equalsIgnoreCase(value))
return true;
String[] values = getValues();
for (String v:values)
if (v.equalsIgnoreCase(value))
return true;
return false;
}
@Override

View File

@ -24,13 +24,11 @@ import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import org.eclipse.jetty.util.ArrayTernaryTrie;
import org.eclipse.jetty.util.LazyList;
@ -50,28 +48,34 @@ import org.eclipse.jetty.util.log.Logger;
* <p>The cookie handling provided by this class is guided by the Servlet specification and RFC6265.
*
*/
public class HttpFields implements Iterable<HttpField>
public class HttpFields extends ArrayList<HttpField>
{
private static final Logger LOG = Log.getLogger(HttpFields.class);
private final static Pattern __splitter = Pattern.compile("\\s*,\\s*");
private static final long serialVersionUID = 1L;
private static final Logger LOG = Log.getLogger(HttpFields.class);
public final static String __separators = ", \t";
private final ArrayList<HttpField> _fields = new ArrayList<>(20);
/**
* Constructor.
*/
public HttpFields()
{
}
/**
* Constructor.
*/
public HttpFields(int capacity)
{
super(capacity);
}
/**
* Get Collection of header names.
*/
public Collection<String> getFieldNamesCollection()
{
final Set<String> list = new HashSet<>(_fields.size());
for (HttpField f : _fields)
final Set<String> list = new HashSet<>(size());
for (HttpField f : this)
{
if (f!=null)
list.add(f.getName());
@ -88,11 +92,6 @@ public class HttpFields implements Iterable<HttpField>
return Collections.enumeration(getFieldNamesCollection());
}
public int size()
{
return _fields.size();
}
/**
* Get a Field by index.
* @return A Field value or null if the Field value has not been set
@ -100,20 +99,14 @@ public class HttpFields implements Iterable<HttpField>
*/
public HttpField getField(int i)
{
return _fields.get(i);
}
@Override
public Iterator<HttpField> iterator()
{
return _fields.iterator();
return get(i);
}
public HttpField getField(HttpHeader header)
{
for (int i=0;i<_fields.size();i++)
for (int i=0;i<size();i++)
{
HttpField f=_fields.get(i);
HttpField f=get(i);
if (f.getHeader()==header)
return f;
}
@ -122,9 +115,9 @@ public class HttpFields implements Iterable<HttpField>
public HttpField getField(String name)
{
for (int i=0;i<_fields.size();i++)
for (int i=0;i<size();i++)
{
HttpField f=_fields.get(i);
HttpField f=get(i);
if (f.getName().equalsIgnoreCase(name))
return f;
}
@ -133,10 +126,10 @@ public class HttpFields implements Iterable<HttpField>
public boolean contains(HttpHeader header, String value)
{
for (int i=0;i<_fields.size();i++)
for (int i=0;i<size();i++)
{
HttpField f=_fields.get(i);
if (f.getHeader()==header && contains(f,value))
HttpField f=get(i);
if (f.getHeader()==header && f.contains(value))
return true;
}
return false;
@ -144,39 +137,21 @@ public class HttpFields implements Iterable<HttpField>
public boolean contains(String name, String value)
{
for (int i=0;i<_fields.size();i++)
for (int i=0;i<size();i++)
{
HttpField f=_fields.get(i);
if (f.getName().equalsIgnoreCase(name) && contains(f,value))
HttpField f=get(i);
if (f.getName().equalsIgnoreCase(name) && f.contains(value))
return true;
}
return false;
}
private boolean contains(HttpField field,String value)
{
String v = field.getValue();
if (v==null)
return false;
if (value.equalsIgnoreCase(v))
return true;
String[] split = __splitter.split(v);
for (int i = 0; split!=null && i < split.length; i++)
{
if (value.equals(split[i]))
return true;
}
return false;
}
public boolean containsKey(String name)
{
for (int i=0;i<_fields.size();i++)
for (int i=0;i<size();i++)
{
HttpField f=_fields.get(i);
HttpField f=get(i);
if (f.getName().equalsIgnoreCase(name))
return true;
}
@ -218,7 +193,7 @@ public class HttpFields implements Iterable<HttpField>
public List<String> getValuesList(String name)
{
final List<String> list = new ArrayList<>();
for (HttpField f : _fields)
for (HttpField f : this)
if (f.getName().equalsIgnoreCase(name))
list.add(f.getValue());
return list;
@ -232,9 +207,9 @@ public class HttpFields implements Iterable<HttpField>
*/
public Enumeration<String> getValues(final String name)
{
for (int i=0;i<_fields.size();i++)
for (int i=0;i<size();i++)
{
final HttpField f = _fields.get(i);
final HttpField f = get(i);
if (f.getName().equalsIgnoreCase(name) && f.getValue()!=null)
{
@ -249,9 +224,9 @@ public class HttpFields implements Iterable<HttpField>
{
if (field==null)
{
while (i<_fields.size())
while (i<size())
{
field=_fields.get(i++);
field=get(i++);
if (field.getName().equalsIgnoreCase(name) && field.getValue()!=null)
return true;
}
@ -330,22 +305,22 @@ public class HttpFields implements Iterable<HttpField>
public void put(HttpField field)
{
boolean put=false;
for (int i=_fields.size();i-->0;)
for (int i=size();i-->0;)
{
HttpField f=_fields.get(i);
HttpField f=get(i);
if (f.isSameName(field))
{
if (put)
_fields.remove(i);
remove(i);
else
{
_fields.set(i,field);
set(i,field);
put=true;
}
}
}
if (!put)
_fields.add(field);
add(field);
}
/**
@ -410,7 +385,7 @@ public class HttpFields implements Iterable<HttpField>
return;
HttpField field = new HttpField(name, value);
_fields.add(field);
add(field);
}
public void add(HttpHeader header, HttpHeaderValue value) throws IllegalArgumentException
@ -431,7 +406,7 @@ public class HttpFields implements Iterable<HttpField>
if (value == null) throw new IllegalArgumentException("null value");
HttpField field = new HttpField(header, value);
_fields.add(field);
add(field);
}
/**
@ -441,11 +416,11 @@ public class HttpFields implements Iterable<HttpField>
*/
public HttpField remove(HttpHeader name)
{
for (int i=_fields.size();i-->0;)
for (int i=size();i-->0;)
{
HttpField f=_fields.get(i);
HttpField f=get(i);
if (f.getHeader()==name)
return _fields.remove(i);
return remove(i);
}
return null;
}
@ -457,11 +432,11 @@ public class HttpFields implements Iterable<HttpField>
*/
public HttpField remove(String name)
{
for (int i=_fields.size();i-->0;)
for (int i=size();i-->0;)
{
HttpField f=_fields.get(i);
HttpField f=get(i);
if (f.getName().equalsIgnoreCase(name))
return _fields.remove(i);
return remove(i);
}
return null;
}
@ -570,7 +545,7 @@ public class HttpFields implements Iterable<HttpField>
try
{
StringBuilder buffer = new StringBuilder();
for (HttpField field : _fields)
for (HttpField field : this)
{
if (field != null)
{
@ -591,21 +566,6 @@ public class HttpFields implements Iterable<HttpField>
return e.toString();
}
}
/**
* Clear the header.
*/
public void clear()
{
_fields.clear();
}
public void add(HttpField field)
{
_fields.add(field);
}
/**
* Add fields from another HttpFields instance. Single valued fields are replaced, while all

View File

@ -436,4 +436,32 @@ public class HttpFieldsTest
assertEquals(""+i,i>=4,header.contains(""+i,"def"));
}
}
@Test
public void testValues()
{
String[] values = new HttpField("name","value").getValues();
assertEquals(1,values.length);
assertEquals("value",values[0]);
values = new HttpField("name","a,b,c").getValues();
assertEquals(3,values.length);
assertEquals("a",values[0]);
assertEquals("b",values[1]);
assertEquals("c",values[2]);
values = new HttpField("name","a,\"x,y,z\",c").getValues();
assertEquals(3,values.length);
assertEquals("a",values[0]);
assertEquals("x,y,z",values[1]);
assertEquals("c",values[2]);
values = new HttpField("name","a,\"x,\\\"p,q\\\",z\",c").getValues();
assertEquals(3,values.length);
assertEquals("a",values[0]);
assertEquals("x,\"p,q\",z",values[1]);
assertEquals("c",values[2]);
}
}

View File

@ -19,14 +19,11 @@
package org.eclipse.jetty.http2.hpack;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme;
@ -35,9 +32,9 @@ import org.eclipse.jetty.http.HttpScheme;
*/
public class MetaData implements Iterable<HttpField>
{
private final Iterable<HttpField> _fields;
private final HttpFields _fields;
public MetaData(Iterable<HttpField> fields)
public MetaData(HttpFields fields)
{
_fields=fields;
}
@ -58,14 +55,9 @@ public class MetaData implements Iterable<HttpField>
return _fields.iterator();
}
public List<HttpField> getFields()
public HttpFields getFields()
{
if (_fields instanceof List)
return (List<HttpField>)_fields;
ArrayList<HttpField> list = new ArrayList<>();
for (HttpField field:_fields)
list.add(field);
return list;
return _fields;
}
@Override
@ -112,7 +104,7 @@ public class MetaData implements Iterable<HttpField>
private final int _port;
private final String _path;
public Request(HttpScheme scheme, String method, String authority, String host, int port, String path, Iterable<HttpField> fields)
public Request(HttpScheme scheme, String method, String authority, String host, int port, String path, HttpFields fields)
{
super(fields);
_authority=authority;
@ -200,12 +192,6 @@ public class MetaData implements Iterable<HttpField>
_status=status;
}
public Response(int status, Iterable<HttpField> fields)
{
super(fields);
_status=status;
}
@Override
public boolean isRequest()
{

View File

@ -19,12 +19,10 @@
package org.eclipse.jetty.http2.hpack;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.http.HostPortHttpField;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpScheme;
/* -------------------------------------------------------- */
@ -40,7 +38,7 @@ public class MetaDataBuilder
private int _port;
private String _path;
List<HttpField> _fields = new ArrayList<>();
HttpFields _fields = new HttpFields(10);
public void emit(HttpField field)
{
@ -104,11 +102,13 @@ public class MetaDataBuilder
{
try
{
HttpFields fields = _fields;
_fields = new HttpFields(Math.max(10,fields.size()+5));
if (_method!=null)
return new MetaData.Request(_scheme,_method,_authority,_host,_port,_path,new ArrayList<>(_fields));
return new MetaData.Request(_scheme,_method,_authority,_host,_port,_path,fields);
if (_status!=0)
return new MetaData.Response(_status,new ArrayList<>(_fields));
return new MetaData(new ArrayList<>(_fields));
return new MetaData.Response(_status,fields);
return new MetaData(fields);
}
finally
{
@ -119,7 +119,6 @@ public class MetaDataBuilder
_path=null;
_host=null;
_port=0;
_fields.clear();
}
}
}