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

org.restlet.data.Conditions 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 org.restlet.data;

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

import org.restlet.resource.Representation;
import org.restlet.util.DateUtils;

/**
 * Set of conditions applying to a request. This is equivalent to the HTTP
 * conditional headers.
 * 
 * @see If-Match
 * @see If-Modified-Since
 * @see If-None-Match
 * @see If-Unmodified-Since
 * 
 * @author Jerome Louvel
 */
public final class Conditions {
    /** The "if-match" condition */
    private volatile List match;

    /** The "if-modified-since" condition */
    private volatile Date modifiedSince;

    /** The "if-none-match" condition */
    private volatile List noneMatch;

    /** The "if-unmodified-since" condition */
    private volatile Date unmodifiedSince;

    /**
     * Constructor.
     */
    public Conditions() {
    }

    /**
     * Returns the modifiable list of tags for the "if-match" condition. Creates
     * a new instance if no one has been set.
     * 
     * @return The "if-match" condition.
     */
    public List getMatch() {
        // Lazy initialization with double-check.
        List m = this.match;
        if (m == null) {
            synchronized (this) {
                m = this.match;
                if (m == null) {
                    this.match = m = new ArrayList();
                }
            }
        }
        return m;
    }

    /**
     * Returns the "if-modified-since" condition.
     * 
     * @return The "if-modified-since" condition.
     */
    public Date getModifiedSince() {
        return this.modifiedSince;
    }

    /**
     * Returns the modifiable list of tags for the "if-none-match" condition.
     * Creates a new instance if no one has been set.
     * 
     * @return The "if-none-match" condition.
     */
    public List getNoneMatch() {
        // Lazy initialization with double-check.
        List n = this.noneMatch;
        if (n == null) {
            synchronized (this) {
                n = this.noneMatch;
                if (n == null) {
                    this.noneMatch = n = new ArrayList();
                }
            }
        }
        return n;
    }

    /**
     * Returns the conditional status of a variant using a given method.
     * 
     * @param method
     *            The request method.
     * @param representation
     *            The representation whose entity tag or date of modification
     *            will be tested
     * @return Null if the requested method can be performed, the status of the
     *         response otherwise.
     */
    public Status getStatus(Method method, Representation representation) {
        Status result = null;

        // Is the "if-Match" rule followed or not?
        if ((this.match != null) && !this.match.isEmpty()) {
            boolean matched = false;
            boolean failed = false;
            final boolean all = getMatch().get(0).equals(Tag.ALL);

            if (representation != null) {
                // If a tag exists
                if (!all && (representation.getTag() != null)) {
                    // Check if it matches one of the representations already
                    // cached by the client
                    Tag tag;

                    for (final Iterator iter = getMatch().iterator(); !matched
                            && iter.hasNext();) {
                        tag = iter.next();
                        matched = tag.equals(representation.getTag(), false);
                    }
                } else {
                    matched = all;
                }
            } else {
                // See
                // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.24
                // If none of the entity tags match, or if "*" is given and no
                // current entity exists, the server MUST NOT perform the
                // requested method
                failed = all;
            }

            failed = failed || !matched;

            if (failed) {
                result = Status.CLIENT_ERROR_PRECONDITION_FAILED;
            }
        }

        // Is the "if-None-Match" rule followed or not?
        if ((result == null) && (this.noneMatch != null)
                && !this.noneMatch.isEmpty()) {
            boolean matched = false;

            if (representation != null) {
                // If a tag exists
                if (representation.getTag() != null) {
                    // Check if it matches one of the representations
                    // already cached by the client
                    Tag tag;

                    for (final Iterator iter = getNoneMatch().iterator(); !matched
                            && iter.hasNext();) {
                        tag = iter.next();
                        matched = tag.equals(representation.getTag(),
                                (Method.GET.equals(method) || Method.HEAD
                                        .equals(method)));
                    }

                    // The current representation matches one of those already
                    // cached by the client
                    if (matched) {
                        // Check if the current representation has been updated
                        // since the "if-modified-since" date. In this case, the
                        // rule is followed.
                        final Date modifiedSince = getModifiedSince();
                        final boolean isModifiedSince = (modifiedSince != null)
                                && (DateUtils.after(new Date(), modifiedSince)
                                        || (representation
                                                .getModificationDate() == null) || DateUtils
                                        .after(modifiedSince, representation
                                                .getModificationDate()));
                        matched = !isModifiedSince;
                    }
                }
            } else {
                matched = getNoneMatch().get(0).equals(Tag.ALL);
            }

            if (matched) {
                if (Method.GET.equals(method) || Method.HEAD.equals(method)) {
                    result = Status.REDIRECTION_NOT_MODIFIED;
                } else {
                    result = Status.CLIENT_ERROR_PRECONDITION_FAILED;
                }
            }
        }

        // Is the "if-Modified-Since" rule followed or not?
        if ((result == null) && (getModifiedSince() != null)) {
            if (representation != null) {
                final Date modifiedSince = getModifiedSince();
                final boolean isModifiedSince = (DateUtils.after(new Date(),
                        modifiedSince)
                        || (representation.getModificationDate() == null) || DateUtils
                        .after(modifiedSince, representation
                                .getModificationDate()));

                if (!isModifiedSince) {
                    if (Method.GET.equals(method) || Method.HEAD.equals(method)) {
                        result = Status.REDIRECTION_NOT_MODIFIED;
                    } else {
                        result = Status.CLIENT_ERROR_PRECONDITION_FAILED;
                    }
                }
            }
        }

        // Is the "if-Unmodified-Since" rule followed or not?
        if ((result == null) && (getUnmodifiedSince() != null)) {
            if (representation != null) {
                final Date unModifiedSince = getUnmodifiedSince();
                final boolean isUnModifiedSince = ((unModifiedSince == null)
                        || (representation.getModificationDate() == null) || !DateUtils
                        .before(representation.getModificationDate(),
                                unModifiedSince));

                if (!isUnModifiedSince) {
                    result = Status.CLIENT_ERROR_PRECONDITION_FAILED;
                }
            }
        }

        return result;
    }

    /**
     * Returns the "if-unmodified-since" condition.
     * 
     * @return The "if-unmodified-since" condition.
     */
    public Date getUnmodifiedSince() {
        return this.unmodifiedSince;
    }

    /**
     * Indicates if there are some conditions set.
     * 
     * @return True if there are some conditions set.
     */
    public boolean hasSome() {
        return (((this.match != null) && !this.match.isEmpty())
                || ((this.noneMatch != null) && !this.noneMatch.isEmpty())
                || (getModifiedSince() != null) || (getUnmodifiedSince() != null));
    }

    /**
     * Sets the "if-match" condition.
     * 
     * @param tags
     *            The "if-match" condition.
     */
    public void setMatch(List tags) {
        this.match = tags;
    }

    /**
     * Sets the "if-modified-since" condition.
     * 
     * @param date
     *            The "if-modified-since" condition.
     */
    public void setModifiedSince(Date date) {
        this.modifiedSince = DateUtils.unmodifiable(date);
    }

    /**
     * Sets the "if-none-match" condition.
     * 
     * @param tags
     *            The "if-none-match" condition.
     */
    public void setNoneMatch(List tags) {
        this.noneMatch = tags;
    }

    /**
     * Sets the "if-unmodified-since" condition.
     * 
     * @param date
     *            The "if-unmodified-since" condition.
     */
    public void setUnmodifiedSince(Date date) {
        this.unmodifiedSince = DateUtils.unmodifiable(date);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy