src/main/java/org/eiichiro/bootleg/Route.java
public boolean apply(WebContext context) {
		Configuration configuration = context.configuration();
		
		if (endpoints == null) {
			synchronized (lock) {
				if (endpoints == null) {
					endpoints = new HashMap<String, Class<?>>();
					
					for (Class<?> endpoint : configuration.endpoints()) {
						String name = endpoint.getSimpleName().toLowerCase();
						
						if (endpoints.containsKey(name)) {
							logger.warn("Web endpoint class name is duplicated: ["
									+ endpoints.get(name) + "] is overwritten by ["
									+ endpoint + "]");
						}
						
						endpoints.put(name, endpoint);
					}
				}
			}
		}
		
		if (routing == null) {
			synchronized (lock) {
				if (routing == null) {
					routing = configuration.routing();
				}
			}
		}
		
		HttpServletRequest request = context.request();
		String uri = request.getRequestURI().substring((request.getContextPath()).length());
		
		try {
			if (routing.ignores(uri)) {
				logger.debug("URI [" + request.getRequestURI() + "] is ignored by routing configuration");
				context.chain().doFilter(request, context.response());
				return false;
			}
			
			Verb verb = null;
			
			try {
				verb = Verb.valueOf(request.getMethod());
			} catch (Exception e) {
				logger.warn("HTTP verb [" + request.getMethod() + "] is not supported");
			}
			
			List<Entry<URITemplate, Map<Verb, Method>>> route = routing.route(uri);
			
			for (Entry<URITemplate, Map<Verb, Method>> r : route) {
				Method method = r.getValue().get(verb);
				
				if (method == null) {
					method = r.getValue().get(null);
				}
				
				if (method != null) {
					context.method(method);
					request.setAttribute(Request.PATH, r.getKey().variables(uri));
					logger.debug("Web endpoint method is [" 
							+ method.getDeclaringClass().getName() 
							+ "#" + method.getName() + "]");
					return true;
				}
			}
			
			if (uri.endsWith("/")) {
				logger.debug("URI [" + request.getRequestURI() + "] is not correlated with any Web endpoint");
				context.chain().doFilter(request, context.response());
				return false;
			}
			
			String[] segments = uri.split("/");
			
			if (segments.length < 2) {
				logger.debug("URI [" + request.getRequestURI() + "] is not correlated with any Web endpoint");
				logger.debug("The requested URI pattern must end with " +
						"[/.../<simple-name-of-the-endpoint-class>/<endpoint-method>] or " + 
						"correlated with any Web endpoint in the routing configuration");
				context.chain().doFilter(request, context.response());
				return false;
			}
			
			Class<?> endpoint = endpoints.get(segments[segments.length - 2].toLowerCase());
			
			if (endpoint == null) {
				logger.warn("Web endpoint class is not found: Simple class name [" + segments[segments.length - 2] + "]");
				context.chain().doFilter(request, context.response());
				return false;
			}
			
			for (Method method : endpoint.getMethods()) {
				if (method.getName().compareToIgnoreCase(segments[segments.length - 1]) == 0) {
					context.method(method);
					logger.debug("Web endpoint method is ["
							+ method.getDeclaringClass().getName()
							+ "#" + method.getName() + "]");
					return true;
				}
			}
			
			logger.warn("Web endpoint method is not found: Method name [" + segments[segments.length - 1] + "]");
			context.chain().doFilter(request, context.response());
			return false;
		} catch (Exception e) {
			throw new UncheckedException(e);
		}
	}
public boolean apply(WebContext context) {
		Configuration configuration = context.configuration();
		
		if (endpoints == null) {
			synchronized (lock) {
				if (endpoints == null) {
					endpoints = new HashMap<String, Class<?>>();
					
					for (Class<?> endpoint : configuration.endpoints()) {
						String name = endpoint.getSimpleName().toLowerCase();
						
						if (endpoints.containsKey(name)) {
							logger.warn("Web endpoint class name is duplicated: ["
									+ endpoints.get(name) + "] is overwritten by ["
									+ endpoint + "]");
						}
						
						endpoints.put(name, endpoint);
					}
				}
			}
		}
		
		if (routing == null) {
			synchronized (lock) {
				if (routing == null) {
					routing = configuration.routing();
				}
			}
		}
		
		HttpServletRequest request = context.request();
		String uri = request.getRequestURI().substring((request.getContextPath()).length());
		
		try {
			if (routing.ignores(uri)) {
				logger.debug("URI [" + request.getRequestURI() + "] is ignored by routing configuration");
				context.chain().doFilter(request, context.response());
				return false;
			}
			
			Verb verb = null;
			
			try {
				verb = Verb.valueOf(request.getMethod());
			} catch (Exception e) {
				logger.warn("HTTP verb [" + request.getMethod() + "] is not supported");
			}
			
			List<Entry<URITemplate, Map<Verb, Method>>> route = routing.route(uri);
			
			for (Entry<URITemplate, Map<Verb, Method>> r : route) {
				Method method = r.getValue().get(verb);
				
				if (method == null) {
					method = r.getValue().get(null);
				}
				
				if (method != null) {
					context.method(method);
					request.setAttribute(Request.PATH, r.getKey().variables(uri));
					logger.debug("Web endpoint method is [" 
							+ method.getDeclaringClass().getName() 
							+ "#" + method.getName() + "]");
					return true;
				}
			}
			
			if (uri.endsWith("/")) {
				logger.debug("URI [" + request.getRequestURI() + "] is not correlated with any Web endpoint");
				context.chain().doFilter(request, context.response());
				return false;
			}
			
			String[] segments = uri.split("/");
			
			if (segments.length < 2) {
				logger.debug("URI [" + request.getRequestURI() + "] is not correlated with any Web endpoint");
				logger.debug("The requested URI pattern must end with " +
						"[/.../<simple-name-of-the-endpoint-class>/<endpoint-method>] or " + 
						"correlated with any Web endpoint in the routing configuration");
				context.chain().doFilter(request, context.response());
				return false;
			}
			
			Class<?> endpoint = endpoints.get(segments[segments.length - 2].toLowerCase());
			
			if (endpoint == null) {
				logger.warn("Web endpoint class is not found: Simple class name [" + segments[segments.length - 2] + "]");
				context.chain().doFilter(request, context.response());
				return false;
			}
			
			for (Method method : endpoint.getMethods()) {
				if (method.getName().compareToIgnoreCase(segments[segments.length - 1]) == 0) {
					context.method(method);
					logger.debug("Web endpoint method is ["
							+ method.getDeclaringClass().getName()
							+ "#" + method.getName() + "]");
					return true;
				}
			}
			
			logger.warn("Web endpoint method is not found: Method name [" + segments[segments.length - 1] + "]");
			context.chain().doFilter(request, context.response());
			return false;
		} catch (Exception e) {
			throw new UncheckedException(e);
		}
	}
public boolean apply ( WebContext context ) { Configuration configuration = context . configuration ( ) ; if ( endpoints == null ) { synchronized ( lock ) { if ( endpoints == null ) { endpoints = new HashMap < String , Class < ? > > ( ) ; for ( Class < ? > endpoint : configuration . endpoints ( ) ) { String name = endpoint . getSimpleName ( ) . toLowerCase ( ) ; if ( endpoints . containsKey ( name ) ) { logger . warn ( "Web endpoint class name is duplicated: [" + endpoints . get ( name ) + "] is overwritten by [" + endpoint + "]" ) ; } endpoints . put ( name , endpoint ) ; } } } } if ( routing == null ) { synchronized ( lock ) { if ( routing == null ) { routing = configuration . routing ( ) ; } } } HttpServletRequest request = context . request ( ) ; String uri = request . getRequestURI ( ) . substring ( ( request . getContextPath ( ) ) . length ( ) ) ; try { if ( routing . ignores ( uri ) ) { logger . debug ( "URI [" + request . getRequestURI ( ) + "] is ignored by routing configuration" ) ; context . chain ( ) . doFilter ( request , context . response ( ) ) ; return false ; } Verb verb = null ; try { verb = Verb . valueOf ( request . getMethod ( ) ) ; } catch ( Exception e ) { logger . warn ( "HTTP verb [" + request . getMethod ( ) + "] is not supported" ) ; } List < Entry < URITemplate , Map < Verb , Method > > > route = routing . route ( uri ) ; for ( Entry < URITemplate , Map < Verb , Method > > r : route ) { Method method = r . getValue ( ) . get ( verb ) ; if ( method == null ) { method = r . getValue ( ) . get ( null ) ; } if ( method != null ) { context . method ( method ) ; request . setAttribute ( Request . PATH , r . getKey ( ) . variables ( uri ) ) ; logger . debug ( "Web endpoint method is [" + method . getDeclaringClass ( ) . getName ( ) + "#" + method . getName ( ) + "]" ) ; return true ; } } if ( uri . endsWith ( "/" ) ) { logger . debug ( "URI [" + request . getRequestURI ( ) + "] is not correlated with any Web endpoint" ) ; context . chain ( ) . doFilter ( request , context . response ( ) ) ; return false ; } String [ ] segments = uri . split ( "/" ) ; if ( segments . length < 2 ) { logger . debug ( "URI [" + request . getRequestURI ( ) + "] is not correlated with any Web endpoint" ) ; logger . debug ( "The requested URI pattern must end with " + "[/.../<simple-name-of-the-endpoint-class>/<endpoint-method>] or " + "correlated with any Web endpoint in the routing configuration" ) ; context . chain ( ) . doFilter ( request , context . response ( ) ) ; return false ; } Class < ? > endpoint = endpoints . get ( segments [ segments . length - 2 ] . toLowerCase ( ) ) ; if ( endpoint == null ) { logger . warn ( "Web endpoint class is not found: Simple class name [" + segments [ segments . length - 2 ] + "]" ) ; context . chain ( ) . doFilter ( request , context . response ( ) ) ; return false ; } for ( Method method : endpoint . getMethods ( ) ) { if ( method . getName ( ) . compareToIgnoreCase ( segments [ segments . length - 1 ] ) == 0 ) { context . method ( method ) ; logger . debug ( "Web endpoint method is [" + method . getDeclaringClass ( ) . getName ( ) + "#" + method . getName ( ) + "]" ) ; return true ; } } logger . warn ( "Web endpoint method is not found: Method name [" + segments [ segments . length - 1 ] + "]" ) ; context . chain ( ) . doFilter ( request , context . response ( ) ) ; return false ; } catch ( Exception e ) { throw new UncheckedException ( e ) ; } }
Identifies Web endpoint method to be invoked from the HTTP request's URI.
This method processes the request as the following steps:
<ol>
<li>Gets Web endpoint classes from the {@code ServletContext}. If they
have not been set on the {@code ServletContext}, this method loads them
by invoking {@code Loader#load()} on the loader that the
{@code Configuration} returns.</li>
<li>Determines if the requested URI is ignored by {@link Routing}. If the
requested URI is matched to the pattern specified by {@code Routing#ignore(String...)},
the request is forwarded to the next filter chain.</li>
<li>Determines if the requested URI is matched to the URI template
specified by {@code Routing#add(String, Class, String)}. If the requested
URI is matched to the URI template, the corresponding Web endpoint method
is set to the current HTTP request processing context.</li>
<li>If the requested URI is not matched to any URI template, identifies
Web endpoint class and method according to the default URI convention
(URI ends with /.../&lt;simple-name-of-the-endpoint-class&gt;/&lt;endpoint-method&gt;).
</li>
<li>If any Web endpoint method is not identified, the request is
forwarded to the next filter chain.</li>
</ol>

@param context HTTP request processing context.
Identifies Web endpoint method to be invoked from the HTTP request s URI . This method processes the request as the following steps : <ol > <li > Gets Web endpoint classes from the { @code ServletContext } . If they have not been set on the { @code ServletContext } this method loads them by invoking { @code Loader#load () } on the loader that the { @code Configuration } returns . < / li > <li > Determines if the requested URI is ignored by { @link Routing } . If the requested URI is matched to the pattern specified by { @code Routing#ignore ( String ... ) } the request is forwarded to the next filter chain . < / li > <li > Determines if the requested URI is matched to the URI template specified by { @code Routing#add ( String Class String ) } . If the requested URI is matched to the URI template the corresponding Web endpoint method is set to the current HTTP request processing context . < / li > <li > If the requested URI is not matched to any URI template identifies Web endpoint class and method according to the default URI convention ( URI ends with / ... / &lt ; simple - name - of - the - endpoint - class&gt ; / &lt ; endpoint - method&gt ; ) . < / li > <li > If any Web endpoint method is not identified the request is forwarded to the next filter chain . < / li > < / ol >