org.jasig.cas.services.web.RegisteredServiceThemeBasedViewResolver.java Source code

Java tutorial

Introduction

Here is the source code for org.jasig.cas.services.web.RegisteredServiceThemeBasedViewResolver.java

Source

/*
 * Licensed to Apereo under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Apereo licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a
 * copy of the License at the following location:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.jasig.cas.services.web;

import org.jasig.cas.authentication.principal.WebApplicationService;
import org.jasig.cas.services.RegisteredService;
import org.jasig.cas.services.ServicesManager;
import org.jasig.cas.web.support.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.view.AbstractUrlBasedView;
import org.springframework.web.servlet.view.InternalResourceView;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;

/**
 * {@link RegisteredServiceThemeBasedViewResolver} is an alternate Spring View Resolver that utilizes a service's
 * associated theme to selectively choose which set of UI views will be used to generate
 * the standard views (casLoginView.jsp, casLogoutView.jsp etc).
 *
 * <p>Views associated with a particular theme by default are expected to be found at:
 * {@link #DEFAULT_PATH_PREFIX}/<code>themeId/ui</code>. A starting point may be to
 * clone the default set of view pages into a new directory based on the theme id.</p>
 *
 * <p>Note: There also exists a {@link org.jasig.cas.services.web.ServiceThemeResolver}
 * that attempts to resolve the view name based on the service theme id. The difference
 * however is that {@link org.jasig.cas.services.web.ServiceThemeResolver} only decorates
 * the default view pages with additional tags and coloring, such as CSS and JS. The
 * component presented here on the other hand has the ability to load an entirely new
 * set of pages that are may be totally different from that of the default's. This
 * is specially useful in cases where the set of pages for a theme that are targetted
 * for a different type of audience are entirely different structurally that simply
 * using the {@link org.jasig.cas.services.web.ServiceThemeResolver} is not practical
 * to augment the default views. In such cases, new view pages may be required.</p>
 *
 * @author John Gasper
 * @author Misagh Moayyed
 * @since 4.1.0
 */
public final class RegisteredServiceThemeBasedViewResolver extends InternalResourceViewResolver {
    private static final Logger LOGGER = LoggerFactory.getLogger(RegisteredServiceThemeBasedViewResolver.class);
    private static final String DEFAULT_PATH_PREFIX = "/WEB-INF/view/jsp";

    /** The ServiceRegistry to look up the service. */
    private final ServicesManager servicesManager;

    private final String defaultThemeId;

    private String pathPrefix = DEFAULT_PATH_PREFIX;

    /**
     * The {@link RegisteredServiceThemeBasedViewResolver} constructor.
     * @param defaultThemeId the theme to apply if the service doesn't specific one or a service is not provided
     * @param servicesManager the serviceManager implementation
     * @see #setCache(boolean)
     */
    public RegisteredServiceThemeBasedViewResolver(final String defaultThemeId,
            final ServicesManager servicesManager) {
        super();
        super.setCache(false);

        this.defaultThemeId = defaultThemeId;
        this.servicesManager = servicesManager;
    }

    /**
     * Uses the viewName and the theme associated with the service.
     * being requested and returns the appropriate view.
     * @param viewName the name of the view to be resolved
     * @return a theme-based UrlBasedView
     * @throws Exception an exception
     */
    @Override
    protected AbstractUrlBasedView buildView(final String viewName) throws Exception {
        final RequestContext requestContext = RequestContextHolder.getRequestContext();
        final WebApplicationService service = WebUtils.getService(requestContext);
        final RegisteredService registeredService = this.servicesManager.findServiceBy(service);

        final String themeId = service != null && registeredService != null
                && registeredService.getAccessStrategy().isServiceAccessAllowed()
                && StringUtils.hasText(registeredService.getTheme()) ? registeredService.getTheme()
                        : defaultThemeId;

        final String themePrefix = String.format("%s/%s/ui/", pathPrefix, themeId);
        LOGGER.debug("Prefix {} set for service {} with theme {}", themePrefix, service, themeId);

        //Build up the view like the base classes do, but we need to forcefully set the prefix for each request.
        //From UrlBasedViewResolver.buildView
        final InternalResourceView view = (InternalResourceView) BeanUtils.instantiateClass(getViewClass());
        view.setUrl(themePrefix + viewName + getSuffix());
        final String contentType = getContentType();
        if (contentType != null) {
            view.setContentType(contentType);
        }
        view.setRequestContextAttribute(getRequestContextAttribute());
        view.setAttributesMap(getAttributesMap());

        //From InternalResourceViewResolver.buildView
        view.setAlwaysInclude(false);
        view.setExposeContextBeansAsAttributes(false);
        view.setPreventDispatchLoop(true);

        LOGGER.debug("View resolved: {}", view.getUrl());

        return view;
    }

    /**
     * setCache is not supported in the {@link RegisteredServiceThemeBasedViewResolver} because each
     * request must be independently evaluated.
     * @param cache a value indicating whether the view should cache results.
     */
    @Override
    public void setCache(final boolean cache) {
        LOGGER.warn("The {} does not support caching. Turned off caching forcefully.",
                this.getClass().getSimpleName());
        super.setCache(false);
    }

    /**
     * Sets path prefix. This is the location where
     * views are expected to be found. The default
     * prefix is {@link #DEFAULT_PATH_PREFIX}.
     *
     * @param pathPrefix the path prefix
     */
    public void setPathPrefix(final String pathPrefix) {
        this.pathPrefix = pathPrefix;
    }
}