Package com.noelios.restlet.application

Source Code of com.noelios.restlet.application.Encoder

/*
* Copyright 2005-2007 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]
*
* Portions Copyright 2006 Lars Heuer (heuer[at]semagia.com)
*/

package com.noelios.restlet.application;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.restlet.Context;
import org.restlet.Filter;
import org.restlet.data.ClientInfo;
import org.restlet.data.Encoding;
import org.restlet.data.MediaType;
import org.restlet.data.Preference;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.resource.Representation;

/**
* Filter compressing entities. The best encoding is automatically selected
* based on the preferences of the client and on the encoding supported by NRE:
* GZip, Zip and Deflate.<br/> If the {@link org.restlet.resource.Representation}
* has an unknown size, it will always be a candidate for encoding. Candidate
* representations need to respect media type criteria by the lists of accepted
* and ignored media types.
*
* @author Lars Heuer (heuer[at]semagia.com) <a
*         href="http://semagia.com/">Semagia</a>
* @author Jerome Louvel (contact@noelios.com) <a
*         href="http://www.noelios.com">Noelios Consulting</a>
*/
public class Encoder extends Filter {
    /**
     * Indicates if the encoding should always occur, regardless of the size.
     */
    public static final int ENCODE_ALL_SIZES = -1;

    /**
     * Indicates if the request entity should be encoded.
     */
    private boolean encodeRequest;

    /**
     * Indicates if the response entity should be encoded.
     */
    private boolean encodeResponse;

    /**
     * The minimal size necessary for encoding.
     */
    private long mininumSize;

    /**
     * The media types that should be encoded.
     */
    private List<MediaType> acceptedMediaTypes;

    /**
     * The media types that should be ignored.
     */
    private List<MediaType> ignoredMediaTypes;

    /**
     * Constructor using the default media types and with
     * {@link #ENCODE_ALL_SIZES} setting. This constructor will only encode
     * response entities after call handling.
     *
     * @param context
     *            The context.
     */
    public Encoder(Context context) {
        this(context, false, true, ENCODE_ALL_SIZES,
                getDefaultAcceptedMediaTypes(), getDefaultIgnoredMediaTypes());
    }

    /**
     * Constructor.
     *
     * @param context
     *            The context.
     * @param encodeInput
     *            Indicates if the request entities should be encoded.
     * @param encodeOutput
     *            Indicates if the response entities should be encoded.
     * @param minimumSize
     *            The minimal size of the representation where compression
     *            should be used.
     * @param acceptedMediaTypes
     *            The media types that should be encoded.
     * @param ignoredMediaTypes
     *            The media types that should be ignored.
     */
    public Encoder(Context context, boolean encodeInput,
            boolean encodeOutput, long minimumSize,
            List<MediaType> acceptedMediaTypes,
            List<MediaType> ignoredMediaTypes) {
        super(context);
        this.encodeRequest = encodeInput;
        this.encodeResponse = encodeOutput;
        this.mininumSize = minimumSize;
        this.acceptedMediaTypes = acceptedMediaTypes;
        this.ignoredMediaTypes = ignoredMediaTypes;
    }

    /**
     * Returns the list of default encoded media types. This can be overriden by
     * subclasses. By default, all media types are encoded (except those
     * explicitely ignored).
     *
     * @return The list of default encoded media types.
     */
    public static List<MediaType> getDefaultAcceptedMediaTypes() {
        List<MediaType> result = new ArrayList<MediaType>();
        result.add(MediaType.ALL);
        return result;
    }

    /**
     * Returns the list of default ignored media types. This can be overriden by
     * subclasses. By default, all archive, audio, image and video media types
     * are ignored.
     *
     * @return The list of default ignored media types.
     */
    public static List<MediaType> getDefaultIgnoredMediaTypes() {
        List<MediaType> result = Arrays.<MediaType> asList(
                MediaType.APPLICATION_CAB, MediaType.APPLICATION_GNU_ZIP,
                MediaType.APPLICATION_ZIP, MediaType.APPLICATION_GNU_TAR,
                MediaType.APPLICATION_JAVA_ARCHIVE,
                MediaType.APPLICATION_STUFFIT, MediaType.APPLICATION_TAR,
                MediaType.AUDIO_ALL, MediaType.IMAGE_ALL, MediaType.VIDEO_ALL);
        return result;
    }

    /**
     * Allows filtering before its handling by the target Restlet. Does nothing
     * by default.
     *
     * @param request
     *            The request to filter.
     * @param response
     *            The response to filter.
     */
    public void beforeHandle(Request request, Response response) {
        // Check if encoding of the request entity is needed
        if (isEncodeRequest() && canEncode(request.getEntity())) {
            request.setEntity(encode(request.getClientInfo(), request
                    .getEntity()));
        }
    }

    /**
     * Allows filtering after its handling by the target Restlet. Does nothing
     * by default.
     *
     * @param request
     *            The request to filter.
     * @param response
     *            The response to filter.
     */
    public void afterHandle(Request request, Response response) {
        // Check if encoding of the response entity is needed
        if (isEncodeResponse() && canEncode(response.getEntity())) {
            response.setEntity(encode(request.getClientInfo(), response
                    .getEntity()));
        }
    }

    /**
     * Indicates if a representation can be encoded.
     *
     * @param representation
     *            The representation to test.
     * @return True if the call can be encoded.
     */
    public boolean canEncode(Representation representation) {
        // Test the existence of the representation and that no existing
        // encoding applies
        boolean result = false;
        if(representation != null){
            boolean identity = true;
            for (Iterator<Encoding> iter = representation.getEncodings().iterator(); identity && iter.hasNext();) {
                identity = (iter.next().equals(Encoding.IDENTITY));
            }
            result = identity;
        }

        if (result) {
            // Test the size of the representation
            result = (getMinimumSize() == ENCODE_ALL_SIZES)
                    || (representation.getSize() == Representation.UNKNOWN_SIZE)
                    || (representation.getSize() >= getMinimumSize());
        }

        if (result) {
            // Test the acceptance of the media type
            MediaType mediaType = representation.getMediaType();
            boolean accepted = false;
            for (Iterator<MediaType> iter = getAcceptedMediaTypes().iterator(); !accepted
                    && iter.hasNext();) {
                accepted = iter.next().includes(mediaType);
            }

            result = accepted;
        }

        if (result) {
            // Test the rejection of the media type
            MediaType mediaType = representation.getMediaType();
            boolean rejected = false;
            for (Iterator<MediaType> iter = getIgnoredMediaTypes().iterator(); !rejected
                    && iter.hasNext();) {
                rejected = iter.next().includes(mediaType);
            }

            result = !rejected;
        }

        return result;
    }

    /**
     * Encodes a given representation if an encoding is supported by the client.
     *
     * @param client
     *            The client preferences to use.
     * @param representation
     *            The representation to encode.
     * @return The encoded representation or the original one if no encoding
     *         supported by the client.
     */
    public Representation encode(ClientInfo client,
            Representation representation) {
        Representation result = representation;
        Encoding bestEncoding = getBestEncoding(client);

        if (bestEncoding != null) {
            result = new EncodeRepresentation(bestEncoding, representation);
        }

        return result;
    }

    /**
     * Returns the best supported encoding for a given client.
     *
     * @param client
     *            The client preferences to use.
     * @return The best supported encoding for the given call.
     */
    public Encoding getBestEncoding(ClientInfo client) {
        Encoding bestEncoding = null;
        Encoding currentEncoding = null;
        Preference<Encoding> currentPref = null;
        float bestScore = 0F;

        for (Iterator<Encoding> iter = EncodeRepresentation
                .getSupportedEncodings().iterator(); iter.hasNext();) {
            currentEncoding = iter.next();

            for (Iterator<Preference<Encoding>> iter2 = client
                    .getAcceptedEncodings().iterator(); iter2.hasNext();) {
                currentPref = iter2.next();

                if (currentPref.getMetadata().equals(Encoding.ALL)
                        || currentPref.getMetadata().equals(currentEncoding)) {
                    // A match was found, compute its score
                    if (currentPref.getQuality() > bestScore) {
                        bestScore = currentPref.getQuality();
                        bestEncoding = currentEncoding;
                    }
                }
            }
        }

        return bestEncoding;
    }

    /**
     * Indicates if the request entity should be encoded.
     *
     * @return True if the request entity should be encoded.
     */
    public boolean isEncodeRequest() {
        return this.encodeRequest;
    }

    /**
     * Indicates if the request entity should be encoded.
     *
     * @param encodeRequest
     *            True if the request entity should be encoded.
     */
    public void setEncodeRequest(boolean encodeRequest) {
        this.encodeRequest = encodeRequest;
    }

    /**
     * Indicates if the response entity should be encoded.
     *
     * @return True if the response entity should be encoded.
     */
    public boolean isEncodeResponse() {
        return this.encodeResponse;
    }

    /**
     * Indicates if the response entity should be encoded.
     *
     * @param encodeResponse
     *            True if the response entity should be encoded.
     */
    public void setEncodeResponse(boolean encodeResponse) {
        this.encodeResponse = encodeResponse;
    }

    /**
     * Returns the minimum size a representation must have before compression is
     * done.
     *
     * @return The minimum size a representation must have before compression is
     *         done.
     */
    public long getMinimumSize() {
        return mininumSize;
    }

    /**
     * Sets the minimum size a representation must have before compression is
     * done.
     *
     * @param mininumSize
     *            The minimum size a representation must have before compression
     *            is done.
     */
    public void setMinimumSize(long mininumSize) {
        this.mininumSize = mininumSize;
    }

    /**
     * Returns the media types that should be encoded.
     *
     * @return The media types that should be encoded.
     */
    public List<MediaType> getAcceptedMediaTypes() {
        return this.acceptedMediaTypes;
    }

    /**
     * Returns the media types that should be ignored.
     *
     * @return The media types that should be ignored.
     */
    public List<MediaType> getIgnoredMediaTypes() {
        return this.ignoredMediaTypes;
    }

}
TOP

Related Classes of com.noelios.restlet.application.Encoder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.