com.quartercode.femtoweb.api.resolutions.View.java Source code

Java tutorial

Introduction

Here is the source code for com.quartercode.femtoweb.api.resolutions.View.java

Source

/*
 * This file is part of FemtoWeb.
 * Copyright (c) 2015 QuarterCode <http://quartercode.com/>
 *
 * FemtoWeb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * FemtoWeb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FemtoWeb. If not, see <http://www.gnu.org/licenses/>.
 */

package com.quartercode.femtoweb.api.resolutions;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.quartercode.femtoweb.api.Action;
import com.quartercode.femtoweb.api.Context;
import com.quartercode.femtoweb.util.RequestUtils;

/**
 * An {@link Action} which sends a set {@link Context#getDynamicAssetPath() dynamic resource} to the user and executes no further actions.
 * Internally, this action forwards the request to that resource (e.g. a JSP page).
 * Therefore, all {@link ServletRequest#setAttribute(String, Object) request attributes}, {@link HttpSession#setAttribute(String, Object) session attributes} etc.
 * are also forwarded to the resource.
 * If the forwarding target is a JSP page, that page can then access those attributes (e.g. through the expression language).
 *
 * @see Action
 */
public class View implements Action {

    private static final Logger LOGGER = LoggerFactory.getLogger(View.class);

    // Either "path" or "dir"&"action" is set
    private final String path;

    private final Class<? extends Action> dir;
    private final String name;

    /**
     * Creates a new view action which displays the dynamic resource located under the given path.
     * Note that the path is relative to the {@link Context#getDynamicAssetPath() dynamic asset path}.
     *
     * @param path The path to the resource which should be displayed to the user.
     */
    public View(String path) {

        Validate.notBlank(path, "Cannot forward to blank path");

        this.path = path;

        dir = null;
        name = null;
    }

    /**
     * Creates a new view action which displays the dynamic resource located under the path provided by the given components.
     * This method takes the {@link Context#getUri(Class) URI of the given action class} and replaces its last entry (the class name of the action) with the given name.
     * That means that the final path uses the URI "directory" of the given action and the given resource file name.
     * For example, calling this method with the {@link Action} class {@code test.package.SomeTestAction} and the file name {@code testForm.jsp} would result in the
     * dynamic resource path {@code /test/package/testForm.jsp}.<br>
     * <br>
     * Note that the final path is relative to the {@link Context#getDynamicAssetPath() dynamic asset path}.
     *
     * @param dir The action class whose URI "directory" should be used as the directory of the final file path.
     * @param name The name of the viewed file in the directory defined by the given action class.
     */
    public View(Class<? extends Action> dir, String name) {

        Validate.notNull(dir, "Cannot use null action as \"directory\" for the forwarding path");
        Validate.notBlank(name, "Cannot forward to a file with blank name");

        path = null;

        this.dir = dir;
        this.name = StringUtils.stripStart(name, "/");
    }

    @Override
    public Action execute(HttpServletRequest request, HttpServletResponse response, Context context)
            throws IOException, ServletException {

        // Generate the actual target path (depending on the invoked constructor, use the set path or combine the "directory" URI of the set action's URI with the set name)
        String actualPath;
        if (path != null) {
            actualPath = path;
        } else {
            String dirUri = StringUtils.substringBeforeLast(context.getUri(dir), "/");
            actualPath = dirUri + "/" + name;
        }

        // Add the path prefix to the directory containing dynamic content
        actualPath = context.getDynamicAssetPath() + "/" + StringUtils.stripStart(actualPath, "/");

        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Forwarding request to '{}' to '{}'", RequestUtils.getRequestUri(request), actualPath);
        }

        // Actually forward the request
        request.getRequestDispatcher(actualPath).forward(request, response);

        return null;
    }

}