All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.noelios.restlet.http.PreferenceReader Maven / Gradle / Ivy

Go to download

This OSGi bundle wraps org.restlet, and com.noelios.restlet ${pkgVersion} jar files.

The newest version!
/**
 * Copyright 2005-2008 Noelios Technologies.
 * 
 * The contents of this file are subject to the terms of the following open
 * source licenses: LGPL 3.0 or LGPL 2.1 or CDDL 1.0 (the "Licenses"). You can
 * select the license that you prefer but you may not use this file except in
 * compliance with one of these Licenses.
 * 
 * You can obtain a copy of the LGPL 3.0 license at
 * http://www.gnu.org/licenses/lgpl-3.0.html
 * 
 * You can obtain a copy of the LGPL 2.1 license at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 * 
 * You can obtain a copy of the CDDL 1.0 license at
 * http://www.sun.com/cddl/cddl.html
 * 
 * See the Licenses for the specific language governing permissions and
 * limitations under the Licenses.
 * 
 * Alternatively, you can obtain a royaltee free commercial license with less
 * limitations, transferable or non-transferable, directly at
 * http://www.noelios.com/products/restlet-engine
 * 
 * Restlet is a registered trademark of Noelios Technologies.
 */

package com.noelios.restlet.http;

import java.io.IOException;
import java.util.Iterator;

import org.restlet.data.CharacterSet;
import org.restlet.data.Encoding;
import org.restlet.data.Form;
import org.restlet.data.Language;
import org.restlet.data.MediaType;
import org.restlet.data.Metadata;
import org.restlet.data.Parameter;
import org.restlet.data.Preference;
import org.restlet.util.Series;

/**
 * Preference header reader. Works for character sets, encodings, languages or
 * media types.
 * 
 * @author Jerome Louvel
 */
public class PreferenceReader extends HeaderReader {
    public static final int TYPE_CHARACTER_SET = 1;

    public static final int TYPE_ENCODING = 2;

    public static final int TYPE_LANGUAGE = 3;

    public static final int TYPE_MEDIA_TYPE = 4;

    /** The type of metadata read. */
    private volatile int type;

    /**
     * Constructor.
     * 
     * @param type
     *            The type of metadata read.
     * @param header
     *            The header to read.
     */
    public PreferenceReader(int type, String header) {
        super(header);
        this.type = type;
    }

    /**
     * Creates a new preference.
     * 
     * @param metadata
     *            The metadata name.
     * @param parameters
     *            The parameters list.
     * @return The new preference.
     */
    @SuppressWarnings("unchecked")
    protected Preference createPreference(CharSequence metadata,
            Series parameters) {
        Preference result;

        if (parameters == null) {
            result = new Preference();

            switch (this.type) {
            case TYPE_CHARACTER_SET:
                result.setMetadata((T) CharacterSet
                        .valueOf(metadata.toString()));
                break;

            case TYPE_ENCODING:
                result.setMetadata((T) Encoding.valueOf(metadata.toString()));
                break;

            case TYPE_LANGUAGE:
                result.setMetadata((T) Language.valueOf(metadata.toString()));
                break;

            case TYPE_MEDIA_TYPE:
                result.setMetadata((T) MediaType.valueOf(metadata.toString()));
                break;
            }
        } else {
            final Series mediaParams = extractMediaParams(parameters);
            final float quality = extractQuality(parameters);
            result = new Preference(null, quality, parameters);

            switch (this.type) {
            case TYPE_CHARACTER_SET:
                result.setMetadata((T) new CharacterSet(metadata.toString()));
                break;

            case TYPE_ENCODING:
                result.setMetadata((T) new Encoding(metadata.toString()));
                break;

            case TYPE_LANGUAGE:
                result.setMetadata((T) new Language(metadata.toString()));
                break;

            case TYPE_MEDIA_TYPE:
                result.setMetadata((T) new MediaType(metadata.toString(),
                        mediaParams));
                break;
            }
        }

        return result;
    }

    /**
     * Extract the media parameters. Only leave as the quality parameter if
     * found. Modifies the parameters list.
     * 
     * @param parameters
     *            All the preference parameters.
     * @return The media parameters.
     */
    protected Series extractMediaParams(Series parameters) {
        Series result = null;
        boolean qualityFound = false;
        Parameter param = null;

        if (parameters != null) {
            result = new Form();

            for (final Iterator iter = parameters.iterator(); !qualityFound
                    && iter.hasNext();) {
                param = iter.next();

                if (param.getName().equals("q")) {
                    qualityFound = true;
                } else {
                    iter.remove();
                    result.add(param);
                }
            }
        }

        return result;
    }

    /**
     * Extract the quality value. If the value is not found, 1 is returned.
     * 
     * @param parameters
     *            The preference parameters.
     * @return The quality value.
     */
    protected float extractQuality(Series parameters) {
        float result = 1F;
        boolean found = false;

        if (parameters != null) {
            Parameter param = null;
            for (final Iterator iter = parameters.iterator(); !found
                    && iter.hasNext();) {
                param = iter.next();
                if (param.getName().equals("q")) {
                    result = PreferenceUtils.parseQuality(param.getValue());
                    found = true;

                    // Remove the quality parameter as we will directly store it
                    // in the Preference object
                    iter.remove();
                }
            }
        }

        return result;
    }

    /**
     * Read the next preference.
     * 
     * @return The next preference.
     */
    public Preference readPreference() throws IOException {
        Preference result = null;

        boolean readingMetadata = true;
        boolean readingParamName = false;
        boolean readingParamValue = false;

        final StringBuilder metadataBuffer = new StringBuilder();
        StringBuilder paramNameBuffer = null;
        StringBuilder paramValueBuffer = null;

        Series parameters = null;

        final String nextValue = readValue();
        int nextIndex = 0;

        if (nextValue != null) {
            int nextChar = nextValue.charAt(nextIndex++);

            while (result == null) {
                if (readingMetadata) {
                    if (nextChar == -1) {
                        if (metadataBuffer.length() > 0) {
                            // End of metadata section
                            // No parameters detected
                            result = createPreference(metadataBuffer, null);
                            paramNameBuffer = new StringBuilder();
                        } else {
                            // Ignore empty metadata name
                        }
                    } else if (nextChar == ';') {
                        if (metadataBuffer.length() > 0) {
                            // End of metadata section
                            // Parameters detected
                            readingMetadata = false;
                            readingParamName = true;
                            paramNameBuffer = new StringBuilder();
                            parameters = new Form();
                        } else {
                            throw new IOException(
                                    "Empty metadata name detected.");
                        }
                    } else if (HttpUtils.isSpace(nextChar)) {
                        // Ignore spaces
                    } else if (HttpUtils.isText(nextChar)) {
                        metadataBuffer.append((char) nextChar);
                    } else {
                        throw new IOException(
                                "Control characters are not allowed within a metadata name.");
                    }
                } else if (readingParamName) {
                    if (nextChar == '=') {
                        if (paramNameBuffer.length() > 0) {
                            // End of parameter name section
                            readingParamName = false;
                            readingParamValue = true;
                            paramValueBuffer = new StringBuilder();
                        } else {
                            throw new IOException(
                                    "Empty parameter name detected.");
                        }
                    } else if (nextChar == -1) {
                        if (paramNameBuffer.length() > 0) {
                            // End of parameters section
                            parameters.add(HttpUtils.createParameter(
                                    paramNameBuffer, null));
                            result = createPreference(metadataBuffer,
                                    parameters);
                        } else {
                            throw new IOException(
                                    "Empty parameter name detected.");
                        }
                    } else if (nextChar == ';') {
                        // End of parameter
                        parameters.add(HttpUtils.createParameter(
                                paramNameBuffer, null));
                        paramNameBuffer = new StringBuilder();
                        readingParamName = true;
                        readingParamValue = false;
                    } else if (HttpUtils.isSpace(nextChar)
                            && (paramNameBuffer.length() == 0)) {
                        // Ignore white spaces
                    } else if (HttpUtils.isTokenChar(nextChar)) {
                        paramNameBuffer.append((char) nextChar);
                    } else {
                        throw new IOException(
                                "Separator and control characters are not allowed within a token.");
                    }
                } else if (readingParamValue) {
                    if (nextChar == -1) {
                        if (paramValueBuffer.length() > 0) {
                            // End of parameters section
                            parameters.add(HttpUtils.createParameter(
                                    paramNameBuffer, paramValueBuffer));
                            result = createPreference(metadataBuffer,
                                    parameters);
                        } else {
                            throw new IOException(
                                    "Empty parameter value detected");
                        }
                    } else if (nextChar == ';') {
                        // End of parameter
                        parameters.add(HttpUtils.createParameter(
                                paramNameBuffer, paramValueBuffer));
                        paramNameBuffer = new StringBuilder();
                        readingParamName = true;
                        readingParamValue = false;
                    } else if ((nextChar == '"')
                            && (paramValueBuffer.length() == 0)) {
                        // Parse the quoted string
                        boolean done = false;
                        boolean quotedPair = false;

                        while ((!done) && (nextChar != -1)) {
                            nextChar = (nextIndex < nextValue.length()) ? nextValue
                                    .charAt(nextIndex++)
                                    : -1;

                            if (quotedPair) {
                                // End of quoted pair (escape sequence)
                                if (HttpUtils.isText(nextChar)) {
                                    paramValueBuffer.append((char) nextChar);
                                    quotedPair = false;
                                } else {
                                    throw new IOException(
                                            "Invalid character detected in quoted string. Please check your value");
                                }
                            } else if (HttpUtils.isDoubleQuote(nextChar)) {
                                // End of quoted string
                                done = true;
                            } else if (nextChar == '\\') {
                                // Begin of quoted pair (escape sequence)
                                quotedPair = true;
                            } else if (HttpUtils.isText(nextChar)) {
                                paramValueBuffer.append((char) nextChar);
                            } else {
                                throw new IOException(
                                        "Invalid character detected in quoted string. Please check your value");
                            }
                        }
                    } else if (HttpUtils.isTokenChar(nextChar)) {
                        paramValueBuffer.append((char) nextChar);
                    } else {
                        throw new IOException(
                                "Separator and control characters are not allowed within a token");
                    }
                }

                nextChar = (nextIndex < nextValue.length()) ? nextValue
                        .charAt(nextIndex++) : -1;
            }
        }

        return result;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy