Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
5ca5ec83
Commit
5ca5ec83
authored
Sep 21, 2019
by
Phillip Webb
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '2.1.x'
Closes gh-18299
parents
4cc7fef7
1ceb96f9
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
84 additions
and
5 deletions
+84
-5
ApplicationContextRequestMatcher.java
...ot/security/servlet/ApplicationContextRequestMatcher.java
+11
-5
ApplicationContextRequestMatcherTests.java
...curity/servlet/ApplicationContextRequestMatcherTests.java
+73
-0
No files found.
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/security/servlet/ApplicationContextRequestMatcher.java
View file @
5ca5ec83
...
...
@@ -16,7 +16,6 @@
package
org
.
springframework
.
boot
.
security
.
servlet
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
java.util.function.Supplier
;
import
javax.servlet.http.HttpServletRequest
;
...
...
@@ -44,7 +43,9 @@ public abstract class ApplicationContextRequestMatcher<C> implements RequestMatc
private
final
Class
<?
extends
C
>
contextClass
;
private
final
AtomicBoolean
initialized
=
new
AtomicBoolean
(
false
);
private
volatile
boolean
initialized
;
private
final
Object
initializeLock
=
new
Object
();
public
ApplicationContextRequestMatcher
(
Class
<?
extends
C
>
contextClass
)
{
Assert
.
notNull
(
contextClass
,
"Context class must not be null"
);
...
...
@@ -59,8 +60,13 @@ public abstract class ApplicationContextRequestMatcher<C> implements RequestMatc
return
false
;
}
Supplier
<
C
>
context
=
()
->
getContext
(
webApplicationContext
);
if
(
this
.
initialized
.
compareAndSet
(
false
,
true
))
{
initialized
(
context
);
if
(!
this
.
initialized
)
{
synchronized
(
this
.
initializeLock
)
{
if
(!
this
.
initialized
)
{
initialized
(
context
);
this
.
initialized
=
true
;
}
}
}
return
matches
(
request
,
context
);
}
...
...
@@ -89,7 +95,7 @@ public abstract class ApplicationContextRequestMatcher<C> implements RequestMatc
* Method that can be implemented by subclasses that wish to initialize items the
* first time that the matcher is called. This method will be called only once and
* only if {@link #ignoreApplicationContext(WebApplicationContext)} returns
* {@code
tru
e}. Note that the supplied context will be based on the
* {@code
fals
e}. Note that the supplied context will be based on the
* <strong>first</strong> request sent to the matcher.
* @param context a supplier for the initialized context (may throw an exception)
* @see #ignoreApplicationContext(WebApplicationContext)
...
...
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/security/servlet/ApplicationContextRequestMatcherTests.java
View file @
5ca5ec83
...
...
@@ -16,6 +16,10 @@
package
org
.
springframework
.
boot
.
security
.
servlet
;
import
java.lang.Thread.UncaughtExceptionHandler
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
java.util.function.Supplier
;
import
javax.servlet.http.HttpServletRequest
;
...
...
@@ -26,6 +30,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.mock.web.MockHttpServletRequest
;
import
org.springframework.mock.web.MockServletContext
;
import
org.springframework.util.ReflectionUtils
;
import
org.springframework.web.context.WebApplicationContext
;
import
org.springframework.web.context.support.StaticWebApplicationContext
;
...
...
@@ -105,6 +110,31 @@ class ApplicationContextRequestMatcherTests {
assertThat
(
matcher
.
matches
(
request
)).
isFalse
();
}
@Test
// gh-18211
void
matchesWhenConcurrentlyCalledWaitsForInitialize
()
{
ConcurrentApplicationContextRequestMatcher
matcher
=
new
ConcurrentApplicationContextRequestMatcher
();
StaticWebApplicationContext
context
=
createWebApplicationContext
();
Runnable
target
=
()
->
matcher
.
matches
(
new
MockHttpServletRequest
(
context
.
getServletContext
()));
List
<
Thread
>
threads
=
new
ArrayList
<>();
AssertingUncaughtExceptionHandler
exceptionHandler
=
new
AssertingUncaughtExceptionHandler
();
for
(
int
i
=
0
;
i
<
2
;
i
++)
{
Thread
thread
=
new
Thread
(
target
);
thread
.
setUncaughtExceptionHandler
(
exceptionHandler
);
threads
.
add
(
thread
);
}
threads
.
forEach
(
Thread:
:
start
);
threads
.
forEach
(
this
::
join
);
exceptionHandler
.
assertNoExceptions
();
}
private
void
join
(
Thread
thread
)
{
try
{
thread
.
join
(
1000
);
}
catch
(
InterruptedException
ex
)
{
}
}
private
StaticWebApplicationContext
createWebApplicationContext
()
{
StaticWebApplicationContext
context
=
new
StaticWebApplicationContext
();
MockServletContext
servletContext
=
new
MockServletContext
();
...
...
@@ -160,4 +190,47 @@ class ApplicationContextRequestMatcherTests {
}
static
class
ConcurrentApplicationContextRequestMatcher
extends
ApplicationContextRequestMatcher
<
Object
>
{
ConcurrentApplicationContextRequestMatcher
()
{
super
(
Object
.
class
);
}
private
AtomicBoolean
initialized
=
new
AtomicBoolean
();
@Override
protected
void
initialized
(
Supplier
<
Object
>
context
)
{
try
{
Thread
.
sleep
(
200
);
}
catch
(
InterruptedException
ex
)
{
}
this
.
initialized
.
set
(
true
);
}
@Override
protected
boolean
matches
(
HttpServletRequest
request
,
Supplier
<
Object
>
context
)
{
assertThat
(
this
.
initialized
.
get
()).
isTrue
();
return
true
;
}
}
private
static
class
AssertingUncaughtExceptionHandler
implements
UncaughtExceptionHandler
{
private
volatile
Throwable
ex
;
@Override
public
void
uncaughtException
(
Thread
thead
,
Throwable
ex
)
{
this
.
ex
=
ex
;
}
void
assertNoExceptions
()
{
if
(
this
.
ex
!=
null
)
{
ReflectionUtils
.
rethrowRuntimeException
(
this
.
ex
);
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment