org.springmodules.validation.valang.javascript.taglib.ValangRulesExportInterceptor.java Source code

Java tutorial

Introduction

Here is the source code for org.springmodules.validation.valang.javascript.taglib.ValangRulesExportInterceptor.java

Source

/*
 * Copyright 2002-20085 the original author or authors.
 * 
 * Licensed 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
 * 
 *      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.springmodules.validation.valang.javascript.taglib;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.support.AopUtils;
import org.springframework.validation.Validator;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.servlet.mvc.BaseCommandController;
import org.springmodules.validation.valang.ValangValidator;

/**
 * Spring MVC interceptor implementation that will automatically export Valang validation rules that are used by any of
 * the intercepted handlers into the the ModelAndView so that they are accessible to the custom tag
 * <code>ValangValidateTag</code>.
 * <p/>
 * <p>
 * Does nothing if the intercepted handler is neither an instance of <code>BaseCommandController</code>, nor a proxied
 * <code>BaseCommandController</code>.
 * </p>
 * <p>
 * This will also do nothing if the handler did not export a command object into the model. Obviously the rules will
 * only be picked up from all validators of type {@link ValangValidator}.
 * 
 * @author Oliver Hutchison
 * @author Uri Boness
 * @author Colin Yates
 * 
 * @see ValangValidateTag
 * @see ValangValidator
 */
public class ValangRulesExportInterceptor extends HandlerInterceptorAdapter {

    private static final Log logger = LogFactory.getLog(ValangRulesExportInterceptor.class);

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {

        BaseCommandController controller = retrieveBaseCommandControllerIfPossible(handler);
        if (controller == null) {
            if (logger.isDebugEnabled()) {
                logger.debug("Controller is of type " + controller.getClass() + " so ignoring");
            }
            return;
        }

        Map model = modelAndView.getModel();
        String commandName = controller.getCommandName();
        if (model == null || !model.containsKey(commandName)) {
            if (logger.isWarnEnabled()) {
                logger.debug("Handler '" + handler + "' did not export command object '"
                        + controller.getCommandName() + "'; no rules added to model");
            }
            return;
        }

        Validator[] validators = controller.getValidators();
        for (int i = 0; i < validators.length; i++) {
            if (!ValangValidator.class.isInstance(validators[i])) {
                continue;
            }

            if (logger.isDebugEnabled()) {
                logger.debug("Adding Valang rules from handler '" + handler + "' to model");
            }

            ValangValidator validator = (ValangValidator) validators[i];
            ValangJavaScriptTagUtils.addValangRulesToModel(commandName, validator.getRules(), model);
        }

    }

    /**
     * Convert the specified <code>handler</code> to a {@link BaseCommandController} if possible.
     * 
     * <p>
     * If the <code>handler</code> is type compatible with a <code>BaseCommandController</code> then it will simply be
     * cast.
     * </p>
     * <p>
     * If the <code>handler</code> is a Spring JDK (or CGLIB) proxy, then it will unravelled and returned (assuming the
     * target is a <code>BaseCommandController</code>.
     * </p>
     * If neither of the above strategies work, <code>null</code> will be returned.
     * 
     * @param handler
     *            the handler to convert to a <code>BaseCommandController</code>.
     * @return a <code>BaseCommandController</code> or <code>null</code> if <code>handler</code> cannot be converted.
     * @throws Exception
     */
    private BaseCommandController retrieveBaseCommandControllerIfPossible(Object handler) throws Exception {
        BaseCommandController baseCommandController = null;

        if (BaseCommandController.class.isAssignableFrom(handler.getClass())) {
            if (logger.isDebugEnabled()) {
                logger.debug("handler is type compatible, simply cast");
            }
            baseCommandController = (BaseCommandController) handler;
        } else if (AopUtils.isAopProxy(handler)) {
            if (logger.isDebugEnabled()) {
                logger.debug("handler is AOP proxy");
            }

            Advised advisedObject = (Advised) handler;
            Class proxiedClass = advisedObject.getTargetClass();
            Object target = advisedObject.getTargetSource().getTarget();

            // convert (if possible) the target.
            baseCommandController = retrieveBaseCommandControllerIfPossible(target);
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Cannot convert handler to BaseCommandController");
        }
        return baseCommandController;
    }
}