Author: dhanji
Date: Tue Jan 6 04:48:44 2009
New Revision: 801
Added:
trunk/servlet/test/com/google/inject/servlet/InvalidScopeBindingTest.java
Modified:
trunk/servlet/src/com/google/inject/servlet/FilterDefinition.java
trunk/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java
trunk/servlet/src/com/google/inject/servlet/GuiceFilter.java
trunk/servlet/src/com/google/inject/servlet/ServletDefinition.java
trunk/servlet/src/com/google/inject/servlet/ServletScopes.java
trunk/servlet/test/com/google/inject/servlet/AllTests.java
trunk/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java
trunk/servlet/test/com/google/inject/servlet/FilterDispatchIntegrationTest.java
trunk/servlet/test/com/google/inject/servlet/FilterPipelineTest.java
trunk/servlet/test/com/google/inject/servlet/MultiModuleDispatchIntegrationTest.java
trunk/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java
trunk/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java
trunk/servlet/test/com/google/inject/servlet/ServletDispatchIntegrationTest.java
trunk/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java
trunk/servlet/test/com/google/inject/servlet/ServletTest.java
trunk/servlet/test/com/google/inject/servlet/VarargsFilterDispatchIntegrationTest.java
trunk/servlet/test/com/google/inject/servlet/VarargsServletDispatchIntegrationTest.java
Log:
Added invalid scope (non-singleton) error checking and tests. Should pretty
much be the last Guice Servlet 2.0 feature needed before release.
Modified: trunk/servlet/src/com/google/inject/servlet/FilterDefinition.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/FilterDefinition.java
(original)
+++ trunk/servlet/src/com/google/inject/servlet/FilterDefinition.java Tue
Jan 6 04:48:44 2009
@@ -18,6 +18,7 @@
import com.google.common.collect.Iterators;
import com.google.inject.Injector;
import com.google.inject.Key;
+import static com.google.inject.servlet.ServletScopes.isSingletonBinding;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
@@ -58,7 +59,12 @@
}
public void init(final ServletContext servletContext, Injector injector)
throws ServletException {
- //TODO validate that the filter is bound as a singleton, to match with
servlet spec idiom
+ // This absolutely must be a singleton, and so is only initialized
once.
+ if (!isSingletonBinding(injector.getBinding(filterKey))) {
+ throw new ServletException("Filters must be bound as singletons. "
+ + filterKey + " was not bound in singleton scope.");
+ }
+
Filter filter = injector.getInstance(filterKey);
this.filter.set(filter);
Modified:
trunk/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java
(original)
+++ trunk/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java
Tue Jan 6 04:48:44 2009
@@ -73,6 +73,7 @@
public void through(Class<? extends Filter> filterKey,
Map<String, String> contextParams) {
+
// Careful you don't accidentally make this method recursive, thank
you IntelliJ IDEA!
through(Key.get(filterKey), contextParams);
}
Modified: trunk/servlet/src/com/google/inject/servlet/GuiceFilter.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/GuiceFilter.java
(original)
+++ trunk/servlet/src/com/google/inject/servlet/GuiceFilter.java Tue Jan
6
04:48:44 2009
@@ -77,7 +77,7 @@
// Multiple injectors with Servlet pipelines?!
// We don't throw an exception in DEVELOPMENT stage, to allow for
legacy
- // tests that don't have a tearDown that calls
GuiceFilter#clearPipeline().
+ // tests that don't have a tearDown that calls GuiceFilter#reset().
if (GuiceFilter.pipeline instanceof ManagedFilterPipeline) {
if (Stage.PRODUCTION.equals(stage)) {
throw new RuntimeException(MULTIPLE_INJECTORS_ERROR);
@@ -91,8 +91,8 @@
}
//VisibleForTesting
- static void clearPipeline() {
- pipeline = null;
+ static void reset() {
+ pipeline = new DefaultFilterPipeline();
}
public void doFilter(ServletRequest servletRequest,
@@ -175,7 +175,7 @@
pipeline.destroyPipeline();
} finally {
- clearPipeline();
+ reset();
servletContext.clear();
}
}
Modified: trunk/servlet/src/com/google/inject/servlet/ServletDefinition.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/ServletDefinition.java
(original)
+++ trunk/servlet/src/com/google/inject/servlet/ServletDefinition.java Tue
Jan 6 04:48:44 2009
@@ -18,6 +18,7 @@
import com.google.common.collect.Iterators;
import com.google.inject.Injector;
import com.google.inject.Key;
+import static com.google.inject.servlet.ServletScopes.isSingletonBinding;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
@@ -61,7 +62,12 @@
}
public void init(final ServletContext servletContext, Injector injector)
throws ServletException {
- //TODO(dhanji): this absolutely must be a singleton, and so is only
initialized once
+ // This absolutely must be a singleton, and so is only initialized
once.
+ if (!isSingletonBinding(injector.getBinding(servletKey))) {
+ throw new ServletException("Servlets must be bound as singletons. "
+ + servletKey + " was not bound in singleton scope.");
+ }
+
HttpServlet httpServlet = injector.getInstance(servletKey);
this.httpServlet.set(httpServlet);
Modified: trunk/servlet/src/com/google/inject/servlet/ServletScopes.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/ServletScopes.java
(original)
+++ trunk/servlet/src/com/google/inject/servlet/ServletScopes.java Tue Jan
6 04:48:44 2009
@@ -16,9 +16,15 @@
package com.google.inject.servlet;
+import com.google.inject.Binding;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.Scope;
+import com.google.inject.Scopes;
+import com.google.inject.Singleton;
+import com.google.inject.spi.DefaultBindingScopingVisitor;
+import java.lang.annotation.Annotation;
+import java.util.concurrent.atomic.AtomicBoolean;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@@ -91,4 +97,36 @@
return "ServletScopes.SESSION";
}
};
+
+ static boolean isSingletonBinding(Binding<?> binding) {
+ final AtomicBoolean isSingleton = new AtomicBoolean(true);
+ binding.acceptScopingVisitor(new DefaultBindingScopingVisitor<Void>() {
+ @Override
+ public Void visitNoScoping() {
+ isSingleton.set(false);
+
+ return null;
+ }
+
+ @Override
+ public Void visitScopeAnnotation(Class<? extends Annotation>
scopeAnnotation) {
+ if (null != scopeAnnotation
&& !Singleton.class.equals(scopeAnnotation)) {
+ isSingleton.set(false);
+ }
+
+ return null;
+ }
+
+ @Override
+ public Void visitScope(Scope scope) {
+ if (null != scope && !Scopes.SINGLETON.equals(scope)) {
+ isSingleton.set(false);
+ }
+
+ return null;
+ }
+ });
+
+ return isSingleton.get();
+ }
}
Modified: trunk/servlet/test/com/google/inject/servlet/AllTests.java
==============================================================================
--- trunk/servlet/test/com/google/inject/servlet/AllTests.java (original)
+++ trunk/servlet/test/com/google/inject/servlet/AllTests.java Tue Jan 6
04:48:44 2009
@@ -39,6 +39,7 @@
suite.addTestSuite(ServletDefinitionPathsTest.class);
suite.addTestSuite(ServletPipelineRequestDispatcherTest.class);
suite.addTestSuite(ServletDispatchIntegrationTest.class);
+ suite.addTestSuite(InvalidScopeBindingTest.class);
// Varargs URL mapping tests.
suite.addTestSuite(VarargsFilterDispatchIntegrationTest.class);
Modified:
trunk/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java
==============================================================================
--- trunk/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java
(original)
+++ trunk/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java
Tue Jan 6 04:48:44 2009
@@ -1,16 +1,25 @@
package com.google.inject.servlet;
+import com.google.inject.Binding;
import com.google.inject.Injector;
import com.google.inject.Key;
-import static org.easymock.EasyMock.*;
-
-import javax.servlet.*;
-import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
import junit.framework.TestCase;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
/**
* Tests the lifecycle of the encapsulated {...@link FilterDefinition} class.
@@ -24,7 +33,13 @@
Injector injector = createMock(Injector.class);
final MockFilter mockFilter = new MockFilter();
-
expect(injector.getInstance(Key.get(Filter.class))).andReturn(mockFilter).anyTimes();
+
+ expect(injector.getBinding(Key.get(Filter.class)))
+ .andReturn(createMock(Binding.class));
+
+ expect(injector.getInstance(Key.get(Filter.class)))
+ .andReturn(mockFilter)
+ .anyTimes();
replay(injector);
@@ -70,7 +85,13 @@
HttpServletRequest request = createMock(HttpServletRequest.class);
final MockFilter mockFilter = new MockFilter();
-
expect(injector.getInstance(Key.get(Filter.class))).andReturn(mockFilter).anyTimes();
+
+ expect(injector.getBinding(Key.get(Filter.class)))
+ .andReturn(createMock(Binding.class));
+
+ expect(injector.getInstance(Key.get(Filter.class)))
+ .andReturn(mockFilter)
+ .anyTimes();
expect(request.getServletPath()).andReturn("/index.html");
@@ -118,7 +139,13 @@
//suppress rest of chain...
}
};
-
expect(injector.getInstance(Key.get(Filter.class))).andReturn(mockFilter).anyTimes();
+
+ expect(injector.getBinding(Key.get(Filter.class)))
+ .andReturn(createMock(Binding.class));
+
+ expect(injector.getInstance(Key.get(Filter.class)))
+ .andReturn(mockFilter)
+ .anyTimes();
expect(request.getServletPath()).andReturn("/index.html");
Modified:
trunk/servlet/test/com/google/inject/servlet/FilterDispatchIntegrationTest.java
==============================================================================
---
trunk/servlet/test/com/google/inject/servlet/FilterDispatchIntegrationTest.java
(original)
+++
trunk/servlet/test/com/google/inject/servlet/FilterDispatchIntegrationTest.java
Tue Jan 6 04:48:44 2009
@@ -39,7 +39,7 @@
doFilters = 0;
destroys = 0;
- GuiceFilter.clearPipeline();
+ GuiceFilter.reset();
}
Modified:
trunk/servlet/test/com/google/inject/servlet/FilterPipelineTest.java
==============================================================================
--- trunk/servlet/test/com/google/inject/servlet/FilterPipelineTest.java
(original)
+++ trunk/servlet/test/com/google/inject/servlet/FilterPipelineTest.java
Tue Jan 6 04:48:44 2009
@@ -33,7 +33,7 @@
@Override
public final void setUp() {
- GuiceFilter.clearPipeline();
+ GuiceFilter.reset();
Guice.createInjector(new ServletModule() {
@@ -53,7 +53,7 @@
@Override
public final void tearDown() {
- GuiceFilter.clearPipeline();
+ GuiceFilter.reset();
}
public final void testDispatchThruGuiceFilter() throws ServletException,
IOException {
Added:
trunk/servlet/test/com/google/inject/servlet/InvalidScopeBindingTest.java
==============================================================================
--- (empty file)
+++
trunk/servlet/test/com/google/inject/servlet/InvalidScopeBindingTest.java
Tue Jan 6 04:48:44 2009
@@ -0,0 +1,98 @@
+package com.google.inject.servlet;
+
+import com.google.inject.Guice;
+import com.google.inject.Singleton;
+import com.google.inject.Scopes;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import junit.framework.TestCase;
+import static org.easymock.EasyMock.createMock;
+
+/**
+ * Ensures that an error is thrown if a Servlet or Filter is bound
+ * under any scope other than singleton, explicitly.
+ *
+ * @author [email protected]
+ */
+public class InvalidScopeBindingTest extends TestCase {
+
+ @Override
+ protected void tearDown() throws Exception {
+ GuiceFilter.reset();
+ }
+
+ public final void testServletInNonSingletonScopeThrowsServletException(){
+ GuiceFilter guiceFilter = new GuiceFilter();
+
+ Guice.createInjector(new ServletModule() {
+ @Override
+ protected void configureServlets() {
+ serve("/*").with(MyNonSingletonServlet.class);
+ }
+ });
+
+ ServletException se = null;
+ try {
+ guiceFilter.init(createMock(FilterConfig.class));
+ } catch (ServletException e) {
+ se = e;
+ } finally {
+ assertNotNull("Servlet exception was not thrown with wrong scope
binding", se);
+ }
+ }
+
+ public final void testFilterInNonSingletonScopeThrowsServletException(){
+ GuiceFilter guiceFilter = new GuiceFilter();
+
+ Guice.createInjector(new ServletModule() {
+ @Override
+ protected void configureServlets() {
+ filter("/*").through(MyNonSingletonFilter.class);
+ }
+ });
+
+ ServletException se = null;
+ try {
+ guiceFilter.init(createMock(FilterConfig.class));
+ } catch (ServletException e) {
+ se = e;
+ } finally {
+ assertNotNull("Servlet exception was not thrown with wrong scope
binding", se);
+ }
+ }
+
+ public final void testHappyCaseFilter(){
+ GuiceFilter guiceFilter = new GuiceFilter();
+
+ Guice.createInjector(new ServletModule() {
+ @Override
+ protected void configureServlets() {
+ // Annotated scoping variant.
+ filter("/*").through(MySingletonFilter.class);
+
+ // Explicit scoping variant.
+ bind(DummyFilterImpl.class).in(Scopes.SINGLETON);
+ filter("/*").through(DummyFilterImpl.class);
+ }
+ });
+
+ ServletException se = null;
+ try {
+ guiceFilter.init(createMock(FilterConfig.class));
+ } catch (ServletException e) {
+ se = e;
+ } finally {
+ assertNull("Servlet exception was thrown with correct scope
binding", se);
+ }
+ }
+
+ @RequestScoped
+ public static class MyNonSingletonServlet extends HttpServlet { }
+
+ @SessionScoped
+ public static class MyNonSingletonFilter extends DummyFilterImpl { }
+
+ @Singleton
+ public static class MySingletonFilter extends DummyFilterImpl { }
+}
Modified:
trunk/servlet/test/com/google/inject/servlet/MultiModuleDispatchIntegrationTest.java
==============================================================================
---
trunk/servlet/test/com/google/inject/servlet/MultiModuleDispatchIntegrationTest.java
(original)
+++
trunk/servlet/test/com/google/inject/servlet/MultiModuleDispatchIntegrationTest.java
Tue Jan 6 04:48:44 2009
@@ -38,7 +38,7 @@
doFilters = 0;
destroys = 0;
- GuiceFilter.clearPipeline();
+ GuiceFilter.reset();
}
Modified:
trunk/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java
==============================================================================
---
trunk/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java
(original)
+++
trunk/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java
Tue Jan 6 04:48:44 2009
@@ -16,21 +16,19 @@
package com.google.inject.servlet;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-
+import com.google.inject.Binding;
import com.google.inject.Injector;
import com.google.inject.Key;
-
-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;
+import junit.framework.TestCase;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
/**
* Ensures servlet spec compliance for CGI-style variables and general
@@ -61,8 +59,10 @@
HttpServletRequest request = createMock(HttpServletRequest.class);
HttpServletResponse response = createMock(HttpServletResponse.class);
- final boolean[] run = new boolean[1];
+ expect(injector.getBinding(Key.get(HttpServlet.class)))
+ .andReturn(createMock(Binding.class));
+ final boolean[] run = new boolean[1];
//get an instance of this servlet
expect(injector.getInstance(Key.get(HttpServlet.class)))
.andReturn(new HttpServlet() {
@@ -125,8 +125,10 @@
HttpServletRequest request = createMock(HttpServletRequest.class);
HttpServletResponse response = createMock(HttpServletResponse.class);
- final boolean[] run = new boolean[1];
+ expect(injector.getBinding(Key.get(HttpServlet.class)))
+ .andReturn(createMock(Binding.class));
+ final boolean[] run = new boolean[1];
//get an instance of this servlet
expect(injector.getInstance(Key.get(HttpServlet.class)))
.andReturn(new HttpServlet() {
@@ -208,8 +210,10 @@
HttpServletRequest request = createMock(HttpServletRequest.class);
HttpServletResponse response = createMock(HttpServletResponse.class);
- final boolean[] run = new boolean[1];
+ expect(injector.getBinding(Key.get(HttpServlet.class)))
+ .andReturn(createMock(Binding.class));
+ final boolean[] run = new boolean[1];
//get an instance of this servlet
expect(injector.getInstance(Key.get(HttpServlet.class)))
.andReturn(new HttpServlet() {
Modified:
trunk/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java
==============================================================================
--- trunk/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java
(original)
+++ trunk/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java
Tue Jan 6 04:48:44 2009
@@ -22,6 +22,7 @@
import com.google.inject.Injector;
import com.google.inject.Key;
+import com.google.inject.Binding;
import junit.framework.TestCase;
import java.util.Enumeration;
@@ -42,6 +43,8 @@
public final void testServletInitAndConfig() throws ServletException {
Injector injector = createMock(Injector.class);
+ expect(injector.getBinding(Key.get(HttpServlet.class)))
+ .andReturn(createMock(Binding.class));
final HttpServlet mockServlet = new HttpServlet() {
};
expect(injector.getInstance(Key.get(HttpServlet.class)))
Modified:
trunk/servlet/test/com/google/inject/servlet/ServletDispatchIntegrationTest.java
==============================================================================
---
trunk/servlet/test/com/google/inject/servlet/ServletDispatchIntegrationTest.java
(original)
+++
trunk/servlet/test/com/google/inject/servlet/ServletDispatchIntegrationTest.java
Tue Jan 6 04:48:44 2009
@@ -52,7 +52,7 @@
destroys = 0;
doFilters = 0;
- GuiceFilter.clearPipeline();
+ GuiceFilter.reset();
}
public final void testDispatchRequestToManagedPipelineServlets()
Modified:
trunk/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java
==============================================================================
---
trunk/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java
(original)
+++
trunk/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java
Tue Jan 6 04:48:44 2009
@@ -73,6 +73,8 @@
}
};
+ expect(injector.getBinding(Key.get(HttpServlet.class)))
+ .andReturn(createMock(Binding.class));
expect(injector.getInstance(HTTP_SERLVET_KEY))
.andReturn(mockServlet);
@@ -134,6 +136,9 @@
}
};
+ expect(injector.getBinding(Key.get(HttpServlet.class)))
+ .andReturn(createMock(Binding.class));
+
expect(injector.getInstance(HTTP_SERLVET_KEY))
.andReturn(mockServlet);
@@ -199,6 +204,9 @@
assertEquals("Wrong attrib returned - " + o, A_VALUE, o);
}
};
+
+ expect(injector.getBinding(Key.get(HttpServlet.class)))
+ .andReturn(createMock(Binding.class));
expect(injector.getInstance(Key.get(HttpServlet.class)))
.andReturn(mockServlet);
Modified: trunk/servlet/test/com/google/inject/servlet/ServletTest.java
==============================================================================
--- trunk/servlet/test/com/google/inject/servlet/ServletTest.java
(original)
+++ trunk/servlet/test/com/google/inject/servlet/ServletTest.java Tue Jan
6 04:48:44 2009
@@ -48,7 +48,7 @@
@Override
public void setUp() {
//we need to clear the reference to the pipeline every test =(
- GuiceFilter.clearPipeline();
+ GuiceFilter.reset();
}
public void testNewRequestObject()
Modified:
trunk/servlet/test/com/google/inject/servlet/VarargsFilterDispatchIntegrationTest.java
==============================================================================
---
trunk/servlet/test/com/google/inject/servlet/VarargsFilterDispatchIntegrationTest.java
(original)
+++
trunk/servlet/test/com/google/inject/servlet/VarargsFilterDispatchIntegrationTest.java
Tue Jan 6 04:48:44 2009
@@ -38,7 +38,7 @@
doFilters = 0;
destroys = 0;
- GuiceFilter.clearPipeline();
+ GuiceFilter.reset();
}
Modified:
trunk/servlet/test/com/google/inject/servlet/VarargsServletDispatchIntegrationTest.java
==============================================================================
---
trunk/servlet/test/com/google/inject/servlet/VarargsServletDispatchIntegrationTest.java
(original)
+++
trunk/servlet/test/com/google/inject/servlet/VarargsServletDispatchIntegrationTest.java
Tue Jan 6 04:48:44 2009
@@ -52,7 +52,7 @@
destroys = 0;
doFilters = 0;
- GuiceFilter.clearPipeline();
+ GuiceFilter.reset();
}
public final void testDispatchRequestToManagedPipelineServlets()
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"google-guice-dev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/google-guice-dev?hl=en
-~----------~----~----~----~------~----~------~--~---