Skip to content

Instantly share code, notes, and snippets.

@darrinholst
Created July 23, 2008 13:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darrinholst/1720 to your computer and use it in GitHub Desktop.
Save darrinholst/1720 to your computer and use it in GitHub Desktop.
package your.domain.routing;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import your.domain.handler.Handler;
public class FirstAvailableMatchRouter implements Router {
private List<Route> routes = new ArrayList<Route>();
public void setRoutes( List<Route> routes ) {
this.routes.clear();
this.routes.addAll( routes );
}
public Handler route( HttpServletRequest request ) {
String uri = request.getRequestURI().replaceFirst( request.getContextPath() + "/", "" );
for( Route route : routes ) {
if( route.matches( uri, request ) ) {
return route.getHandler();
}
}
return Router.NOT_FOUND;
}
}
package your.domain.routing;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import your.domain.WebTestCase;
import your.domain.rhigis.handler.Handler;
public class FirstAvailableMatchRouterTest extends WebTestCase {
private FirstAvailableMatchRouter router;
private Route route1;
private Route route2;
private Handler handler;
@Before
public void setup() {
route1 = mock( Route.class );
route2 = mock( Route.class );
handler = mock( Handler.class );
router = new FirstAvailableMatchRouter();
router.setRoutes( Arrays.asList( route1, route2 ) );
}
@Test
public void testMatchFoundOnFirstRoute() throws Exception {
expect( request.getRequestURI() ).andReturn( "/context-root/some/uri" );
expect( request.getContextPath() ).andReturn( "/context-root" );
expect( route1.matches( "some/uri", request ) ).andReturn( true );
expect( route1.getHandler() ).andReturn( handler );
replayWebMocks();
assertSame( handler, router.route( request ) );
verifyWebMocks();
}
@Test
public void testMatchFoundOnSecondRoute() throws Exception {
expect( request.getRequestURI() ).andReturn( "/context-root/some/uri" );
expect( request.getContextPath() ).andReturn( "/context-root" );
expect( route1.matches( "some/uri", request ) ).andReturn( false );
expect( route2.matches( "some/uri", request ) ).andReturn( true );
expect( route2.getHandler() ).andReturn( handler );
replayWebMocks();
assertSame( handler, router.route( request ) );
verifyWebMocks();
}
@Test
public void testNoMatchFound() throws Exception {
expect( request.getRequestURI() ).andReturn( "/context-root/some/uri" );
expect( request.getContextPath() ).andReturn( "/context-root" );
expect( route1.matches( "some/uri", request ) ).andReturn( false );
expect( route2.matches( "some/uri", request ) ).andReturn( false );
replayWebMocks();
assertSame( Router.NOT_FOUND, router.route( request ) );
verifyWebMocks();
}
}
package your.domain.handler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface Handler {
void doGet( HttpServletRequest request, HttpServletResponse response ) throws Exception;
void doPost( HttpServletRequest request, HttpServletResponse response ) throws Exception;
void doPut( HttpServletRequest request, HttpServletResponse response ) throws Exception;
void doDelete( HttpServletRequest request, HttpServletResponse response ) throws Exception;
}
package your.domain.routing;
import javax.servlet.http.HttpServletRequest;
import your.domain.handler.Handler;
public interface Route {
Handler getHandler();
boolean matches( String uri, HttpServletRequest request );
}
package your.domain.routing;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import your.domain.handler.Handler;
public class RouteImpl implements Route {
private static final String VARIABLE = "\\{(.+?)\\}";
private static final Pattern VARIABLE_PATTERN = Pattern.compile( VARIABLE );
private Handler handler;
private Pattern uriTemplate;
private final List<String> variables = new ArrayList<String>();
public RouteImpl() {
}
public RouteImpl( String uriTemplate, Handler handler ) {
setHandler( handler );
setTemplate( uriTemplate );
}
public void setTemplate( String uriTemplate ) {
this.uriTemplate = Pattern.compile( uriTemplate.replaceAll( VARIABLE, "(.+)" ) );
Matcher m = VARIABLE_PATTERN.matcher( uriTemplate );
while( m.find() ) {
variables.add( m.group( 1 ) );
}
}
public void setHandler( Handler handler ) {
this.handler = handler;
}
public Handler getHandler() {
return handler;
}
public boolean matches( String uri, HttpServletRequest request ) {
final Matcher matcher = uriTemplate.matcher( uri );
if( matcher.matches() ) {
for( int i = 0; i < variables.size(); i++ ) {
request.setAttribute( variables.get( i ), matcher.group( i + 1 ) );
}
return true;
}
return false;
}
}
package your.domain.routing;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import your.domain.WebTestCase;
import your.domain.rhigis.handler.Handler;
public class RouteImplTest extends WebTestCase {
private Handler handler;
@Before
public void setUp() {
super.setUp();
handler = mock( Handler.class );
}
@Test
public void testMatches() throws Exception {
replayWebMocks();
assertTrue( new RouteImpl( "the/template", handler ).matches( "the/template", request ) );
verifyWebMocks();
}
@Test
public void testDoesNotMatch() throws Exception {
replayWebMocks();
assertFalse( new RouteImpl( "the/template", handler ).matches( "the/other/template", request ) );
verifyWebMocks();
}
@Test
public void testMatchesWithVariable() throws Exception {
expectToSetRequestAttribute( "v1", "value" );
replayWebMocks();
assertTrue( new RouteImpl( "the/template/{v1}", handler ).matches( "the/template/value", request ) );
verifyWebMocks();
}
@Test
public void testMatchesWithTwoVariable() throws Exception {
expectToSetRequestAttribute( "v1", "value1" );
expectToSetRequestAttribute( "v2", "value2" );
replayWebMocks();
assertTrue( new RouteImpl( "the/template/{v1}/and/{v2}", handler ).matches( "the/template/value1/and/value2", request ) );
verifyWebMocks();
}
@Test
public void testMatchesWithVariableAndStaticTextInTheSameNode() throws Exception {
expectToSetRequestAttribute( "policy-number", "12345" );
replayWebMocks();
assertTrue( new RouteImpl( "the/template/MP-{policy-number}", handler ).matches( "the/template/MP-12345", request ) );
verifyWebMocks();
}
@Test
public void testMatchesWithMultiplesOfVariableAndStaticTextInTheSameNode() throws Exception {
expectToSetRequestAttribute( "policy-symbol", "MP" );
expectToSetRequestAttribute( "policy-number", "12345" );
replayWebMocks();
assertTrue( new RouteImpl( "the/template/{policy-symbol}-{policy-number}", handler ).matches( "the/template/MP-12345", request ) );
verifyWebMocks();
}
}
package your.domain.routing;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import your.domain.handler.Handler;
public interface Router {
Handler NOT_FOUND = new Handler() {
public void doDelete( HttpServletRequest request, HttpServletResponse response ) throws Exception {
response.setStatus( HttpServletResponse.SC_NOT_FOUND );
}
public void doGet( HttpServletRequest request, HttpServletResponse response ) throws Exception {
response.setStatus( HttpServletResponse.SC_NOT_FOUND );
}
public void doPost( HttpServletRequest request, HttpServletResponse response ) throws Exception {
response.setStatus( HttpServletResponse.SC_NOT_FOUND );
}
public void doPut( HttpServletRequest request, HttpServletResponse response ) throws Exception {
response.setStatus( HttpServletResponse.SC_NOT_FOUND );
}
};
Handler route( HttpServletRequest request );
}
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="router" class="your.domain.routing.FirstAvailableMatchRouter">
<property name="routes">
<list>
<bean
class="your.domain.routing.RouteImpl"
p:template="acres/crop/{crop-year}/{division}/{policy-symbol}-{policy-number}"
p:handler-ref="crop-acres-handler" />
<bean
class="your.domain.routing.RouteImpl"
p:template="identify/high-risk/{x},{y}"
p:handler-ref="high-risk-identify-handler" />
<bean
class="your.domain.routing.RouteImpl"
p:template="identify/storm-spottings/{x},{y}"
p:handler-ref="storm-spottings-identify-handler" />
<bean
class="your.domain.routing.RouteImpl"
p:template="layer-filter/{layer}"
p:handler-ref="layer-filter-handler" />
<bean
class="your.domain.routing.RouteImpl"
p:template="policy/{crop-year}/{division}/{policy-symbol}-{policy-number}/image"
p:handler-ref="policy-image-handler" />
<bean
class="your.domain.routing.RouteImpl"
p:template="policy/{crop-year}/{division}/{policy-symbol}-{policy-number}/legend"
p:handler-ref="policy-legend-handler" />
<bean
class="your.domain.routing.RouteImpl"
p:template="policy/{crop-year}/{division}/{policy-symbol}-{policy-number}"
p:handler-ref="policy-handler" />
</list>
</property>
</bean>
<bean
id="crop-acres-handler"
class="your.domain.handler.CropAcresHandler"
parent="dao-factory-enabled" />
<bean
id="high-risk-identify-handler"
class="your.domain.handler.HighRiskIdentifyHandler"
parent="dao-factory-enabled"
p:spatial-query-ref="spatial-query" />
<bean
id="layer-filter-handler"
class="your.domain.handler.LayerFilterHandler" />
<bean
id="policy-handler"
class="your.domain.handler.PolicyHandler"
parent="dao-factory-enabled" />
<bean
id="policy-image-handler"
class="your.domain.handler.PolicyImageHandler"
p:mapFactory-ref="pocket-booklet-map-factory" />
<bean
id="policy-legend-handler"
class="your.domain.handler.PolicyLegendHandler"
parent="dao-factory-enabled" />
<bean
id="storm-spottings-identify-handler"
class="your.domain.handler.StormSpotterIdentifyHandler"
p:spatial-query-ref="spatial-query"
p:shape-factory-ref="storm-spotting-shape-factory" />
</beans>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment