Skip to content

Commit 0c0e439

Browse files
committed
fix(spring): implement thread safety for ServletContext resolution & lookup
1 parent c70620e commit 0c0e439

File tree

4 files changed

+92
-47
lines changed

4 files changed

+92
-47
lines changed

integration-spring/src/main/java/org/ocpsoft/rewrite/spring/SpringServiceEnricher.java

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,25 @@
1919
import java.util.Collection;
2020

2121
import javax.servlet.ServletContext;
22-
import javax.servlet.ServletContextEvent;
2322

2423
import org.ocpsoft.common.spi.ServiceEnricher;
2524
import org.ocpsoft.logging.Logger;
26-
import org.ocpsoft.rewrite.servlet.spi.ContextListener;
2725
import org.springframework.web.context.support.SpringBeanAutowiringSupport;
2826

2927
/**
3028
* {@link ServiceEnricher} implementation for Spring.
3129
*
3230
* @author Christian Kaltepoth
3331
*/
34-
public class SpringServiceEnricher implements ServiceEnricher, ContextListener
32+
public class SpringServiceEnricher implements ServiceEnricher
3533
{
3634

3735
private final Logger log = Logger.getLogger(SpringServiceEnricher.class);
38-
private static ServletContext context;
3936

4037
@Override
4138
public <T> void enrich(final T service)
4239
{
40+
ServletContext context = SpringServletContextLoader.getCurrentServletContext();
4341
if (context != null) {
4442
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(service, context);
4543
}
@@ -58,22 +56,4 @@ public <T> Collection<T> produce(final Class<T> type)
5856
return new ArrayList<T>();
5957
}
6058

61-
@Override
62-
public void contextInitialized(ServletContextEvent event)
63-
{
64-
context = event.getServletContext();
65-
}
66-
67-
@Override
68-
public void contextDestroyed(ServletContextEvent event)
69-
{
70-
context = null;
71-
}
72-
73-
@Override
74-
public int priority()
75-
{
76-
return 0;
77-
}
78-
7959
}

integration-spring/src/main/java/org/ocpsoft/rewrite/spring/SpringServiceLocator.java

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,8 @@
2121
import java.util.Set;
2222

2323
import javax.servlet.ServletContext;
24-
import javax.servlet.ServletContextEvent;
2524

2625
import org.ocpsoft.common.spi.ServiceLocator;
27-
import org.ocpsoft.rewrite.servlet.spi.ContextListener;
2826
import org.springframework.web.context.ContextLoader;
2927
import org.springframework.web.context.WebApplicationContext;
3028
import org.springframework.web.context.support.WebApplicationContextUtils;
@@ -35,16 +33,15 @@
3533
* @author Christian Kaltepoth
3634
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
3735
*/
38-
public class SpringServiceLocator implements ServiceLocator, ContextListener
36+
public class SpringServiceLocator implements ServiceLocator
3937
{
40-
private static ServletContext servletContext;
41-
4238
@Override
4339
@SuppressWarnings("unchecked")
4440
public <T> Collection<Class<T>> locate(Class<T> clazz)
4541
{
4642
Set<Class<T>> result = new LinkedHashSet<Class<T>>();
4743

44+
ServletContext servletContext = SpringServletContextLoader.getCurrentServletContext();
4845
WebApplicationContext applicationContext = null;
4946
if (servletContext != null) {
5047
applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
@@ -69,22 +66,4 @@ public <T> Collection<Class<T>> locate(Class<T> clazz)
6966
return result;
7067
}
7168

72-
@Override
73-
public void contextInitialized(ServletContextEvent event)
74-
{
75-
servletContext = event.getServletContext();
76-
}
77-
78-
@Override
79-
public void contextDestroyed(ServletContextEvent event)
80-
{
81-
servletContext = null;
82-
}
83-
84-
@Override
85-
public int priority()
86-
{
87-
return 0;
88-
}
89-
9069
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright 2011 <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.ocpsoft.rewrite.spring;
17+
18+
import java.util.Map;
19+
import java.util.Map.Entry;
20+
import java.util.concurrent.ConcurrentHashMap;
21+
22+
import javax.servlet.ServletContext;
23+
import javax.servlet.ServletContextEvent;
24+
import javax.servlet.ServletRequestEvent;
25+
26+
import org.ocpsoft.rewrite.servlet.spi.ContextListener;
27+
import org.ocpsoft.rewrite.servlet.spi.RequestListener;
28+
29+
/**
30+
* Thread-safe {@link ServletContext} loader implementation for Spring.
31+
*
32+
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
33+
*/
34+
public class SpringServletContextLoader implements ContextListener, RequestListener
35+
{
36+
private static final Map<ClassLoader, ServletContext> contextMap = new ConcurrentHashMap<>(1);
37+
38+
@Override
39+
public void contextInitialized(ServletContextEvent event)
40+
{
41+
ServletContext servletContext = event.getServletContext();
42+
contextMap.put(Thread.currentThread().getContextClassLoader(), servletContext);
43+
}
44+
45+
@Override
46+
public void contextDestroyed(ServletContextEvent event)
47+
{
48+
removeContext(event.getServletContext());
49+
}
50+
51+
@Override
52+
public void requestInitialized(ServletRequestEvent event)
53+
{
54+
ServletContext servletContext = event.getServletContext();
55+
contextMap.put(Thread.currentThread().getContextClassLoader(), servletContext);
56+
}
57+
58+
@Override
59+
public void requestDestroyed(ServletRequestEvent event)
60+
{
61+
removeContext(event.getServletContext());
62+
63+
}
64+
65+
private static void removeContext(ServletContext context)
66+
{
67+
if (contextMap.containsValue(context)) {
68+
for (Entry<ClassLoader, ServletContext> entry : contextMap.entrySet()) {
69+
if (entry.getValue() == context) {
70+
contextMap.remove(entry.getKey());
71+
}
72+
}
73+
}
74+
}
75+
76+
public static ServletContext getCurrentServletContext()
77+
{
78+
return contextMap.get(Thread.currentThread().getContextClassLoader());
79+
}
80+
81+
@Override
82+
public int priority()
83+
{
84+
return 0;
85+
}
86+
87+
}
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
org.ocpsoft.rewrite.spring.SpringServiceEnricher
2-
org.ocpsoft.rewrite.spring.SpringServiceLocator
1+
org.ocpsoft.rewrite.spring.SpringServletContextLoader

0 commit comments

Comments
 (0)