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

com.foreach.common.web.mapper.SubClassAllowingRequestHandlerMapping Maven / Gradle / Ivy

/*
 * Copyright 2014 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 com.foreach.common.web.mapper;

import org.springframework.beans.BeansException;
import org.springframework.util.Assert;
import org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * This is a partial copy from AbstractUrlHandlerMapping except for the registerHandler Method.
 * Compatible with Spring 3.1.1-RELEASE.
 *
 * Usage:
 * Initialize the class in the spring-dispatcher-servlet.xml
 * 	
 *
 * Note: the overwriting controller method must have the same signature as the parent!
 *
 * @deprecated because using this mapping would encourage having multiple singleton beans whereas only
 * one would be used.  Better solution is to ensure only one controller exists.
 */
@Deprecated
public class SubClassAllowingRequestHandlerMapping extends DefaultAnnotationHandlerMapping {
    private boolean lazyInitHandlers = false;

    private final Map handlerMap = new LinkedHashMap();

    /**
     * Set whether to lazily initialize handlers. Only applicable to
     * singleton handlers, as prototypes are always lazily initialized.
     * Default is "false", as eager initialization allows for more efficiency
     * through referencing the controller objects directly.
     * 

If you want to allow your controllers to be lazily initialized, * make them "lazy-init" and set this flag to true. Just making them * "lazy-init" will not work, as they are initialized through the * references from the handler mapping in this case. */ public void setLazyInitHandlers( boolean lazyInitHandlers ) { this.lazyInitHandlers = lazyInitHandlers; } /** * Look up a handler instance for the given URL path. *

Supports direct matches, e.g. a registered "/test" matches "/test", * and various Ant-style pattern matches, e.g. a registered "/t*" matches * both "/test" and "/team". For details, see the AntPathMatcher class. *

Looks for the most exact pattern, where most exact is defined as * the longest path pattern. * * @param urlPath URL the bean is mapped to * @param request current HTTP request (to expose the path within the mapping to) * @return the associated handler instance, or null if not found * @see #exposePathWithinMapping * @see org.springframework.util.AntPathMatcher */ protected Object lookupHandler( String urlPath, HttpServletRequest request ) throws Exception { // Direct match? Object handler = this.handlerMap.get( urlPath ); if( handler != null ) { // Bean name or resolved handler? if( handler instanceof String ) { String handlerName = ( String ) handler; handler = getApplicationContext().getBean( handlerName ); } validateHandler( handler, request ); return buildPathExposingHandler( handler, urlPath, urlPath, null ); } // Pattern match? List matchingPatterns = new ArrayList(); for( String registeredPattern : this.handlerMap.keySet() ) { if( getPathMatcher().match( registeredPattern, urlPath ) ) { matchingPatterns.add( registeredPattern ); } } String bestPatternMatch = null; Comparator patternComparator = getPathMatcher().getPatternComparator( urlPath ); if( !matchingPatterns.isEmpty() ) { Collections.sort( matchingPatterns, patternComparator ); if( logger.isDebugEnabled() ) { logger.debug( "Matching patterns for request [" + urlPath + "] are " + matchingPatterns ); } bestPatternMatch = matchingPatterns.get( 0 ); } if( bestPatternMatch != null ) { handler = this.handlerMap.get( bestPatternMatch ); // Bean name or resolved handler? if( handler instanceof String ) { String handlerName = ( String ) handler; handler = getApplicationContext().getBean( handlerName ); } validateHandler( handler, request ); String pathWithinMapping = getPathMatcher().extractPathWithinPattern( bestPatternMatch, urlPath ); // There might be multiple 'best patterns', let's make sure we have the correct URI template variables // for all of them Map uriTemplateVariables = new LinkedHashMap(); for( String matchingPattern : matchingPatterns ) { if( patternComparator.compare( bestPatternMatch, matchingPattern ) == 0 ) { uriTemplateVariables.putAll( getPathMatcher().extractUriTemplateVariables( matchingPattern, urlPath ) ); } } if( logger.isDebugEnabled() ) { logger.debug( "URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables ); } return buildPathExposingHandler( handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables ); } // No handler found... return null; } /** * Register the specified handler for the given URL path. * * @param urlPath the URL the bean should be mapped to * @param handler the handler instance or handler bean name String * (a bean name will automatically be resolved into the corresponding handler bean) * @throws org.springframework.beans.BeansException * if the handler couldn't be registered * @throws IllegalStateException if there is a conflicting handler registered */ protected void registerHandler( String urlPath, Object handler ) throws BeansException, IllegalStateException { Assert.notNull( urlPath, "URL path must not be null" ); Assert.notNull( handler, "Handler object must not be null" ); Object resolvedHandler = handler; // Eagerly resolve handler if referencing singleton via name. if( !this.lazyInitHandlers && handler instanceof String ) { String handlerName = ( String ) handler; if( getApplicationContext().isSingleton( handlerName ) ) { resolvedHandler = getApplicationContext().getBean( handlerName ); } } Object mappedHandler = this.handlerMap.get( urlPath ); if( mappedHandler != null ) { if( mappedHandler != resolvedHandler ) { // This is where the magic happens if( resolvedHandler.getClass().isAssignableFrom( mappedHandler.getClass() ) ) { // handler is superClass return; } else if( !mappedHandler.getClass().isAssignableFrom( resolvedHandler.getClass() ) ) { throw new IllegalStateException( "Cannot map " + getHandlerDescription( resolvedHandler ) + " to URL path [" + urlPath + "]: There is already " + getHandlerDescription( mappedHandler ) + " mapped and it is not a subclass." ); } } } if( urlPath.equals( "/" ) ) { // This is where the magic also happens if( getRootHandler() != null && resolvedHandler.getClass().isAssignableFrom( getRootHandler().getClass() ) ) { return; } else if( getRootHandler() != null && !getRootHandler().getClass().isAssignableFrom( resolvedHandler.getClass() ) ) { throw new IllegalStateException( "Cannot map " + getHandlerDescription( resolvedHandler ) + " to URL path [" + urlPath + "]: There is already " + getHandlerDescription( getRootHandler() ) + " mapped and it is not a subclass." ); } if( logger.isInfoEnabled() ) { logger.info( "Root mapping to " + getHandlerDescription( resolvedHandler ) ); } setRootHandler( resolvedHandler ); } else if( urlPath.equals( "/*" ) ) { if( logger.isInfoEnabled() ) { logger.info( "Default mapping to " + getHandlerDescription( resolvedHandler ) ); } setDefaultHandler( resolvedHandler ); } else { this.handlerMap.put( urlPath, resolvedHandler ); if( logger.isInfoEnabled() ) { logger.info( "Mapped URL path [" + urlPath + "] onto " + getHandlerDescription( resolvedHandler ) ); } } } private String getHandlerDescription( Object handler ) { return "handler " + (handler instanceof String ? "'" + handler + "'" : "of type [" + handler.getClass() + "]"); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy