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 :-).
>>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>>
>>
>