Frank Gerhardt | 1 Mar 2008 11:18
Favicon

Re: First steps with Restlets in Equinox OSGi

Jerome Louvel schrieb:
> Hi Frank,
> 
> I'm not sure either how to achieve this, normally you would specify a
> context-param on your ServerServlet. Can't you specify that in OSGi Servlet
> service?

I got it. Instead of the extension point, I register the ServerSevlet 
with the HttpService. The registerServlet method allows me to pass in 
initparams and a http context.

public void start(BundleContext bundleContext) throws Exception {
   Hashtable initparams = new Hashtable();
   initparams.put(
      "org.restlet.application",
      FirstStepsApplication.class.getName());

   ServiceReference serviceReference = bundleContext
     .getServiceReference(HttpService.class.getName());

   if (serviceReference != null) {
	HttpService httpService;
	httpService = (HttpService) bundleContext
			.getService(serviceReference);

	if (httpService != null) {
		httpService.registerServlet(
                     "/alias", new ServerServlet(),
                     initparams, httpContext);
			}
(Continue reading)

Bruno Harbulot | 1 Mar 2008 16:55
Picon
Favicon

Re: Problems extracting a POST request's entity

Hi,

I've had a similar problem. Yesterday, just before 1.1M2 was released, I 
upgraded my application from Restlet 1.0.6 to 1.1M1. The POST requests 
stopped working.

I wrote a few tests to try to find where the problem was.
Using either the Apache HttpClient lib directly or Restlet, the clients 
were sending something like this:

    Request request = new Request(Method.POST, uri);
    request.setEntity("<test 
xmlns='http://example.org/test'>Hello</test>", MediaType.APPLICATION_XML);

On the server side, I was using something like this ('post' or 
'acceptRepresentation'):

public void acceptRepresentation(Representation entity) {
	try {
		System.out.println("entity.isAvailable():
		System.out.println("Document: "+entity.getText());
	} catch (Exception e) {
		throw new RuntimeException(e);
	}
}

This would just print:
   entity.isAvailable(): true
   Document:

(Continue reading)

cleverpig | 3 Mar 2008 11:33
Picon
Gravatar

Re: Restlet 1.1 M2 released

great!
I translated it in
Chinese:http://www.matrix.org.cn/resource/news/e2dda96c-e908-11dc-91da-b599c3ba16ef.html

On Fri, Feb 29, 2008 at 11:29 PM, Jerome Louvel <contact <at> noelios.com> wrote:
>
>  Hi again!
>
>  After two months of intense work we are finally releasing our next
>  milestone. In addition to the numerous bug fixes and API enhancements, we
>  would like to underline the following features:
>
>     * Addition of a HTTP server based on the Grizzly NIO framework. This
>  connector is the first to provide end-to-end NIO support, for example with
>  direct transfer from file to socket for static files.
>
>     * Support for HTTP DIGEST authentication (client and server side) and
>  refactoring of engine to support pluggable authentication.
>
>     * Addition of new Spring NRE extension providing even more integration
>  possibilities with the Servlets and Restlets at the same time. The existing
>  Spring API extension has also been extended and improved based on users
>  feed-back and contributions.
>
>     * Addition of JiBX extension, providing an efficient and flexible
>  alternative to JAXB for XML to Object serialization.
>
>     * Configuration of a Component based on a XML document is now directly
>  supported.
>
(Continue reading)

Bruno Harbulot | 3 Mar 2008 12:43
Picon
Favicon

Issue 376

Hello,

I'm interested in trying to contribute to solve issue 376:
http://restlet.tigris.org/issues/show_bug.cgi?id=376

There are in fact two sub-problems in this issue: (1) exposing 
javax.servlet.request.X509Certificate and (2) defining something that 
would provide the equivalent of 
javax.servlet.http.HttpServletRequest.getRemoteUser().

Is someone already working on it? I wouldn't mind having a go at this, 
but I'm not sure if this would conflict with some other work.

Best wishes,

Bruno.

Sergio Saugar | 3 Mar 2008 13:02
Picon
Favicon

Re: Problems extracting a POST request's entity

Hi,

   Thanks Mitch and Bruno for your answers.

   Bruno, I was using Restlet 1.1M1 and the problem was the same that
yours. The resolution of the POST method took a long time and the
returned entity's value was null (either using getText() or using streams).

   I returned to Restlet 1.07 and now the problem is gone.

Regards,

Sergio.

--

   Sergio Saugar García
   Área de Ciencias de la Computación e Inteligencia Artificial
   Departamento de Ciencias de la Computación
   Edificio Departamental II - Despacho 053
   Escuela Técnica Superior de Ingeniería Informática
   Universidad Rey Juan Carlos
   Móstoles (MADRID)

   Clave PGP:
   http://pgp.rediris.es:11371/pks/lookup?op=get&search=0xADFA3433

Rasmus Agerholm | 3 Mar 2008 13:25

1.1-M2 maven dependency error for artifact 'com.noelios.restlet.ext.spring'

Hi

The pom file for the 'com.noelios.restlet.ext.spring' artifact found at the 'maven.restlet.org' repository,
http://maven.restlet.org/com/noelios/restlet/com.noelios.restlet.ext.servlet/1.1-M2/com.noelios.restlet.ext.servlet-1.1-M2.pom
defines the 'com.noelios.restlet.ext.servlet' dependency like this:

      <dependency>
         <groupId>com.noelios.restlet.ext.servlet</groupId>
         <artifactId>com.noelios.restlet.ext.servlet</artifactId>
         <version>1.1-M</version>
      </dependency>

I believe the groupId should be 'com.noelios.restlet' and the version should be '1.1-M2', right?
The groupId issue also goes for the 1.1-SNAPSHOT pom.


Best Regards, and thanks for a very good framework :-)

Rasmus Agerholm

Jerome Louvel | 3 Mar 2008 14:52

RE: Issue 376


Hi Bruno,

Thanks for proposing to help on this front Bruno. I've reassigned the RFE to
you.

Note that in 1.1 M2, the Guard is automatically adding a Principal instance
to the request attributes upon successful authentication.

Best regards,
Jerome  

> -----Message d'origine-----
> De : news [mailto:news <at> ger.gmane.org] De la part de Bruno Harbulot
> Envoyé : lundi 3 mars 2008 12:43
> À : discuss <at> restlet.tigris.org
> Objet : Issue 376
> 
> Hello,
> 
> I'm interested in trying to contribute to solve issue 376:
> http://restlet.tigris.org/issues/show_bug.cgi?id=376
> 
> There are in fact two sub-problems in this issue: (1) exposing 
> javax.servlet.request.X509Certificate and (2) defining something that 
> would provide the equivalent of 
> javax.servlet.http.HttpServletRequest.getRemoteUser().
> 
> Is someone already working on it? I wouldn't mind having a go 
> at this, 
> but I'm not sure if this would conflict with some other work.
> 
> Best wishes,
> 
> Bruno.
> 

Peter Neubauer | 3 Mar 2008 15:10
Picon

Re: 1.1-M2 maven dependency error for artifact 'com.noelios.restlet.ext.spring'

Rasmus Agerholm <rasmus <at> agerholm.org> writes:

> 
> HiThe pom file for the 'com.noelios.restlet.ext.spring' artifact found at the
'maven.restlet.org' repository,
http://maven.restlet.org/com/noelios/restlet/com.noelios.restlet.ext.servlet/1.1-M2/com.noelios.restlet.ext.servlet-1.1-M2.pom
> defines the 'com.noelios.restlet.ext.servlet' dependency like this:     
<dependency>         <groupId>com.noelios.restlet.ext.servlet</groupId>        
<artifactId>com.noelios.restlet.ext.servlet</artifactId>
>          <version>1.1-M</version>      </dependency>I believe the groupId
should be 'com.noelios.restlet' and the version should be '1.1-M2', right?The
groupId issue also goes for the 1.1-SNAPSHOT pom.Best Regards, and thanks for a
very good framework Rasmus Agerholm
> 

Hi there,
another error in both 1.1-M2 and 1.1-SNAPSHOT like at
http://maven.restlet.org/org/restlet/org.restlet.ext.spring/1.1-SNAPSHOT/org.restlet.ext.spring-1.1-SNAPSHOT.pom
is the non-replaced spring framework dependency version variable
 <at> lib-spring-version <at> , resulting in non-valid deps in maven.

/peter 

<dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-core</artifactId>
         <version> <at> lib-spring-version <at> </version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
         <version> <at> lib-spring-version <at> </version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-beans</artifactId>
         <version> <at> lib-spring-version <at> </version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-web</artifactId>
         <version> <at> lib-spring-version <at> </version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-webmvc</artifactId>
         <version> <at> lib-spring-version <at> </version>
      </dependency>

Aaron Crow | 3 Mar 2008 20:43
Picon
Favicon

Understanding Restlet's Threading Model?

I'd like to understand the threading model used by my basic Restlet app. I 
have a standalone app that uses Application and Component, and attaches 
subclasses of Restlet to the router. I am using the reference implementation 
provided by noelios. (Many, many thanks to Jerome for all of this!)

So, what rules should I expect this app to follow as far as how many threads 
get created when requests come in, and how many threads are allowed to run 
concurrently?

I've looked at the behaviour empirically and I'm a little confused:

1) When I insert test code that sometimes has a handlers sleep before 
finishing the request, and I then manually hit that handler through my 
browser with multiple requests, I seem to be observing purely synchronous 
behaviour. I do see that new threads are created for each request, however I 
also see that all requests coming in are forced to wait if a previous 
request triggered the handler to sleep. Then when the sleep is done, all 
requests seem to complete synchronously. Shouldn't I expect that the 
sleeping request handler would not cause any non-sleeping handlers to block? 
Or I'm missing something obvious?

2) When I run load tests against the app, generating dozens or more of 
simultaneous requests, I *do* observe asynchronous processing of those 
requests. (I conclude this from the fact that file output from my handler to 
a specific file ends up interlaced, or if I try using locking I may get 
OverlappingFileLockException).

I've reviewed the docs on restlet.org and I haven't been able to find a 
basic overview of the strategy being used here. Many many thanks to anyone 
who can enlighten me or point me to relevant docs!

8-]

All the best,
Aaron

Stephan Koops | 3 Mar 2008 22:25
Picon

Re: HTML with REST

Hello,

as discussed two weeks ago, some browsers (e.g. Internet Explorer 7.0 and Firefox 2.0) sends as accepted media type XML with a higher quality than HTML. The consequence is, that a HTTP server sends XML instead of HTML, if it could produce XML.
For this problem I've created a Filter (named HtmlPreferer now), that will increase the qualities for HTML media types (text/html and application/xhtml+xml) higher than both XML types (text/xml and application/xml), if at least one of both is available in a request.

Now it is available in the JAX-RS extension. What do you think about make it available for all developers in the main project? I put the actual source and a test case as attachment.

Jerome or Thierry: If you want to integrate the class in the main package or where ever, use the file of the JAX-RS; perhaps I continue developing or something like this.

best regards
   Stephan

Rob Heittman schrieb:
This legacy browser behavior is frustrating in the extreme.  Why in heaven's name would a tool meant primarily for viewing HTML, request XML as a higher quality representation?  Just goes to show how uber-excited everybody was about XML once upon a time.  You know, because in the future, all web pages will someday be XML with a reference to an XSL stylesheet, not HTML.

Choosing a different MediaType for your XML, that the browser doesn't ask for, is the usual solution.

Another workable solution I have found -- if you are using XML and will get criticized for making up MIME types -- is to expose the browser-friendly HTML variant by itself on a distinct URI (e.g. person.html).  That's sloppy too, just in a different way.

Now, packaging your data with JSON instead of XML will avoid the issue altogether, without making up MIME types  =)

- R

On 2/18/08, Stephan Koops <Stephan.Koops <at> web.de> wrote:
if a browser requests to a REST server, some browsers (Firefox and IE
for example, Opera not) requests text/xml and application/xml with a
higher quality than text/html.
/*
 * Copyright 2005-2008 Noelios Consulting.
 * 
 * The contents of this file are subject to the terms of the Common Development
 * and Distribution License (the "License"). You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at
 * http://www.opensource.org/licenses/cddl1.txt See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL HEADER in each file and
 * include the License file at http://www.opensource.org/licenses/cddl1.txt If
 * applicable, add the following below this CDDL HEADER, with the fields
 * enclosed by brackets "[]" replaced with your own identifying information:
 * Portions Copyright [yyyy] [name of copyright owner]
 */
package org.restlet.ext.jaxrs;

import java.util.List;
import java.util.Map;

import org.restlet.Context;
import org.restlet.Filter;
import org.restlet.Restlet;
import org.restlet.data.MediaType;
import org.restlet.data.Preference;
import org.restlet.data.Request;
import org.restlet.data.Response;

/**
 * <p>
 * Some browsers (e.g. Internet Explorer 7.0 and Firefox 2.0) sends as accepted
 * media type XML with a higher quality than html. The consequence is, that a
 * HTTP server sends XML instead of HTML, if it could produce XML. To avoid
 * this, you can use this filter.
 * </p>
 * <p>
 * This Filter will increase the qualities for HTML media types (text/html and
 * application/xhtml+xml) higher than both XML types (text/xml and
 * application/xml), if at least one of both is available in a request. The
 * check is implemented in method { <at> link #shouldChangeToPrefereHtml(Request)}.
 * <br>
 * Requests that not are not effected.
 * </p>
 * <p>
 * You may alter the test if the filter should change the request by subclass
 * this Filter and overrider method { <at> link #shouldChangeToPrefereHtml(Request)}.
 * </p>
 * 
 *  <at> author Stephan Koops
 */
public class HtmlPreferer extends Filter {

    private static final int MT_PREF_APP_XHTML = 1;

    private static final int MT_PREF_APP_XML = 3;

    private static final int MT_PREF_TEXT_HTML = 0;

    private static final int MT_PREF_TEXT_XML = 2;

    private static final String MT_QUALITY_ARRAY = "org.restlet.HtmlPreferer.qualities";

    /**
     * Creates a new { <at> link HtmlPreferer}. You should use constructor
     * { <at> link #HtmlPreferer(Context)} or { <at> link #HtmlPreferer(Context, Restlet)}.
     */
     <at> Deprecated
    public HtmlPreferer() {
        super();
    }

    /**
     * Creates a new { <at> link HtmlPreferer}. You can give also the next restlet
     * by using constructor { <at> link #HtmlPreferer(Context, Restlet)}.
     * 
     *  <at> param context
     *                the context from the parent
     */
    public HtmlPreferer(Context context) {
        super(context);
    }

    /**
     * Creates a new { <at> link HtmlPreferer}.
     * 
     *  <at> param context
     *                the context from the parent
     *  <at> param next
     *                the { <at> link Restlet} to call after filtering.
     */
    public HtmlPreferer(Context context, Restlet next) {
        super(context, next);
    }

    /**
     * Allows filtering before processing by the next Restlet.
     * 
     *  <at> param request
     *                The request to filter.
     *  <at> param response
     *                The response to update.
     *  <at> return The continuation status, see
     *         { <at> link Filter#beforeHandle(Request, Response)}
     *  <at> see Filter#beforeHandle(Request, Response)
     */
     <at> Override
    protected int beforeHandle(Request request, Response response) {
        if (shouldChangeToPrefereHtml(request))
            prefereHtml(request);
        return super.beforeHandle(request, response);
    }

    /**
     * Returns the quality of accepted media type application/xhtml+xml, or
     * null, if not present in the given request.
     * 
     *  <at> param request
     *  <at> return the quality of accepted media type application/xhtml+xml, or
     *         null, if not present in the given request.
     *  <at> see #getHtmlMinQuality(Request)
     */
    protected Float getAppXhtmlQuality(Request request) {
        return getHtmlXmlMtQualities(request)[MT_PREF_APP_XHTML];
    }

    /**
     * Returns the quality of accepted media type app/xml, or null, if not
     * present in the given request.
     * 
     *  <at> param request
     *  <at> return the quality of accepted media type app/xml, or null, if not
     *         present in the given request.
     *  <at> see #getXmlMaxQuality(Request)
     */
    protected Float getAppXmlQuality(Request request) {
        return getHtmlXmlMtQualities(request)[MT_PREF_APP_XML];
    }

    /**
     * Returns the lowest quality of the HTML types (text/html and
     * application/xhtml+xml), or null, if not available.
     * 
     *  <at> param request
     *  <at> return the lowest quality of the HTML types (text/html and
     *         application/xhtml+xml), or null, if not available.
     *  <at> see #getTextHtmlQuality(Request)
     *  <at> see #getAppXhtmlQuality(Request)
     */
    protected Float getHtmlMinQuality(Request request) {
        Float xhtmlQuality = getAppXhtmlQuality(request);
        Float htmlQuality = getTextHtmlQuality(request);
        if (xhtmlQuality == null)
            return htmlQuality;
        if (htmlQuality == null)
            return xhtmlQuality;
        return Math.min(xhtmlQuality, htmlQuality);
    }

     <at> SuppressWarnings("unchecked")
    private Float[] getHtmlXmlMtQualities(Request request) {
        Float[] htmlXmlQualities;
        Map<String, Object> attributes = request.getAttributes();
        htmlXmlQualities = (Float[]) attributes.get(MT_QUALITY_ARRAY);
        if (htmlXmlQualities == null) {
            htmlXmlQualities = new Float[4];
            List<Preference<MediaType>> acceptedMediaTypes = request
                    .getClientInfo().getAcceptedMediaTypes();
            for (Preference<MediaType> accPref : acceptedMediaTypes) {
                MediaType accMediaType = accPref.getMetadata();
                if (accMediaType.equals(MediaType.TEXT_HTML, true))
                    htmlXmlQualities[MT_PREF_TEXT_HTML] = accPref.getQuality();
                if (accMediaType.equals(MediaType.TEXT_XML, true))
                    htmlXmlQualities[MT_PREF_TEXT_XML] = accPref.getQuality();
                if (accMediaType.equals(MediaType.APPLICATION_XHTML_XML, true))
                    htmlXmlQualities[MT_PREF_APP_XHTML] = accPref.getQuality();
                if (accMediaType.equals(MediaType.APPLICATION_XML, true))
                    htmlXmlQualities[MT_PREF_APP_XML] = accPref.getQuality();
            }
            attributes.put(MT_QUALITY_ARRAY, htmlXmlQualities);
        }
        return htmlXmlQualities;
    }

    /**
     * Returns the quality of accepted media type text/html, or null, if not
     * present in the given request.
     * 
     *  <at> param request
     *  <at> return the quality of accepted media type text/html, or null, if not
     *         present in the given request.
     *  <at> see #getHtmlMinQuality(Request)
     */
    protected Float getTextHtmlQuality(Request request) {
        return getHtmlXmlMtQualities(request)[MT_PREF_TEXT_HTML];
    }

    /**
     * Returns the quality of accepted media type text/xml, or null, if not
     * present in the given request.
     * 
     *  <at> param request
     *  <at> return the quality of accepted media type text/xml, or null, if not
     *         present in the given request.
     *  <at> see #getXmlMaxQuality(Request)
     */
    protected Float getTextXmlQuality(Request request) {
        return getHtmlXmlMtQualities(request)[MT_PREF_TEXT_XML];
    }

    /**
     * Returns the highest quality of the XML types (text/xml and
     * application/xml), or null, if not available.
     * 
     *  <at> param request
     *  <at> return the highest quality of the XML types (text/xml and
     *         application/xml), or null, if not available.
     *  <at> see #getAppXmlQuality(Request)
     *  <at> see #getTextXmlQuality(Request)
     */
    protected Float getXmlMaxQuality(Request request) {
        Float appXmlQuality = getAppXmlQuality(request);
        Float textXmlQuality = getTextXmlQuality(request);
        if (appXmlQuality == null)
            return textXmlQuality;
        if (textXmlQuality == null)
            return appXmlQuality;
        return Math.max(appXmlQuality, textXmlQuality);
    }

    /**
     * Alters the request, that HTML is prefered before XML.
     * 
     *  <at> param request
     *                the request to alter.
     */
    protected void prefereHtml(Request request) {
        Float xmlQualityO = getXmlMaxQuality(request);
        if (xmlQualityO == null)
            return;
        float xmlQuality = xmlQualityO;
        float htmlMinQuality;
        if (xmlQuality < 1) {
            htmlMinQuality = xmlQuality + 0.001f;
        } else {
            lowerWithQuality(request, xmlQuality);
            htmlMinQuality = 1;
        }
        htmlPrefsMin(request, htmlMinQuality);
    }

    /**
     * Lowers all accepted media type Preferences with the given quality to
     * 0.001 (littlest accuracy for HTML qualities). Also lowers recursive the
     * preferences with the goal quality.
     * 
     *  <at> param request
     *  <at> param quality
     */
    private void lowerWithQuality(Request request, float quality) {
        List<Preference<MediaType>> acceptedMediaTypes = request
                .getClientInfo().getAcceptedMediaTypes();
        float goalQuality = quality - 0.001f;
        boolean alreadyAvailable = false;
        for (Preference<MediaType> accPref : acceptedMediaTypes) {
            if (accPref.getQuality() == goalQuality) {
                alreadyAvailable = true;
                break;
            }
        }
        if (alreadyAvailable)
            lowerWithQuality(request, goalQuality);
        for (Preference<MediaType> accPref : acceptedMediaTypes) {
            if (accPref.getQuality() == quality)
                accPref.setQuality(goalQuality);
        }
    }

    /**
     * sets the quality of the preferences of the HTML media types (text/html
     * and app/xhtml) at least to the given quality.
     * 
     *  <at> param request
     *  <at> param htmlQuality
     */
    private void htmlPrefsMin(Request request, float htmlQuality) {
        for (Preference<MediaType> accPref : request.getClientInfo()
                .getAcceptedMediaTypes()) {
            MediaType accMediaType = accPref.getMetadata();
            if (accMediaType.equals(MediaType.APPLICATION_XHTML_XML, true)
                    || accMediaType.equals(MediaType.TEXT_HTML, true)) {
                if (accPref.getQuality() < htmlQuality)
                    accPref.setQuality(htmlQuality);
            }
        }
    }

    /**
     * This method checks, if HTML should be prefered for the given request. The
     * check may be overridden or complemented by override that method.
     * 
     *  <at> param request
     *                the request to check.
     *  <at> return true, if the { <at> link Request} should be altered, or false if not.
     */
    protected boolean shouldChangeToPrefereHtml(Request request) {
        Float htmlQuality = getHtmlMinQuality(request);
        Float xmlQuality = getXmlMaxQuality(request);
        if (htmlQuality == null || xmlQuality == null)
            return false;
        return xmlQuality >= htmlQuality;
    }
}
/*
 * Copyright 2005-2008 Noelios Consulting.
 * 
 * The contents of this file are subject to the terms of the Common Development
 * and Distribution License (the "License"). You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at
 * http://www.opensource.org/licenses/cddl1.txt See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL HEADER in each file and
 * include the License file at http://www.opensource.org/licenses/cddl1.txt If
 * applicable, add the following below this CDDL HEADER, with the fields
 * enclosed by brackets "[]" replaced with your own identifying information:
 * Portions Copyright [yyyy] [name of copyright owner]
 */
package org.restlet.test.jaxrs;

import java.util.List;

import org.restlet.Restlet;
import org.restlet.data.MediaType;
import org.restlet.data.Preference;
import org.restlet.data.Request;
import org.restlet.ext.jaxrs.HtmlPreferer;

import junit.framework.TestCase;

/**
 * This TextCase checks the { <at> link HtmlPreferer}.
 * 
 *  <at> author Stephan Koops
 */
public class HtmlPrefererTest extends TestCase {

    private static final HtmlPreferer HTML_PREFERER = new HtmlPreferer(null,
            new Restlet());

    /**
     *  <at> param accMediaTypes
     *  <at> param mediaType
     *  <at> param quality
     */
    private void addMediaTypePref(List<Preference<MediaType>> accMediaTypes,
            MediaType mediaType, float quality) {
        accMediaTypes.add(new Preference<MediaType>(mediaType, quality));
    }

    /**
     *  <at> param accMediaTypes
     *  <at> param q0
     *  <at> param q1
     *  <at> param q2
     *  <at> param q3
     *  <at> param q4
     */
    private void check(List<Preference<MediaType>> accMediaTypes, float q0,
            float q1, float q2, float q3, float q4) {
        assertEquals(5, accMediaTypes.size());
        Preference<MediaType> amt0 = accMediaTypes.get(0);
        Preference<MediaType> amt1 = accMediaTypes.get(1);
        Preference<MediaType> amt2 = accMediaTypes.get(2);
        Preference<MediaType> amt3 = accMediaTypes.get(3);
        Preference<MediaType> amt4 = accMediaTypes.get(4);
        assertEquals(q0, amt0.getQuality());
        assertEquals(q1, amt1.getQuality());
        assertEquals(q2, amt2.getQuality());
        assertEquals(q3, amt3.getQuality());
        assertEquals(q4, amt4.getQuality());
    }

    public void test1() {
        Request request = new Request();
        List<Preference<MediaType>> accMediaTypes = request.getClientInfo()
                .getAcceptedMediaTypes();
        addMediaTypePref(accMediaTypes, MediaType.APPLICATION_ALL, 0.2f);
        addMediaTypePref(accMediaTypes, MediaType.TEXT_HTML, 1f);
        addMediaTypePref(accMediaTypes, MediaType.APPLICATION_XHTML_XML, 0.9f);
        addMediaTypePref(accMediaTypes, MediaType.APPLICATION_XML, 0.8f);
        addMediaTypePref(accMediaTypes, MediaType.TEXT_XML, 0.7f);
        HTML_PREFERER.handle(request);
        check(accMediaTypes, 0.2f, 1f, 0.9f, 0.8f, 0.7f);
    }

    public void test2() {
        Request request = new Request();
        List<Preference<MediaType>> accMediaTypes = request.getClientInfo()
                .getAcceptedMediaTypes();
        addMediaTypePref(accMediaTypes, MediaType.APPLICATION_ALL, 0.2f);
        addMediaTypePref(accMediaTypes, MediaType.TEXT_HTML, 0.6f);
        addMediaTypePref(accMediaTypes, MediaType.APPLICATION_XHTML_XML, 0.9f);
        addMediaTypePref(accMediaTypes, MediaType.APPLICATION_XML, 0.8f);
        addMediaTypePref(accMediaTypes, MediaType.TEXT_XML, 0.7f);
        HTML_PREFERER.handle(request);
        check(accMediaTypes, 0.2f, 0.801f, 0.9f, 0.8f, 0.7f);
    }

    public void test3() {
        Request request = new Request();
        List<Preference<MediaType>> accMediaTypes = request.getClientInfo()
                .getAcceptedMediaTypes();
        addMediaTypePref(accMediaTypes, MediaType.APPLICATION_ALL, 0.2f);
        addMediaTypePref(accMediaTypes, MediaType.TEXT_HTML, 0.6f);
        addMediaTypePref(accMediaTypes, MediaType.APPLICATION_XHTML_XML, 1f);
        addMediaTypePref(accMediaTypes, MediaType.IMAGE_BMP, 0.8f);
        addMediaTypePref(accMediaTypes, MediaType.TEXT_PLAIN, 0.7f);
        HTML_PREFERER.handle(request);
        check(accMediaTypes, 0.2f, 0.6f, 1f, 0.8f, 0.7f);
    }

    public void test4() {
        Request request = new Request();
        List<Preference<MediaType>> accMediaTypes = request.getClientInfo()
                .getAcceptedMediaTypes();
        addMediaTypePref(accMediaTypes, MediaType.APPLICATION_ALL, 0.2f);
        addMediaTypePref(accMediaTypes, MediaType.TEXT_HTML, 0.6f);
        addMediaTypePref(accMediaTypes, MediaType.APPLICATION_XML, 1f);
        addMediaTypePref(accMediaTypes, MediaType.IMAGE_BMP, 0.999f);
        addMediaTypePref(accMediaTypes, MediaType.TEXT_PLAIN, 0.7f);
        HTML_PREFERER.handle(request);
        check(accMediaTypes, 0.2f, 1f, 0.999f, 0.998f, 0.7f);
    }
}

Gmane