users@jersey.java.net

Re: [Jersey] Initial crack at HeaderValue class (and corresponding unit test)

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Sat, 08 Nov 2008 10:03:57 +0100

On Nov 7, 2008, at 8:34 PM, Craig McClanahan wrote:

> Paul Sandoz wrote:
>>
>> On Nov 7, 2008, at 8:08 PM, Craig McClanahan wrote:
>>
>>> Paul Sandoz wrote:
>>>> Hi Craig,
>>>>
>>>> I have re-factored the header stuff in jersey-core to be part of
>>>> the API and added the following:
>>>>
>>>> com.sun.jersey.core.header.ContentDisposition
>>>> com.sun.jersey.core.header.FormDataContentDisposition
>>>>
>>>> that can used by jersey-multipart for processing content
>>>> disposition headers (currently for reading, need to me modified
>>>> for writing). I need to add some tests. Perhaps they make sense
>>>> as part of multipart module? I did not create any general header
>>>> type because i am not sure if that is appropriate or not. Feel
>>>> free to modify/move/add as appropriate.
>>>>
>>> I saw the commit notices ... will take a look later today.
>>>
>>> Regarding a general purpose header class, you can tell I'm an
>>> architect at heart :-) ... I like to generalize things that look
>>> like they might be generally useful. When reviewing the HTTP and
>>> other specs while thinking about this, I was a bit surprised how
>>> often parameterized headers show up. And the fact that apps can
>>> construct their own headers sure makes me think there are use
>>> cases for parsing header values far beyond these two.
>>
>> Good point. What made me pause is one can consider three forms of
>> headers with parameters:
>>
>> 1) a token + parameters (e.g. AcceptLanguages: en;q=1.0)
>>
>> 2) a list of tokens delineated by separators + parameters
>> (e.g. Accept with a single value: application/xml;q=1.0 )
>>
>> 3) 1 or 2 as a comma separated list.
>>
>> I created a pull-based reader to make it easier to efficiently
>> parse (avoiding the creation of many String instances, indexof/
>> trims etc) in all three cases (it handles the cases of quoted
>> strings and comments). I guess what you are proposing is to have a
>> general header value that combines 1) and 2) ?
> Pretty much. You can think of 1) and 2) as being identical if you
> only consider comma and semicolon to be delimiters -- the slash in a
> media type is just another character.
>

How about i add such a general class utilizing HttpHeaderReader ?


> For 3) I consider that to be multiple header values, so you should
> get a list back when you parse it. In my implementation last night,
> I included a static method (HeaderValue.parseHeadervalues()) to take
> care of this scenario.

It will not work if there are commas in quoted strings of parameter
values. To do this correctly it is necessary process the string
linearly as a series of tokens then one can adapt the stream, using
HttpHeaderListAdapter as follows:

     public static <T> List<T> readList(ListElementCreator<T> c,
             String header) throws ParseException {
         List<T> l = new ArrayList<T>();
         HttpHeaderReader reader = new HttpHeaderReaderImpl(header);
         HttpHeaderListAdapter adapter = new
HttpHeaderListAdapter(reader);
         while(reader.hasNext()) {
             l.add(c.create(adapter));
             adapter.reset();
             if (reader.hasNext())
                 reader.next();
         }

         return l;
     }

which works for any comma separated header value, be it general or
more specific.

Paul.