I for got to list one other use case. There are times when the order
in which the form data comes in is signification. For example:
a=123&b=234&c=345
could mean something different than
c=345&a=123&b=234

This is something I was never able to capture with the standard Servlet api.

On Thu, Nov 20, 2008 at 8:13 AM, Tom McGee <[EMAIL PROTECTED]> wrote:
> I'll add the code at the end of this email.
> So far what looks to work best is to have a provider that only handles
> cases where I have a class that impements MultivaluedMap and leave
> those cases where MultivaluedMap it's self is used to
> FormEncodingReaderProvider to handle.
>
> Right now the values that get passed into the MultivaluedMap from the
> html form are url encoded. A value of "This is a test" is encoded as
> "This+is+a+test", for example. I plan to add a helper to decode these.
> Also I want to add a helper to strip out cross site scripting attach
> strings from incoming form data. The last case I'm thinking about is
> putting validation helpers here.
>
> Here is the code:
> package org.sherpa.jaxrs;
>
> import java.io.ByteArrayOutputStream;
> import java.io.IOException;
> import java.io.InputStream;
> import java.io.OutputStream;
> import java.lang.annotation.Annotation;
> import java.lang.reflect.Type;
> import java.util.Arrays;
> import java.util.List;
>
> import javax.ws.rs.Consumes;
> import javax.ws.rs.WebApplicationException;
> import javax.ws.rs.core.MediaType;
> import javax.ws.rs.core.MultivaluedMap;
> import javax.ws.rs.ext.MessageBodyReader;
> import javax.ws.rs.ext.Provider;
>
>
> @Consumes("application/x-www-form-urlencoded")
> @Provider
> public class XxxSherpaFormEncodingReader implements MessageBodyReader<Object> 
> {
>
>        public boolean isReadable(Class<?> clazz, Type genericType,
>                        Annotation[] annotations, MediaType mt) {
>                return !clazz.isInterface() && 
> MultivaluedMap.class.isAssignableFrom(clazz);
>        }
>
>        public MultivaluedMap<String, String> readFrom(Class<Object> clazz,
>                        Type genericType, Annotation[] annotations, MediaType 
> type,
>                        MultivaluedMap<String, String> headers, InputStream is)
>                        throws IOException {
>                try {
>                        String charset = "UTF-8";
>                        ByteArrayOutputStream bos = new 
> ByteArrayOutputStream();
>                        copy(is, bos, 1024);
>                        String postBody = new String(bos.toByteArray(), 
> charset);
>                        MultivaluedMap<String, String> params = 
> makeResult(clazz);
>                        readParams(postBody, (MultivaluedMap<String, String>) 
> params);
>                        return params;
>                } catch (Exception e) {
>                        throw new WebApplicationException(e);
>                }
>        }
>
>        @SuppressWarnings("unchecked")
>        public MultivaluedMap<String, String> makeResult(Class<Object> clazz)
> throws InstantiationException, IllegalAccessException{
>                return (MultivaluedMap<String, String>) clazz.newInstance();
>        }
>
>        public static void copy(final InputStream input, final OutputStream 
> output,
>                        final int bufferSize) throws IOException {
>                final byte[] buffer = new byte[bufferSize];
>                int n = 0;
>                n = input.read(buffer);
>                while (-1 != n) {
>                        output.write(buffer, 0, n);
>                        n = input.read(buffer);
>                }
>        }
>
>        protected static void readParams(String body,
>                        MultivaluedMap<String, String> params) {
>                if((body != null) && (body.length() != 0)){
>                        List<String> parts = Arrays.asList(body.split("&"));
>                        for (String part : parts) {
>                                String[] keyValue = part.split("=");
>                                // Change to add blank string if key but not 
> value is specified
>                                if (keyValue.length == 2) {
>                                        params.add(keyValue[0], keyValue[1]);
>                                } else {
>                                        params.add(keyValue[0], "");
>                                }
>                        }
>                }
>        }
>
> }
>
>
> On Thu, Nov 20, 2008 at 3:06 AM, Sergey Beryozkin
> <[EMAIL PROTECTED]> wrote:
>> Hi Tom
>>
>>
>>> Rather than modify FormEncodingReaderProvider I made my own provider
>>> that handles classes that implement MultivalueMap.
>>> On the plus side
>>> there is no need to modify FormEncodingReaderProvider and I can use
>>> this provider in other jaxrs implementations.
>>> On the negative side I had to duplicate some of the code in
>>>  FormEncodingReaderProvider
>>> (which I just copied from it. thank you vary much!). I have included
>>> my new provider. You are welcome to use it any way you wish, but be
>>> warned that I have not tested it yet.
>>
>> The provider has not been included with this email, but I'd be interested in
>> looking at the code
>> you did to handle cases where specific MultivaluedMap implementations are
>> listed in signatures and possibly applying it to FormEncodingReaderProvider.
>> So if you could post it then it would be helpful
>>
>> Out of curiosity - why having a default provider impl (say be it a CXF JAXRS
>> one or a Jersey one) is not always sufficient for your case ? Do you have
>> some optimized MultivaluedMap impls ?
>>
>> Or some additional helper methods ? In this case it might make sense to
>> update FormEncodingReaderProvider
>>
>> Thanks, Sergey
>>
>>>
>>> On Wed, Nov 19, 2008 at 10:40 AM, Tom McGee <[EMAIL PROTECTED]>
>>> wrote:
>>>>
>>>> You may want to wait on that patch. I'm playing with it and have
>>>> already found a problem. If you have a class in your signature that
>>>> implements MultivaluedMap you get an exception thrown. If you want
>>>> only the option of using MultivaluedMap in the signature then leave
>>>> FormEncodingReaderProvider unchange. If you want to allow a class that
>>>> implements MultivaluedMap in the method signature then stay tuned ...
>>>> I'm working on it.
>>>>
>>>> On Wed, Nov 19, 2008 at 9:47 AM, Sergey Beryozkin
>>>> <[EMAIL PROTECTED]> wrote:
>>>>>
>>>>> Yea, agreed - but if are you using MultivaluedMap in your signature then
>>>>> it
>>>>> should work fine.
>>>>> BradO - if you're reading it - it's a perfect time for a patch :-),
>>>>> unless
>>>>> Tom does it first :-)
>>>>>
>>>>> Thanks, Sergey
>>>>>
>>>>>
>>>>> ----- Original Message ----- From: "Tom McGee"
>>>>> <[EMAIL PROTECTED]>
>>>>> To: <[email protected]>
>>>>> Sent: Wednesday, November 19, 2008 5:37 PM
>>>>> Subject: problem in FormEncodingReaderProvider or in my java knowledge
>>>>>
>>>>>
>>>>>> Line 47 of  org.apache.cxf.jaxrs.provider. FormEncodingReaderProvider
>>>>>> reads:
>>>>>>      return type.isAssignableFrom(MultivaluedMap.class);
>>>>>> I think maybe it should be:
>>>>>>      return MultivaluedMap.class.isAssignableFrom(type);
>>>>>> Or maybe I'm just showing my ignorance :-).
>>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>>
>>
>

Reply via email to