blob: c89834fce408565da1e3967a5e0f950bf5304083 [file] [log] [blame]
/**
* Copyright (C) 2008 Google Inc.
*
* 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.google.inject.servlet;
import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import com.google.common.collect.Sets;
import com.google.inject.Binding;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.spi.BindingScopingVisitor;
import junit.framework.TestCase;
import java.io.IOException;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Ensures servlet spec compliance for CGI-style variables and general
* path/pattern matching.
*
* @author Dhanji R. Prasanna (dhanji@gmail com)
*/
public class ServletDefinitionPathsTest extends TestCase {
// Data-driven test.
public final void testServletPathMatching() throws IOException, ServletException {
servletPath("/index.html", "*.html", "/index.html");
servletPath("/somewhere/index.html", "*.html", "/somewhere/index.html");
servletPath("/somewhere/index.html", "/*", "");
servletPath("/index.html", "/*", "");
servletPath("/", "/*", "");
servletPath("//", "/*", "");
servletPath("/////", "/*", "");
servletPath("", "/*", "");
servletPath("/thing/index.html", "/thing/*", "/thing");
servletPath("/thing/wing/index.html", "/thing/*", "/thing");
}
private void servletPath(final String requestPath, String mapping,
final String expectedServletPath) throws IOException, ServletException {
Injector injector = createMock(Injector.class);
Binding binding = createMock(Binding.class);
HttpServletRequest request = createMock(HttpServletRequest.class);
HttpServletResponse response = createMock(HttpServletResponse.class);
expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
.andReturn(true);
expect(injector.getBinding(Key.get(HttpServlet.class)))
.andReturn(binding);
final boolean[] run = new boolean[1];
//get an instance of this servlet
expect(injector.getInstance(Key.get(HttpServlet.class)))
.andReturn(new HttpServlet() {
@Override
protected void service(HttpServletRequest servletRequest,
HttpServletResponse httpServletResponse) throws ServletException, IOException {
final String path = servletRequest.getServletPath();
assertEquals(String.format("expected [%s] but was [%s]", expectedServletPath, path),
expectedServletPath, path);
run[0] = true;
}
});
expect(request.getServletPath())
.andReturn(requestPath);
replay(injector, binding, request);
ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class),
UriPatternType.get(UriPatternType.SERVLET, mapping), new HashMap<String, String>(), null);
servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
servletDefinition.doService(request, response);
assertTrue("Servlet did not run!", run[0]);
verify(injector, binding, request);
}
// Data-driven test.
public final void testPathInfoWithServletStyleMatching() throws IOException, ServletException {
pathInfoWithServletStyleMatching("/path/index.html", "/path", "/*", "/index.html", "");
pathInfoWithServletStyleMatching("/path//hulaboo///index.html", "/path", "/*",
"/hulaboo/index.html", "");
pathInfoWithServletStyleMatching("/path/", "/path", "/*", "/", "");
pathInfoWithServletStyleMatching("/path////////", "/path", "/*", "/", "");
// a servlet mapping of /thing/*
pathInfoWithServletStyleMatching("/path/thing////////", "/path", "/thing/*", "/", "/thing");
pathInfoWithServletStyleMatching("/path/thing/stuff", "/path", "/thing/*", "/stuff", "/thing");
pathInfoWithServletStyleMatching("/path/thing/stuff.html", "/path", "/thing/*", "/stuff.html",
"/thing");
pathInfoWithServletStyleMatching("/path/thing", "/path", "/thing/*", null, "/thing");
// see external issue 372
pathInfoWithServletStyleMatching("/path/some/path/of.jsp", "/path", "/thing/*",
null, "/some/path/of.jsp");
// *.xx style mapping
pathInfoWithServletStyleMatching("/path/thing.thing", "/path", "*.thing", null, "/thing.thing");
pathInfoWithServletStyleMatching("/path///h.thing", "/path", "*.thing", null, "/h.thing");
pathInfoWithServletStyleMatching("/path///...//h.thing", "/path", "*.thing", null,
"/.../h.thing");
pathInfoWithServletStyleMatching("/path/my/h.thing", "/path", "*.thing", null, "/my/h.thing");
// Encoded URLs
pathInfoWithServletStyleMatching("/path/index%2B.html", "/path", "/*", "/index+.html", "");
pathInfoWithServletStyleMatching("/path/a%20file%20with%20spaces%20in%20name.html", "/path", "/*", "/a file with spaces in name.html", "");
pathInfoWithServletStyleMatching("/path/Tam%C3%A1s%20nem%20m%C3%A1s.html", "/path", "/*", "/Tamás nem más.html", "");
}
private void pathInfoWithServletStyleMatching(final String requestUri, final String contextPath,
String mapping, final String expectedPathInfo, final String servletPath)
throws IOException, ServletException {
Injector injector = createMock(Injector.class);
Binding binding = createMock(Binding.class);
HttpServletRequest request = createMock(HttpServletRequest.class);
HttpServletResponse response = createMock(HttpServletResponse.class);
expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
.andReturn(true);
expect(injector.getBinding(Key.get(HttpServlet.class)))
.andReturn(binding);
final boolean[] run = new boolean[1];
//get an instance of this servlet
expect(injector.getInstance(Key.get(HttpServlet.class)))
.andReturn(new HttpServlet() {
@Override
protected void service(HttpServletRequest servletRequest,
HttpServletResponse httpServletResponse) throws ServletException, IOException {
final String path = servletRequest.getPathInfo();
if (null == expectedPathInfo) {
assertNull(String.format("expected [%s] but was [%s]", expectedPathInfo, path),
path);
}
else {
assertEquals(String.format("expected [%s] but was [%s]", expectedPathInfo, path),
expectedPathInfo, path);
}
//assert memoizer
//noinspection StringEquality
assertSame("memo field did not work", path, servletRequest.getPathInfo());
run[0] = true;
}
});
expect(request.getRequestURI())
.andReturn(requestUri);
expect(request.getServletPath())
.andReturn(servletPath)
.anyTimes();
expect(request.getContextPath())
.andReturn(contextPath);
expect(request.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(null);
replay(injector, binding, request);
ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class),
UriPatternType.get(UriPatternType.SERVLET, mapping), new HashMap<String, String>(), null);
servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
servletDefinition.doService(request, response);
assertTrue("Servlet did not run!", run[0]);
verify(injector, binding, request);
}
// Data-driven test.
public final void testPathInfoWithRegexMatching() throws IOException, ServletException {
// first a mapping of /*
pathInfoWithRegexMatching("/path/index.html", "/path", "/(.)*", "/index.html", "");
pathInfoWithRegexMatching("/path//hulaboo///index.html", "/path", "/(.)*",
"/hulaboo/index.html", "");
pathInfoWithRegexMatching("/path/", "/path", "/(.)*", "/", "");
pathInfoWithRegexMatching("/path////////", "/path", "/(.)*", "/", "");
// a servlet mapping of /thing/*
pathInfoWithRegexMatching("/path/thing////////", "/path", "/thing/(.)*", "/", "/thing");
pathInfoWithRegexMatching("/path/thing/stuff", "/path", "/thing/(.)*", "/stuff", "/thing");
pathInfoWithRegexMatching("/path/thing/stuff.html", "/path", "/thing/(.)*", "/stuff.html",
"/thing");
pathInfoWithRegexMatching("/path/thing", "/path", "/thing/(.)*", null, "/thing");
// *.xx style mapping
pathInfoWithRegexMatching("/path/thing.thing", "/path", ".*\\.thing", null, "/thing.thing");
pathInfoWithRegexMatching("/path///h.thing", "/path", ".*\\.thing", null, "/h.thing");
pathInfoWithRegexMatching("/path///...//h.thing", "/path", ".*\\.thing", null,
"/.../h.thing");
pathInfoWithRegexMatching("/path/my/h.thing", "/path", ".*\\.thing", null, "/my/h.thing");
// path
pathInfoWithRegexMatching("/path/test.com/com.test.MyServletModule", "", "/path/[^/]+/(.*)",
"com.test.MyServletModule", "/path/test.com/com.test.MyServletModule");
// Encoded URLs
pathInfoWithRegexMatching("/path/index%2B.html", "/path", "/(.)*", "/index+.html", "");
pathInfoWithRegexMatching("/path/a%20file%20with%20spaces%20in%20name.html", "/path", "/(.)*", "/a file with spaces in name.html", "");
pathInfoWithRegexMatching("/path/Tam%C3%A1s%20nem%20m%C3%A1s.html", "/path", "/(.)*", "/Tamás nem más.html", "");
}
public final void pathInfoWithRegexMatching(final String requestUri, final String contextPath,
String mapping, final String expectedPathInfo, final String servletPath)
throws IOException, ServletException {
Injector injector = createMock(Injector.class);
Binding binding = createMock(Binding.class);
HttpServletRequest request = createMock(HttpServletRequest.class);
HttpServletResponse response = createMock(HttpServletResponse.class);
expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
.andReturn(true);
expect(injector.getBinding(Key.get(HttpServlet.class)))
.andReturn(binding);
final boolean[] run = new boolean[1];
//get an instance of this servlet
expect(injector.getInstance(Key.get(HttpServlet.class)))
.andReturn(new HttpServlet() {
@Override
protected void service(HttpServletRequest servletRequest,
HttpServletResponse httpServletResponse) throws ServletException, IOException {
final String path = servletRequest.getPathInfo();
if (null == expectedPathInfo) {
assertNull(String.format("expected [%s] but was [%s]", expectedPathInfo, path),
path);
}
else {
assertEquals(String.format("expected [%s] but was [%s]", expectedPathInfo, path),
expectedPathInfo, path);
}
//assert memoizer
//noinspection StringEquality
assertSame("memo field did not work", path, servletRequest.getPathInfo());
run[0] = true;
}
});
expect(request.getRequestURI())
.andReturn(requestUri);
expect(request.getServletPath())
.andReturn(servletPath)
.anyTimes();
expect(request.getContextPath())
.andReturn(contextPath);
expect(request.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(null);
replay(injector, binding, request);
ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class),
UriPatternType.get(UriPatternType.REGEX, mapping), new HashMap<String, String>(), null);
servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
servletDefinition.doService(request, response);
assertTrue("Servlet did not run!", run[0]);
verify(injector, binding, request);
}
}