Redirector.java :  » Web-Services » restlet-1.0.8 » org » restlet » Java Open Source

Java Open Source » Web Services » restlet 1.0.8 
restlet 1.0.8 » org » restlet » Redirector.java
/*
 * 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]
 */

package org.restlet;

import java.util.logging.Level;

import org.restlet.data.Reference;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.resource.Representation;
import org.restlet.util.Template;

/**
 * Rewrites URIs then redirects the call or the client to a new destination.
 * 
 * @see org.restlet.util.Template
 * @see <a href="http://www.restlet.org/documentation/1.0/tutorial#part10">Tutorial: URI rewriting
 *      and redirection</a>
 * @author Jerome Louvel (contact@noelios.com)
 */
public class Redirector extends Restlet {
    /**
     * In this mode, the client is permanently redirected to the URI generated
     * from the target URI pattern.<br/> See
     * org.restlet.data.Status.REDIRECTION_PERMANENT.
     */
    public static final int MODE_CLIENT_PERMANENT = 1;

    /**
     * In this mode, the client is simply redirected to the URI generated from
     * the target URI pattern.<br/> See
     * org.restlet.data.Status.REDIRECTION_FOUND.
     */
    public static final int MODE_CLIENT_FOUND = 2;

    /**
     * In this mode, the client is simply redirected to the URI generated from
     * the target URI pattern.<br/> See
     * org.restlet.data.Status.REDIRECTION_SEE_OTHER.
     */
    public static final int MODE_CLIENT_SEE_OTHER = 3;

    /**
     * In this mode, the client is temporarily redirected to the URI generated
     * from the target URI pattern.<br/> See
     * org.restlet.data.Status.REDIRECTION_TEMPORARY.
     */
    public static final int MODE_CLIENT_TEMPORARY = 4;

    /**
     * In this mode, the call is sent to the context's dispatcher. Once the
     * selected client connector has completed the request handling, the
     * response is normally returned to the client. In this case, you can view
     * the Redirector as acting as a transparent proxy Restlet.<br>
     * <br>
     * Remember to add the required connectors to the parent Component and to
     * declare them in the list of required connectors on the
     * Application.connectorService property.<br>
     * <br>
     * Note that in this mode, the headers of HTTP requests, stored in the
     * request's attributes, are removed before dispatching. Also, when a HTTP
     * response comes back the headers are also removed.
     */
    public static final int MODE_DISPATCHER = 5;

    /** The target URI pattern. */
    protected String targetTemplate;

    /** The redirection mode. */
    protected int mode;

    /**
     * Constructor for the dispatcher mode.
     * 
     * @param context
     *            The context.
     * @param targetTemplate
     *            The template to build the target URI.
     * @see org.restlet.util.Template
     */
    public Redirector(Context context, String targetTemplate) {
        this(context, targetTemplate, MODE_DISPATCHER);
    }

    /**
     * Constructor.
     * 
     * @param context
     *            The context.
     * @param targetPattern
     *            The pattern to build the target URI (using StringTemplate
     *            syntax and the CallModel for variables).
     * @param mode
     *            The redirection mode.
     */
    public Redirector(Context context, String targetPattern, int mode) {
        super(context);
        this.targetTemplate = targetPattern;
        this.mode = mode;
    }

    /**
     * Handles a call to a resource or a set of resources.
     * 
     * @param request
     *            The request to handle.
     * @param response
     *            The response to update.
     */
    public void handle(Request request, Response response) {
        // Generate the target reference
        Reference targetRef = getTargetRef(request, response);

        switch (this.mode) {
        case MODE_CLIENT_PERMANENT:
            getLogger().log(Level.INFO,
                    "Permanently redirecting client to: " + targetRef);
            response.redirectPermanent(targetRef);
            break;

        case MODE_CLIENT_FOUND:
            getLogger().log(Level.INFO,
                    "Redirecting client to found location: " + targetRef);
            response.setRedirectRef(targetRef);
            response.setStatus(Status.REDIRECTION_FOUND);
            break;

        case MODE_CLIENT_SEE_OTHER:
            getLogger().log(Level.INFO,
                    "Redirecting client to another location: " + targetRef);
            response.setRedirectRef(targetRef);
            response.setStatus(Status.REDIRECTION_SEE_OTHER);
            break;

        case MODE_CLIENT_TEMPORARY:
            getLogger().log(Level.INFO,
                    "Temporarily redirecting client to: " + targetRef);
            response.redirectTemporary(targetRef);
            break;

        case MODE_DISPATCHER:
            getLogger().log(Level.INFO,
                    "Redirecting via client connector to: " + targetRef);
            redirectDispatcher(targetRef, request, response);
            break;
        }
    }

    /**
     * Redirects a given call to a target reference. In the default
     * implementation, the request HTTP headers, stored in the request's
     * attributes, are removed before dispatching. After dispatching, the
     * response HTTP headers are also removed to prevent conflicts with the main
     * call.
     * 
     * @param targetRef
     *            The target reference with URI variables resolved.
     * @param request
     *            The request to handle.
     * @param response
     *            The response to update.
     */
    protected void redirectDispatcher(Reference targetRef, Request request,
            Response response) {
    // Save the base URI if it exists as we might need it for redirections
    Reference baseRef = request.getResourceRef().getBaseRef();

    // Update the request to cleanly go to the target URI
    request.setResourceRef(targetRef);
    request.getAttributes().remove("org.restlet.http.headers");
    getContext().getDispatcher().handle(request, response);

    // Allow for response rewriting and clean the headers
    response.setEntity(rewrite(response.getEntity()));
    response.getAttributes().remove("org.restlet.http.headers");

    // In case of redirection, we may have to rewrite the redirect URI
    if (response.getRedirectRef() != null) {
      Template rt = new Template(getLogger(), this.targetTemplate);
      int matched = rt.parse(response.getRedirectRef().toString(),
          request);

      if (matched > 0) {
        String remainingPart = (String) request.getAttributes().get(
            "rr");

        if (remainingPart != null) {
          response.setRedirectRef(baseRef.toString() + remainingPart);
        }
      }
    }
    }

    /**
     * Returns the target reference to redirect to.
     * 
     * @param request
     *            The request to handle.
     * @param response
     *            The response to update.
     * @return The target reference to redirect to.
     */
    protected Reference getTargetRef(Request request, Response response) {
        // Create the template
        Template rt = new Template(getLogger(), this.targetTemplate);

        // Return the formatted target URI
        return new Reference(rt.format(request, response));
    }

    /**
     * Optionnaly rewrites the response entity returned in the MODE_CONNECTOR
     * mode. By default, it just returns the initial entity without any
     * modification.
     * 
     * @param initialEntity
     *            The initial entity returned.
     * @return The rewritten entity.
     */
    protected Representation rewrite(Representation initialEntity) {
        return initialEntity;
    }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.