Compare commits

..

297 Commits

Author SHA1 Message Date
Eleftheria Stein
b1d68c0731 Release 2.5.0 2021-05-19 00:13:33 +02:00
Eleftheria Stein
7ec5add1bd Configure user name for Gradle CI builds
This reverts commit e41ebd8a77.
2021-05-19 00:13:17 +02:00
Eleftheria Stein
05e103d9c5 Use GPG_PRIVATE_KEY_NO_HEADER secret in CI
Issue gh-1812
2021-05-19 00:09:26 +02:00
Eleftheria Stein
8190072d3f Revert "Release 2.5.0"
This reverts commit ce16374c15.
2021-05-19 00:08:02 +02:00
Eleftheria Stein
ce16374c15 Release 2.5.0 2021-05-18 22:24:46 +02:00
Eleftheria Stein
e41ebd8a77 Revert "Configure user name for Gradle CI builds"
This reverts commit ce938fd2fe.
2021-05-18 22:22:37 +02:00
Eleftheria Stein
8550aeca5c Revert "Release 2.5.0"
This reverts commit 5cb8a6b79a.
2021-05-18 22:22:21 +02:00
Eleftheria Stein
5cb8a6b79a Release 2.5.0 2021-05-18 13:28:56 +02:00
Eleftheria Stein
5b48e7e8e7 Upgrade Spring Security to 5.5.0
Closes gh-1856
2021-05-18 10:00:37 +02:00
Eleftheria Stein
9e2b729d62 Upgrade test dependencies 2021-05-17 17:45:47 +02:00
Eleftheria Stein
524ee0d9bc Upgrade samples to Spring Boot 2.4.5
Closes gh-1855
2021-05-17 17:20:46 +02:00
Eleftheria Stein
26be3218fb Upgrade Spring Framework to 5.3.7
Closes gh-1853
2021-05-17 17:12:53 +02:00
Eleftheria Stein
8d4fd80add Upgrade Spring Data to 2021.0.1
Closes gh-1854
2021-05-17 17:12:25 +02:00
Eleftheria Stein
6969ea0049 Upgrade Reactor to 2020.0.7
Closes gh-1852
2021-05-17 17:11:01 +02:00
Eleftheria Stein
ce938fd2fe Configure user name for Gradle CI builds
Closes gh-1851
2021-05-14 12:32:29 +02:00
weix sun
98d7448b40 Fix broken Framework link in reference docs 2021-05-11 11:18:52 +02:00
Eleftheria Stein
4bb2bd6fda JDBC session with negative timeout should never expire
Closes gh-1847
2021-05-10 16:38:30 +02:00
Eleftheria Stein
0e5dd1863f Rename master branch to main
Closes gh-1846
2021-04-28 17:19:52 +02:00
Eleftheria Stein
548b58ee55 Next development version 2021-04-13 12:43:12 +02:00
Eleftheria Stein
bb28af9934 Release 2.5.0-RC1 2021-04-13 12:28:27 +02:00
Eleftheria Stein
dee8402473 Upgrade test dependencies 2021-04-13 12:12:17 +02:00
Eleftheria Stein
7bd0b45f29 Upgrade samples to Spring Boot 2.4.4
Closes gh-1822
2021-04-13 12:01:37 +02:00
Eleftheria Stein
b42b01af9b Upgrade Hazelcast 4 to 4.2
Closes gh-1821
2021-04-13 11:31:58 +02:00
Eleftheria Stein
6744fee3cb Upgrade Hazelcast to 3.12.12
Closes gh-1820
2021-04-13 11:22:00 +02:00
Eleftheria Stein
6811f25565 Upgrade Spring Security to 5.5.0-RC1
Closes gh-1819
2021-04-13 11:21:10 +02:00
Eleftheria Stein
47817c46e1 Upgrade Spring Data to 2021.0.0-RC1
Closes gh-1818
2021-04-13 11:20:20 +02:00
Eleftheria Stein
4f7c6406ad Upgrade Spring Framework to 5.3.5
Closes gh-1817
2021-04-13 11:19:27 +02:00
Eleftheria Stein
34cc1d1171 Upgrade Reactor to 2020.0.6
Closes gh-1816
2021-04-13 11:18:29 +02:00
Josh Cummings
9e7d9912e5 Change to GPG_PRIVATE_KEY_NO_HEADER
Closes gh-1812
2021-03-30 13:32:28 -06:00
Eleftheria Stein
d2960b570f Polish gh-1798
- Should throw IllegalStateException
2021-03-25 09:55:32 +02:00
Eleftheria Stein
8bd4374909 Throw exception if session created after response
Closes gh-1798
2021-03-25 09:27:27 +02:00
Eleftheria Stein
15f29f8adf Fix README formatting 2021-03-22 12:48:34 +02:00
Eleftheria Stein
74d53e8bfc Add additional information to README 2021-03-22 12:45:51 +02:00
Eleftheria Stein
77deb63373 Fix SessionRepositoryFilter Javadoc 2021-03-17 16:39:45 +01:00
Stefan Wurzinger
69285f2a9a Fix Redis session expiration entry deletion
Closes gh-585
2021-03-12 16:24:48 +01:00
Eleftheria Stein
c93513f18f Fix typo in reference docs 2021-02-09 16:12:51 +01:00
Eleftheria Stein
27044c8766 Make Hazelcast tests independent of ordering
Closes gh-1787
2021-02-02 13:24:24 +01:00
Eleftheria Stein
b198844671 Use io.spring.gradle-enterprise-conventions
Adds support for build cache and build scans

Closes gh-1713
2021-02-01 18:14:28 +01:00
Eleftheria Stein
0f27bbaff7 Update to gradle 6.8.1
Closes gh-1785
2021-02-01 17:32:09 +01:00
Eleftheria Stein
62ad3e1bab Replace deprecated verifyZeroInteractions in tests 2021-01-29 17:00:03 +01:00
Eleftheria Stein
7eed8427a5 Use spring-build-conventions:0.0.37 2021-01-27 11:09:43 +01:00
Eleftheria Stein
4cbb253c11 Resolve artifacts from Maven Central first
- Use spring-build-conventions:0.0.36
- Add https://repo.spring.io/release to reference

Closes gh-1778
2021-01-22 15:27:06 +01:00
Eleftheria Stein
3fe03c60f3 Add manual trigger to CI workflow
Closes gh-1777
2021-01-19 17:37:18 +01:00
Eleftheria Stein
d95652dcb3 Next development version 2021-01-19 14:19:49 +01:00
Eleftheria Stein
cfc1a1e7ce Release 2.5.0-M1 2021-01-19 13:55:51 +01:00
Eleftheria Stein
e17d0cc1d9 Upgrade test dependencies 2021-01-18 12:54:54 +01:00
Eleftheria Stein
0a0766e4a8 Upgrade Hazelcast 4 to 4.1.1
Closes gh-1761
2021-01-18 12:43:34 +01:00
Eleftheria Stein
4108c77797 Upgrade Hazelcast to 3.12.11
Closes gh-1760
2021-01-18 12:41:02 +01:00
Eleftheria Stein
c015a69a4a Upgrade Spring Data to 2021.0.0-M2
Closes gh-1759
2021-01-18 12:39:30 +01:00
Eleftheria Stein
293cf3f730 Upgrade Spring Security to 5.5.0-M1
Closes gh-1758
2021-01-18 12:37:49 +01:00
Eleftheria Stein
6f79e87c8f Upgrade Spring Framework to 5.3.3
Closes gh-1757
2021-01-18 12:35:29 +01:00
Eleftheria Stein
d74c5b1445 Upgrade Reactor to 2020.0.3
Closes gh-1755
2021-01-18 12:34:01 +01:00
Eleftheria Stein
6075089691 Upgrade samples to Spring Boot 2.4.2
Closes gh-1756
2021-01-18 12:31:54 +01:00
Eleftheria Stein
e7a0924904 Upgrade test dependencies 2021-01-12 13:34:47 +01:00
daisuzz
319f0a97ad Fix example in RedisIndexedSessionRepository and Storage Details section
* Fix example in JavaDocs of RedisIndexedSessionRepository

* Fix example in Storage Details section of documentation
2021-01-04 09:32:44 +01:00
Eleftheria Stein
95de199aa4 Upgrade samples to Spring Boot 2.4.1
Closes gh-1744
2020-12-14 09:56:17 +01:00
Eleftheria Stein
db589b7c29 Update community extensions section of reference manual
Closes gh-1736
2020-12-09 13:02:30 +01:00
Vedran Pavic
2aae51b1a1 Rationalize JDBC integration tests
This commit reduces the JDBC integration tests to only single (latest) version per RDBMS vendor, due to a growing number of integration tests. Additionally, the configuration of most containers is simplified due to improved defaults within the Testcontainers library.
2020-11-28 00:26:17 +01:00
Vedran Pavic
e721efeb85 Optimize insert attribute statement in JdbcIndexedSessionRepository
At present, the SQL statement used to insert a session attribute record contains a nested select statement that verifies the existence of parent record in the session table. Such approach can be susceptible to deadlocks on certain RDMBSs.

This commit optimizes the SQL statement used to insert session attribute so that it doesn't perform a nested select statement.

Closes: #1550
2020-11-28 00:26:17 +01:00
Vedran Pavic
0111c6e686 Provide database specific JdbcIndexedSessionRepository customizers
This commit provides JdbcIndexedSessionRepository customizers for the following SQL dialects:

- PostgreSQL
- MySQL (also used by MariaDB)
- SQL Server
- IBM DB2
- Oracle

These customizers are intended to address the concurrency issues occurring on insert of new session attribute by applying SQL dialect specific SQL upsert/merge statement instead of a generic insert.

Closes: #1213
2020-11-27 23:54:03 +01:00
Eleftheria Stein
07058c0cdf Add artifactory credentials to build 2020-11-17 13:59:06 +01:00
Thomas Heigl
5f5168814d Delay allocating Strings for message channel and body 2020-11-10 08:03:57 -05:00
Vedran Pavic
55502f336d Harmonize Redis key namespace configurations
At present, the RedisSessionRepository#setKeyNamespace expects users to provide the trailing colon (:) character that is used as separator between namespace segments. This is unlike RedisIndexedSessionRepository and ReactiveRedisSessionRepository that apply the separator implicitly in their respective #setRedisKeyNamespace methods.

This commit harmonizes the Redis key namespaces configurations across all Redis-backed session repository implementations.
2020-11-10 06:55:19 -05:00
Eleftheria Stein
0e83e3f1e0 Next development version 2020-11-10 11:48:27 +01:00
Eleftheria Stein
34876397a0 Next development version 2020-11-09 16:49:29 +01:00
Eleftheria Stein
faee8f1bdb Release 2.4.1 2020-11-09 15:40:43 +01:00
Eleftheria Stein
859784fe9e Use secrets from GitHub Actions workflow 2020-11-09 15:39:54 +01:00
Eleftheria Stein
4dd2db32d2 Revert "Release 2.4.1"
This reverts commit ae86831821.
2020-11-09 15:39:20 +01:00
Eleftheria Stein
ae86831821 Release 2.4.1 2020-11-04 17:36:47 +01:00
Eleftheria Stein
b722b12327 Fix formatting
Issue gh-1654
2020-10-30 14:34:37 +01:00
Kohei Tamura
29ff2e47fb Add try-with-resources to methods to insert BLOB 2020-10-30 08:45:52 -04:00
Eleftheria Stein
dc9da1d5bf Use OSSRH token credentials in workflow
Closes gh-1725
2020-10-30 13:42:36 +01:00
Eleftheria Stein
5a52df37ba Next development version 2020-10-28 23:36:40 +01:00
Eleftheria Stein
6d161575d5 Release 2.4.0wq 2020-10-28 22:48:46 +01:00
Eleftheria Stein
1cd8849eb9 Revert "Delete Jenkinsfile"
This reverts commit 68f867b60b.
2020-10-28 22:42:47 +01:00
Eleftheria Stein
cb3894614a Revert "Release 2.4.0"
This reverts commit 82e71d834b.
2020-10-28 22:42:06 +01:00
Eleftheria Stein
82e71d834b Release 2.4.0 2020-10-28 18:40:09 +01:00
Eleftheria Stein
81a9e71a5b Upgrade test and sample dependencies
This is needed in order for them to work with Spring Data 2020.0.0
2020-10-28 18:18:45 +01:00
Eleftheria Stein
298f0d59a0 Upgrade Spring Data to 2020.0.0
Closes gh-1721
2020-10-28 18:18:15 +01:00
Eleftheria Stein
c354284616 Upgrade samples to Spring Boot 2.4.0-M4
Closes gh-1722
2020-10-28 18:17:54 +01:00
Eleftheria Stein
4086044c2f Upgrade Spring Framework to 5.3.0
Closes gh-1720
2020-10-28 09:51:48 +01:00
Eleftheria Stein
e663401ecb Upgrade Hazelcast to 3.12.10
Closes gh-1718
2020-10-27 15:50:35 +01:00
Eleftheria Stein
60151c9e7d Upgrade Spring Security to 5.4.1
Closes gh-1717
2020-10-27 15:50:16 +01:00
Eleftheria Stein
18052460c6 Upgrade Reactor to 2020.0.0
Closes gh-1716
2020-10-27 15:49:49 +01:00
Eleftheria Stein
5092e86306 Upgrade samples to Spring Boot 2.3.4.RELEASE
Closes gh-1719
2020-10-27 15:49:19 +01:00
Eleftheria Stein
6de6df6dab Upgrade test dependencies 2020-10-27 15:15:30 +01:00
Vedran Pavic
301e65c2b9 Remove unnecessary Redis commands in RedisIndexedSessionRepository#save
See: #1331
2020-10-12 10:13:38 -04:00
Vedran Pavic
090a10fb10 Improve RedisSessionRepository-based sample configuration 2020-10-12 03:23:21 -04:00
Eleftheria Stein
235801487e Hazelcast4SessionUpdateEntryProcessor does not implement Offloadable
Closes gh-1707
2020-09-25 10:31:54 +02:00
Eleftheria Stein
e6e02de210 Upgrade Hazelcast 4 to 4.0.3
Closes gh-1706
2020-09-22 11:12:58 +02:00
Eleftheria Stein
b3b46fd8eb Upgrade Hazelcast to 3.12.9
Closes gh-1705
2020-09-22 10:46:15 +02:00
Eleftheria Stein
e46610f53a Next development version 2020-09-16 18:39:21 +02:00
Eleftheria Stein
e8c6b8db7b Release 2.4.0-RC1 2020-09-16 18:21:15 +02:00
Eleftheria Stein
486d00e5da Upgrade Spring Data to 2020.0.0-RC1
Closes gh-1704
2020-09-16 18:00:54 +02:00
Eleftheria Stein
0ab781e537 Consolidate Hazelcast configurations
Issue gh-1584
2020-09-16 16:35:03 +02:00
Eleftheria Stein
849b353cec Disable parallel deployment in CI build
Closes gh-1699
2020-09-16 09:59:38 +02:00
Eleftheria Stein
b262c9a3fd Upgrade Spring Framework to 5.3.0-RC1
Closes gh-1698
2020-09-15 17:18:35 +02:00
Eleftheria Stein
5d9e7caff0 Upgrade samples to Spring Boot 2.3.3.RELEASE
Closes gh-1683
2020-09-14 20:06:59 +02:00
Eleftheria Stein
dd348bc7b8 Upgrade test dependencies 2020-09-14 20:06:50 +02:00
Eleftheria Stein
9372986f84 Upgrade Spring Security to 5.4.0
Closes gh-1682
2020-09-14 19:41:49 +02:00
Eleftheria Stein
657c6a63e1 Upgrade Reactor to 2020.0.0-RC1
Closes gh-1681
2020-09-14 19:41:03 +02:00
Eleftheria Stein
a9c2336482 Use controller in Spring Boot sample
Issue gh-1647
2020-09-14 19:04:54 +02:00
Eleftheria Stein
068ed8d355 Ensure Hazelcast 4 compatibility with Java 9+ 2020-09-14 18:25:36 +02:00
Eleftheria Stein
2b6489c2bd Add support for Hazelcast 4
Closes gh-1584
2020-09-14 17:59:35 +02:00
Eleftheria Stein
c0c672b9f8 Update samples module link
Closes gh-1680
2020-09-09 17:04:37 +02:00
Ellie Bahadori
46d1205ff9 Create sample Spring Boot / Hazelcast project
Closes gh-1647
2020-09-09 15:44:31 +02:00
Enes Ozcan
cc85e927cd Add optional Hazelcast session serializer
Issue gh-1131
2020-09-08 07:31:32 -04:00
Ellie Bahadori
0819988a15 Move Gradle enterprise cache secrets to top level of CI build 2020-09-07 07:43:20 -04:00
Ellie Bahadori
0f3ea33b50 Fix indentation for cron job 2020-08-06 04:41:52 -04:00
Ellie Bahadori
0205c318d1 Remove placeholder comment from pipeline file 2020-08-04 05:18:40 -04:00
Ellie Bahadori
13bc1a5d24 Merge pull request #1663 from spring-projects/deploy-pipeline-test
Deploy pipeline test
2020-07-30 16:09:13 -07:00
Ellie Bahadori
8d2ec1ea44 Bring back master branch in preparation for merge
This reverts commit b54fb41952.
2020-07-30 14:53:18 -07:00
Ellie Bahadori
729ce13390 Add Gradle enterprise cache values to build steps 2020-07-30 14:34:37 -07:00
Ellie Bahadori
b54fb41952 Temporarily revert branch name changes to test artifact output
This reverts commit cf911322c2.
2020-07-30 14:10:10 -07:00
Ellie Bahadori
cf911322c2 Update badge to point to master and trigger builds on push to master branch 2020-07-28 11:46:38 -07:00
Ellie Bahadori
6bce5ddf7f Bump spring-build-conventions version and add README badge 2020-07-28 11:43:49 -07:00
Ellie Bahadori
7384504871 Fix YAML spacing issue 2020-07-27 12:14:12 -07:00
Ellie Bahadori
c21fff1a00 Add cron job back in 2020-07-27 11:57:36 -07:00
Ellie Bahadori
d602880a58 Re-introduce JDK matrix for CI pipeline 2020-07-27 11:00:01 -07:00
Ellie Bahadori
2a2c430793 Add URL for maven snapshots 2020-07-27 09:44:26 -07:00
Ellie Bahadori
6080611d1d Bump back up to 0.0.34.BUILD-SNAPSHOT 2020-07-27 09:44:26 -07:00
Ellie Bahadori
38adaeca94 Rev spring build conventions down to 0.0.33.RELEASE 2020-07-27 09:44:26 -07:00
Ellie Bahadori
6a791651e0 Bump spring build conventions version to 0.0.34.BUILD-SNAPSHOT 2020-07-27 09:44:26 -07:00
Ellie Bahadori
dfd6a0bc1b Add in deploy artifacts and docs steps 2020-07-27 09:44:26 -07:00
Ellie Bahadori
805820eeea Remove JDK version matrix for now 2020-07-27 09:44:26 -07:00
Ellie Bahadori
68f867b60b Delete Jenkinsfile 2020-07-27 09:44:26 -07:00
Ellie Bahadori
1044621caf Setup initial CI pipeline file 2020-07-27 09:44:26 -07:00
Eleftheria Stein-Kousathana
13f5cb4bac Document @SpringSessionDataSource in reference docs
Issue gh-1011
2020-07-27 12:14:41 +02:00
Thanh Nhan
5c05970b86 Update OncePerRequestFilter to match with spring-web
Closes gh-1658
2020-07-27 03:58:21 -04:00
Eleftheria Stein-Kousathana
0cd0bfb32f Remove attribute key and value from Redis
Closes gh-1331
2020-07-24 12:55:26 +02:00
Ellie Bahadori
b219806d8e Set up Github Actions pipeline for PRs 2020-07-23 04:01:58 -04:00
Eleftheria Stein
0f2a331ea3 Remove JDK 9 and 10 from Jenkins build
Closes gh-1659
2020-07-16 10:44:26 +02:00
Jay Bryant
ef8f667e35 Wording changes
Replacing some terms
2020-07-16 04:21:23 -04:00
Eleftheria Stein
4599e75c3a Next development version 2020-06-26 18:49:34 +02:00
Eleftheria Stein
8a971b9ce1 Release 2.4.0-M1 2020-06-26 18:25:57 +02:00
Eleftheria Stein
56e9dcfe20 Upgrade Spring Data to 2020.0.0-M1
Closes gh-1648
2020-06-26 11:45:17 -04:00
Eleftheria Stein
59e2cdb74f Upgrade Spring Framework to 5.3.0-M1
Closes gh-1649
2020-06-26 11:45:17 -04:00
Eleftheria Stein
847433562e Upgrade samples to Spring Boot 2.3.1.RELEASE
Closes gh-1650
2020-06-25 21:47:59 +02:00
Eleftheria Stein
55a6967331 Upgrade sample dependencies 2020-06-25 21:13:55 +02:00
Eleftheria Stein
2c8ce67ffc Upgrade Spring Security to 5.3.3.RELEASE
Closes gh-1651
2020-06-25 16:16:57 +02:00
Eleftheria Stein
076ed5cd71 Upgrade Reactor to Dysprosium-SR9
Closes gh-1652
2020-06-25 16:14:49 +02:00
Eleftheria Stein
f1ea71e55e Upgrade test dependencies 2020-06-25 15:41:39 +02:00
Eleftheria Stein
5acb307a54 Upgrade documentation styling
Resolves gh-1640
2020-05-14 16:12:06 -04:00
Eleftheria Stein
f921c4f527 Next development build 2020-05-12 14:41:38 -04:00
Eleftheria Stein
12dc76ec36 Release 2.3.0.RELEASE 2020-05-12 13:05:08 -04:00
Eleftheria Stein
7be3d30981 Upgrade Spring Security to 5.3.2.RELEASE
Resolves gh-1625
2020-05-12 12:58:59 -04:00
Eleftheria Stein
9c8fe23789 Upgrade Spring Data to Neumann-RELEASE
Resolves gh-1623
2020-05-12 12:58:12 -04:00
Eleftheria Stein
3114ef51ec Upgrade samples to Spring Boot 2.2.7
Resolves gh-1624
2020-05-12 12:54:19 -04:00
Kacper
9e7736bf7f Complete Javadoc description of setCookieMaxAge
Issue: gh-1627
2020-05-11 15:16:40 -04:00
Eleftheria Stein
6c5e335568 Upgrade Reactor to Dysprosium-SR7
Resolves gh-1626
2020-05-05 11:19:49 -04:00
Eleftheria Stein
1deedad3b9 Upgrade Spring Framework to 5.2.6.RELEASE
Resolves gh-1622
2020-05-05 11:17:34 -04:00
Eleftheria Stein
e4a8a6aa5c Upgrade test dependencies 2020-05-01 16:46:06 -04:00
Eleftheria Stein
49375a28fa Add guide for customizing cookie in WebFlux
Resolves gh-1614
2020-04-28 16:25:40 -04:00
Eleftheria Stein
5375f51bca Fix broken links in guides
Resolves gh-1621
2020-04-28 14:25:47 -04:00
Eleftheria Stein
29af9d3a4d WebFlux custom cookie sample
Resolves gh-1620
2020-04-22 12:40:40 -04:00
Eleftheria Stein
997ff56c63 Update gitignore 2020-04-22 12:40:40 -04:00
Rob Winch
06d8031211 Add status: waiting-for-triage to issue templates 2020-04-16 16:07:46 -05:00
Rob Winch
904369ac29 Revert PULL_REQUEST_TEMPLATE
Issue gh-1618
2020-04-15 20:34:52 -05:00
Rob Winch
266854a0be Add GitHub Issue Templates
Closes gh-1618
2020-04-15 20:22:29 -05:00
Rob Winch
8f02c83e06 Use GitHub default community health files
Closes gh-1617
2020-04-15 20:22:29 -05:00
Jay Bryant
570a7686b1 Fix a bad typo
Caught an egregious typing error from my own earlier work.
2020-04-15 16:38:40 -04:00
Rob Winch
fed318abc7 Find by Username Sample switch from DELETE to POST
Spring Boot 2.2 no longer adds HiddenHttpMethodFilter by default See
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.2-Release-Notes#httphiddenmethodfilter-disabled-by-default
This means that trying to map DELETE requests using _method variable
does not work.

This changes the mapping to use a POST which doesn't require the
HiddenHttpMethodFilter which might expose the application to unnecessary
security risk by allowing the HTTP method to be overridden.

Closes gh-1613
2020-04-13 09:41:02 -05:00
Eleftheria Stein
a824edd1c3 Mention Spring Boot implementation detection in docs
Resolves: gh-1610
2020-03-30 13:54:07 -04:00
慕华
aa4f783b45 Update boot-redis.adoc
on-save -> on_save
2020-03-16 08:08:14 -05:00
Eleftheria Stein
11fb68444f Fix invalid reference in docs 2020-03-13 11:04:12 -04:00
Eleftheria Stein
00026a30f4 Fix PDF docs
Resolves: #1603
2020-03-13 10:59:40 -04:00
Eleftheria Stein
c007437bd3 Next Development Build 2020-03-02 17:24:40 -05:00
Eleftheria Stein
dda13b5619 Release 2.3.0.RC1 2020-03-02 17:02:13 -05:00
Eleftheria Stein
366f13bd25 Upgrade Hazelcast to 3.12.6
Resolves: #1591
2020-03-02 16:29:04 -05:00
Eleftheria Stein
3535137c47 Upgrade test dependencies 2020-03-02 16:28:51 -05:00
Eleftheria Stein
a9bca9088f Upgrade Reactor to Dysprosium-SR5
Resolves: #1590
2020-03-02 16:14:41 -05:00
Eleftheria Stein
31de86ecef Upgrade samples to Spring Boot 2.2.5
Resolves: #1589
2020-03-02 15:46:30 -05:00
Eleftheria Stein
d123960f89 Upgrade Spring Data to Neumann-M3
Resolves: #1588
2020-03-02 15:45:19 -05:00
Eleftheria Stein
16d2923efd Upgrade Spring Security to 5.3.0.RC1
Resolves: #1587
2020-03-02 15:44:49 -05:00
Eleftheria Stein
24015d0854 Upgrade Spring Framework to 5.2.4.RELEASE
Resolves: #1586
2020-03-02 15:43:43 -05:00
Eleftheria Stein
d8f160c178 Update documentation styling
Upgrade spring-build-conventions to 0.0.28.RELEASE

Resolves: #1585
2020-03-02 15:30:29 -05:00
Eleftheria Stein
0318f6e2c1 Fix asciidoctor warnings
Invalid references and mismatched nesting blocks
2020-03-02 09:13:17 -05:00
Eleftheria Stein
43dd571345 Fix typo in Javadoc 2020-02-27 16:32:29 -05:00
Adam Kucera
e7fb9fce47 Fix examples in JavaDocs of classes which use SessionRepositories
The examples in JavaDocs of @EnableSpringHttpSession, SpringHttpSessionConfiguration and @EnableSpringWebSession were creating MapSessionRepository / ReactiveMapSessionRepository
using a constructor, which no longer exists in the classes. This should allow the example
to be used out of the box.
2020-02-20 15:25:46 -05:00
Eleftheria Stein
f13eb8d73e Use Spring Security lambda DSL in samples
Fixes: gh-1580
2020-02-19 12:36:51 +01:00
Jivko Vantchev
1a07ba5114 Fixes the duplicate index name in the example SQL script
The change is in the comments for the JdbcIndexedSessionRepository.
2020-02-14 12:03:24 +01:00
Eleftheria Stein
7125aac567 Next Development Build 2020-01-29 22:18:06 +01:00
Eleftheria Stein
3cbd3a9e25 Release 2.3.0.M1 2020-01-29 21:54:34 +01:00
Eleftheria Stein
4c914d46c9 Upgrade Spring Framework to 5.2.3.RELEASE
Resolves: #1575
2020-01-29 21:47:32 +01:00
Eleftheria Stein
adf411ecc3 Upgrade Spring Security to 5.3.0.M1
Resolves: #1568
2020-01-29 21:12:50 +01:00
Eleftheria Stein
95b39a203f Upgrade Spring Data to Neumann-M2
Resolves: #1567
2020-01-29 21:12:06 +01:00
Eleftheria Stein
3d653b3b50 Next Development Build 2020-01-29 21:08:14 +01:00
Eleftheria Stein
938fd3c2e5 Next Development Build 2020-01-29 20:55:04 +01:00
Eleftheria Stein
45bb0f9b0c Run deployArtifacts before finalizeDeployArtifacts in build
This commit is needed to fix the release

Resolves: #1574
2020-01-29 16:39:07 +01:00
Eleftheria Stein
cddd84d564 Release 2.2.1.RELEASE 2020-01-28 10:57:10 +01:00
Eleftheria Stein
6931d40e6e Upgrade samples to Spring Boot 2.2.4.RELEASE
Resolves: #1563
2020-01-28 10:26:32 +01:00
Eleftheria Stein
3b672787f3 Upgrade Spring Data to Moore-SR4
Resolves: #1564
2020-01-28 10:22:14 +01:00
Eleftheria Stein
c0ee52b33b Upgrade Reactor to Dysprosium-SR4
Resolves: #1565
2020-01-28 10:21:32 +01:00
Eleftheria Stein
68f8641233 Upgrade Spring Security to 5.2.1.RELEASE
Resolves: #1566
2020-01-28 10:20:48 +01:00
Eleftheria Stein
e7b2af47e1 Upgrade Hazelcast to 3.12.5
Resolves: #1569
2020-01-28 10:19:16 +01:00
Eleftheria Stein
1ad6cbd7f8 Update note in custom-cookie index page
Resolves: gh-1559
2020-01-13 11:57:20 +01:00
Rob Winch
195af52d0b Upgrade to Spring Framework 5.2.2.RELEASE
Fixes gh-1548
2019-12-13 07:06:19 -06:00
Vedran Pavic
bc9d5f1299 Start building against Spring Framework 5.2.2.RELEASE snapshots
See: #1548
2019-11-16 10:20:11 +01:00
Vedran Pavic
3a4345eb6a Upgrade Gradle to 5.6.4 2019-11-15 22:23:23 +01:00
Vedran Pavic
6c41dea893 Polish contribution
Resolves: #1543
2019-11-15 22:10:35 +01:00
Eleftheria Stein
ee1d5b3b3c Document support for SameSite cookie directive
See: #1543
2019-11-15 22:06:13 +01:00
Christoph Dreis
89a4255679 Parse expression only once in PrincipalNameIndexResolver
Resolves: #1539
2019-11-15 12:13:42 +01:00
Rob Winch
6d2e51a0b9 Next Development Build 2019-10-15 15:32:01 -05:00
Rob Winch
798d398d9b Release 2.2.0.RELEASE 2019-10-15 15:31:21 -05:00
Vedran Pavic
085554f56b Polish DefaultCookieSerializer
See: #1514
2019-10-09 08:58:42 +02:00
Vedran Pavic
45b3b35db7 Update Travis CI config 2019-10-08 12:28:42 +02:00
Vedran Pavic
2d06e1159c Improve Hazelcast integration tests
Resolves: #1534
2019-10-08 12:04:42 +02:00
Vedran Pavic
927008bdc8 Ensure session cookie's expires directive uses GMT format
Resolves: #1514
2019-10-07 21:54:00 +02:00
Vedran Pavic
30588dc3c8 Improve Hazelcast client-server topology integration tests
Resolves: #1527
2019-10-06 15:54:02 +02:00
Vedran Pavic
2f79da00dc Upgrade Hazelcast to 3.12.3
Resolves: #1525
2019-10-06 11:41:03 +02:00
Vedran Pavic
e2abe36fa8 Upgrade samples to Spring Boot 2.2.0.RC1
Resolves: #1521
2019-10-03 17:16:59 +02:00
Vedran Pavic
456fd3adb4 Next development version 2019-10-01 06:26:41 +02:00
Vedran Pavic
bd0f474b5b Release 2.2.0.RC1 2019-10-01 06:25:43 +02:00
Vedran Pavic
e5a3933cb6 Upgrade spring-build-conventions to 0.0.27.RELEASE 2019-10-01 06:09:41 +02:00
Vedran Pavic
71e5cc857a Use Jackson 2.10.0 in samples
See: #1508
2019-10-01 00:28:34 +02:00
Vedran Pavic
df455ddc89 Upgrade Spring Security to 5.2.0.RELEASE
Resolves: #1508
2019-09-30 23:55:50 +02:00
Vedran Pavic
eceeaa665d Use Reactor Dysprosium-RELEASE in samples
See: #1509
2019-09-30 21:47:08 +02:00
Vedran Pavic
e6c54d8a75 Upgrade Spring Data to Moore-RELEASE
Resolves: #1507
2019-09-30 21:42:47 +02:00
Vedran Pavic
c88456a183 Rework scheduling configurers into nested configuration
This commit extracts scheduling configurers that are used in Redis and JDBC configurations into nested configuration classes in order to avoid bean method references.

Resolves: #1516
2019-09-30 16:08:55 +02:00
Vedran Pavic
f5abd55394 Ensure proxyBeanMethods is set to false everywhere
This commit sets proxyBeanMethods to false on all @Enable*Session annotations since they are meta-annotated with @Configuration.

See: #1516
2019-09-30 16:08:55 +02:00
Vedran Pavic
b9fd3666b5 Update integration tests 2019-09-30 16:08:20 +02:00
Vedran Pavic
e06ea36ad5 Upgrade test dependencies 2019-09-30 16:08:18 +02:00
Vedran Pavic
0a1701233e Upgrade Spring Framework to 5.2.0.RELEASE
Resolves: #1506
2019-09-30 09:55:05 +02:00
Vedran Pavic
47a4873199 Align TransactionOperations usage with Spring Framework 5.2.0.RELEASE
See: #1506
2019-09-29 22:12:30 +02:00
Vedran Pavic
bd36e115a8 Align with spring-javaformat 0.0.15 2019-09-29 16:16:36 +02:00
Vedran Pavic
ec82336477 Parallelize JDBC integration tests
See: #1505
2019-09-27 07:14:23 +02:00
Vedran Pavic
feaf8780a8 Add support for configuring custom IndexResolver
See: #1467
2019-09-26 22:18:37 +02:00
Vedran Pavic
b357a76ce3 Align Spring Data Redis dependency excludes with Moore-RELEASE
See: #1507
2019-09-26 14:42:22 +02:00
Vedran Pavic
2c6f22afb0 Upgrade Reactor to Dysprosium-RELEASE
Resolves: #1509
2019-09-25 00:30:42 +02:00
Vedran Pavic
34306fd3a0 Fix Gradle dependency caching configuration
See: #1505
2019-09-24 20:50:58 +02:00
Vedran Pavic
a6c1d8eb1d Tweak Gradle JVM memory settings
See: #1505
2019-09-23 22:35:34 +02:00
Vedran Pavic
e48b46a2d5 Improve support for Oracle integration tests
Resolves: #1510
2019-09-23 22:35:33 +02:00
Vedran Pavic
8cc8fbb7fd Harmonize naming of session repositories
Resolves: #1455
2019-09-22 21:47:53 +02:00
Vedran Pavic
96715e04f2 Start building against Reactor Dysprosium-RELEASE snapshots
See: #1509
2019-09-17 22:12:04 +02:00
Vedran Pavic
121a633a40 Optimize project build
This commit optimizes build by:
- configuring Gradle JVM memory settings
- configuring parallel execution
- disabling caching of snapshots

Resolves: #1505
2019-09-17 22:07:44 +02:00
Vedran Pavic
bf31a9b04b Start building against Spring Security 5.2.0.RELEASE snapshots
See: #1508
2019-09-12 22:47:01 +02:00
Vedran Pavic
a209d436d1 Start building against Spring Data Moore-RELEASE snapshots
See: #1507
2019-09-12 22:46:18 +02:00
Vedran Pavic
6c76a1ccdd Start building against Spring Framework 5.2.0.RELEASE snapshots
See: #1506
2019-09-12 22:45:33 +02:00
Vedran Pavic
c974eeb188 Upgrade samples to Spring Boot 2.2.0.M6
Resolves: #1504
2019-09-11 22:38:38 +02:00
Rob Winch
3b5dadb07f Next Development Version 2019-09-06 11:54:55 -05:00
Rob Winch
3e6b3fda0f Release 2.2.0.M4 2019-09-06 11:36:11 -05:00
Rob Winch
840da7fb5a Update to Spring Security 5.2.0.RC1
Fixes gh-1487
2019-09-06 09:31:24 -05:00
Vedran Pavic
560ee5ff4f Upgrade Spring Data to Moore-RC3
Resolves: #1486
2019-09-06 13:17:30 +02:00
Vedran Pavic
072348e28f Upgrade Gradle to 5.6.2 2019-09-05 22:19:39 +02:00
Vedran Pavic
99dfdda7b7 Upgrade Spring Framework to 5.2.0.RC2
Resolves: #1485
2019-09-05 13:12:34 +02:00
Vedran Pavic
18b097d9c7 Upgrade Reactor to Dysprosium-RC1
Resolves: #1498
2019-09-04 07:12:21 +02:00
Vedran Pavic
702a35fac6 Update integration tests 2019-09-03 22:54:57 +02:00
Vedran Pavic
df3e4c5bc1 Add support for customizing session repository before initialization
This commit adds support for customizing session repository implementations (both SessionRepository and ReactiveSessionRepository) before initialization by introducing SessionRepositoryCustomizer and ReactiveSessionRepositoryCustomizer strategies.

Resolves: #1499
2019-09-03 22:17:36 +02:00
Lars Grefer
f746233255 Upgrade Gradle to 5.6.1
Resolves: #1496
2019-08-30 22:44:42 +02:00
Vedran Pavic
f6c82f1eee Improve support for customizing JDBC session store transaction behavior
Resolves: #1469
2019-08-23 23:26:11 +02:00
Josh Cummings
bcdd05a0bc Add OnCommittedResponseWrapper.setContentLengthLong
Add setContentLengthLong tracking to OnCommittedResponseWrapper in
order to detect commits on servlets that use setContentLengthLong to
announce the entity size they are about to write (as used in the
Apache Tomcat's DefaultServlet).

Fixes gh-1489
2019-08-20 13:29:52 -06:00
Vedran Pavic
5d26ab4df4 Add support for AuthenticatedPrincipal in SpringSessionBackedSessionRegistry
Resolves: #1488
2019-08-10 11:23:25 +02:00
Vedran Pavic
e55d86f5e2 Start building against Spring Security 5.2.0.RC1 snapshots
See: #1487
2019-08-07 21:21:34 +02:00
Vedran Pavic
fe480b338c Start building against Spring Data Moore-RC3 snapshots
See: #1486
2019-08-07 21:13:03 +02:00
Vedran Pavic
4b13392430 Start building against Spring Framework 5.2.0.RC2 snapshots
See: #1485
2019-08-07 21:11:34 +02:00
Vedran Pavic
e5d9ce6ead Upgrade samples to Spring Boot 2.2.0.M5
Resolves: #1484
2019-08-06 18:07:18 +02:00
Vedran Pavic
bc1ef4359a Next development version 2019-08-05 22:18:02 +02:00
Vedran Pavic
98fa5ed52d Release 2.2.0.M3 2019-08-05 22:16:41 +02:00
Vedran Pavic
44468134aa Upgrade samples to Spring Framework 5.2.0.RC1
See: #1460
2019-08-05 21:58:23 +02:00
Vedran Pavic
c14c621da6 Remove Spring Framework snapshot dependency from samples
See: #1460
2019-08-05 21:43:53 +02:00
Vedran Pavic
6ceca18248 Revert to development version 2019-08-05 21:23:54 +02:00
Vedran Pavic
229ca09f10 Release 2.2.0.M3 2019-08-05 21:12:00 +02:00
Vedran Pavic
36b82d52f8 Upgrade Spring Security to 5.2.0.M4
Resolves: #1462
2019-08-05 20:49:04 +02:00
Vedran Pavic
dbeb33fd9d Add flush mode support for JDBC sessions
Resolves: #1468
2019-08-05 18:58:29 +02:00
Vedran Pavic
23bf92a086 Upgrade Spring Data to Moore-RC2
Resolves: #1461
2019-08-05 16:04:58 +02:00
Vedran Pavic
2e0c347a3a Update integration tests 2019-08-05 13:26:34 +02:00
Vedran Pavic
972537a3d5 Upgrade test dependencies 2019-08-05 13:25:15 +02:00
Vedran Pavic
99c4f5bc32 Upgrade Spring Framework to 5.2.0.RC1
Resolves: #1460
2019-08-05 12:53:10 +02:00
Vedran Pavic
89f8127763 Upgrade test dependencies 2019-08-02 22:43:08 +02:00
Vedran Pavic
63f1013a07 Upgrade Hazelcast to 3.12.2
Resolves: #1483
2019-08-02 22:39:28 +02:00
Vedran Pavic
a988b062c3 Add IBM DB2 integration tests
Resolves: #1482
2019-08-02 01:11:02 +02:00
Vedran Pavic
09368243aa Update integration tests 2019-07-30 23:28:54 +02:00
Vedran Pavic
903fa10861 Polish 2019-07-30 23:08:13 +02:00
Vedran Pavic
a883e2ee77 Upgrade test dependencies 2019-07-30 20:00:37 +02:00
Vedran Pavic
f68e569bec Upgrade Reactor to Dysprosium-M3
Resolves: #1474
2019-07-30 19:40:58 +02:00
Vedran Pavic
593c126c03 Filtering for nested ERROR dispatch
Resolves: #1470
See: spring-projects/spring-framework#23196
2019-07-19 20:38:30 +02:00
Vedran Pavic
033d6eecae Add support for session save mode
This commit introduces SaveMode enum that individual SessionRepository implementations use to allow customization of the way they handle save operation in terms of tracking delta of changes.

Resolves: #1466
2019-07-14 10:35:05 +02:00
Vedran Pavic
24b9d24e18 Upgrade Gradle to 5.5.1 2019-07-12 17:40:31 +02:00
Vedran Pavic
46bc4b0957 Use no-op TransactionOperations 2019-07-07 13:40:59 +02:00
Vedran Pavic
8cb85618c2 Polish 2019-07-02 23:19:11 +02:00
Vedran Pavic
1ca9daccb4 Remove unnecessary throws declaration 2019-07-02 19:23:35 +02:00
Vedran Pavic
0731e7f2d0 Upgrade Gradle to 5.5 2019-07-02 18:50:52 +02:00
Vedran Pavic
8d0d757e46 Polish 2019-06-25 22:11:29 +02:00
Vedran Pavic
e2f1fe5446 Add missing deprecation
See: #1465
2019-06-25 21:50:03 +02:00
Vedran Pavic
07b9433540 Add common flush mode support
Resolves: #1465
2019-06-24 19:11:12 +02:00
Vedran Pavic
a6f6042831 Introduce IndexResolver
This commit introduces IndexResolver as a strategy interface for resolving index values in FindByIndexNameSessionRepository implementations.

Resolves: #557
2019-06-24 12:01:26 +02:00
Vedran Pavic
099be441dd Fix copyright dates
See: #1441
2019-06-21 15:52:26 +02:00
Rob Winch
17d029d34d Add spring-session label to Jenkins check node
Try and troubleshoot failures in Jenkins
2019-06-20 13:16:17 -05:00
Vedran Pavic
aab9b39a6b Remove immediate flush mode support for reactive Redis sessions
Resolves: #1441
2019-06-20 10:44:22 +02:00
Vedran Pavic
090d882f98 Start building against Spring Security 5.2 snapshots
See: #1462
2019-06-19 16:55:26 +02:00
Vedran Pavic
d91d09567f Start building against Spring Data Moore snapshots
See: #1461
2019-06-19 16:54:55 +02:00
Vedran Pavic
ab5b0e3a32 Start building against Spring Framework 5.2 snapshots
See: #1460
2019-06-19 16:54:31 +02:00
Vedran Pavic
549a2b7f0b Upgrade samples to Spring Boot 2.2.0.M4
Resolves: #1459
2019-06-19 16:51:12 +02:00
Craig Andrews
050ff7538b In Oracle ignore non-existant tables when dropping
If tables don't exist, ignore that error when dropping.

This aligns Oracle with the existing mysql, postgresql, h2, and hsqldb behavior.
2019-06-19 08:25:44 -05:00
Vedran Pavic
e8e65ac09f Add IntelliJ IDEA specific config
See: #1450
2019-06-18 22:48:25 +02:00
Vedran Pavic
822db7fbbf Use spring-javaformat to format and check code
Resolves: #1450
2019-06-17 23:54:41 +02:00
Vedran Pavic
0eaeb98b0c Next development version 2019-06-14 23:27:58 +02:00
395 changed files with 14348 additions and 9796 deletions

View File

@@ -1,7 +0,0 @@
<!--
For Security Vulnerabilities, please use https://pivotal.io/security#reporting
-->
<!--
Thanks for raising a Spring Session issue. Please provide a brief description of your problem along with the version of Spring Session that you are using. If possible, please also consider putting together a sample application that reproduces the issue.
-->

24
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,24 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: 'type: bug, status: waiting-for-triage'
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Sample**
A link to a GitHub repository with a [minimal, reproducible sample](https://stackoverflow.com/help/minimal-reproducible-example).
Reports that include a sample will take priority over reports that do not.
At times, we may require a sample, so it is good to try and include a sample up front.

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Community Support
url: https://stackoverflow.com/questions/tagged/spring-security
about: Please ask and answer questions on StackOverflow with the tag spring-session

View File

@@ -0,0 +1,25 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: 'status: waiting-for-triage, type: enhancement'
assignees: ''
---
**Expected Behavior**
<!--- Tell us how it should work -->
**Current Behavior**
<!--- Explain the difference from current behavior -->
**Context**
<!---
How has this issue affected you?
What are you trying to accomplish?
What other alternatives have you considered?
Are you aware of any workarounds?
-->

View File

@@ -0,0 +1,101 @@
name: CI
on:
push:
branches:
- main
schedule:
- cron: '0 10 * * *' # Once per day at 10am UTC
workflow_dispatch: # Manual trigger
env:
GRADLE_ENTERPRISE_CACHE_USER: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USER }}
GRADLE_ENTERPRISE_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }}
GRADLE_ENTERPRISE_SECRET_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_SECRET_ACCESS_KEY }}
ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
jobs:
build:
name: Build
runs-on: ubuntu-latest
strategy:
matrix:
jdk: [8, 11]
fail-fast: false
steps:
- uses: actions/checkout@v2
- name: Set up JDK ${{ matrix.jdk }}
uses: actions/setup-java@v1
with:
java-version: ${{ matrix.jdk }}
- name: Setup gradle user name
run: |
mkdir -p ~/.gradle
echo 'systemProp.user.name=spring-builds' >> ~/.gradle/gradle.properties
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
- name: Build with Gradle
run: |
export GRADLE_ENTERPRISE_CACHE_USERNAME="$GRADLE_ENTERPRISE_CACHE_USER"
export GRADLE_ENTERPRISE_CACHE_PASSWORD="$GRADLE_ENTERPRISE_CACHE_PASSWORD"
export GRADLE_ENTERPRISE_ACCESS_KEY="$GRADLE_ENTERPRISE_SECRET_ACCESS_KEY"
./gradlew clean build -PartifactoryUsername="$ARTIFACTORY_USERNAME" -PartifactoryPassword="$ARTIFACTORY_PASSWORD" --no-daemon --stacktrace
artifacts:
name: Deploy Artifacts
needs: [build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: '8'
- name: Setup gradle user name
run: |
mkdir -p ~/.gradle
echo 'systemProp.user.name=spring-builds' >> ~/.gradle/gradle.properties
- name: Deploy artifacts
run: |
export GRADLE_ENTERPRISE_CACHE_USERNAME="$GRADLE_ENTERPRISE_CACHE_USER"
export GRADLE_ENTERPRISE_CACHE_PASSWORD="$GRADLE_ENTERPRISE_CACHE_PASSWORD"
export GRADLE_ENTERPRISE_ACCESS_KEY="$GRADLE_ENTERPRISE_SECRET_ACCESS_KEY"
export VERSION_HEADER=$'Version: GnuPG v2\n\n'
export ORG_GRADLE_PROJECT_signingKey=${GPG_PRIVATE_KEY#"$VERSION_HEADER"}
export ORG_GRADLE_PROJECT_signingPassword="$GPG_PASSPHRASE"
./gradlew deployArtifacts -PossrhUsername="$OSSRH_TOKEN_USERNAME" -PossrhPassword="$OSSRH_TOKEN_PASSWORD" -PartifactoryUsername="$ARTIFACTORY_USERNAME" -PartifactoryPassword="$ARTIFACTORY_PASSWORD" --stacktrace --no-parallel
./gradlew finalizeDeployArtifacts -PossrhUsername="$OSSRH_TOKEN_USERNAME" -PossrhPassword="$OSSRH_TOKEN_PASSWORD" -PartifactoryUsername="$ARTIFACTORY_USERNAME" -PartifactoryPassword="$ARTIFACTORY_PASSWORD" --stacktrace --no-parallel
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY_NO_HEADER }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
OSSRH_TOKEN_USERNAME: ${{ secrets.OSSRH_TOKEN_USERNAME }}
OSSRH_TOKEN_PASSWORD: ${{ secrets.OSSRH_TOKEN_PASSWORD }}
ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
docs:
name: Deploy Docs
needs: [build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: '8'
- name: Setup gradle user name
run: |
mkdir -p ~/.gradle
echo 'systemProp.user.name=spring-builds' >> ~/.gradle/gradle.properties
- name: Deploy Docs
run: |
export GRADLE_ENTERPRISE_CACHE_USERNAME="$GRADLE_ENTERPRISE_CACHE_USER"
export GRADLE_ENTERPRISE_CACHE_PASSWORD="$GRADLE_ENTERPRISE_CACHE_PASSWORD"
export GRADLE_ENTERPRISE_ACCESS_KEY="$GRADLE_ENTERPRISE_SECRET_ACCESS_KEY"
./gradlew deployDocs --no-daemon -PdeployDocsSshKey="$DOCS_SSH_KEY" -PdeployDocsSshUsername="$DOCS_USERNAME" -PdeployDocsHost="$DOCS_HOST" --stacktrace
env:
DOCS_USERNAME: ${{ secrets.DOCS_USERNAME }}
DOCS_SSH_KEY: ${{ secrets.DOCS_SSH_KEY }}
DOCS_HOST: ${{ secrets.DOCS_HOST }}

25
.github/workflows/pr-build-workflow.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
name: PR Build
on: pull_request
jobs:
build:
name: Build
runs-on: ubuntu-latest
strategy:
matrix:
jdk: [8, 11]
fail-fast: false
steps:
- uses: actions/checkout@v2
- name: Set up JDK ${{ matrix.jdk }}
uses: actions/setup-java@v1
with:
java-version: ${{ matrix.jdk }}
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
- name: Build with Gradle
run: ./gradlew clean build --no-daemon --stacktrace

1
.gitignore vendored
View File

@@ -13,3 +13,4 @@ out
.checkstyle
!etc/eclipse/.checkstyle
!**/src/**/build
.DS_Store

View File

@@ -1,20 +0,0 @@
language: java
sudo: required
services: docker
jdk: oraclejdk8
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
install: true
script: ./gradlew clean build --refresh-dependencies --no-daemon

View File

@@ -1,44 +0,0 @@
= Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of fostering an open
and welcoming community, we pledge to respect all people who contribute through reporting
issues, posting feature requests, updating documentation, submitting pull requests or
patches, and other activities.
We are committed to making participation in this project a harassment-free experience for
everyone, regardless of level of experience, gender, gender identity and expression,
sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic addresses,
without explicit permission
* Other unethical or unprofessional conduct
Project maintainers have the right and responsibility to remove, edit, or reject comments,
commits, code, wiki edits, issues, and other contributions that are not aligned to this
Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors
that they deem inappropriate, threatening, offensive, or harmful.
By adopting this Code of Conduct, project maintainers commit themselves to fairly and
consistently applying these principles to every aspect of managing this project. Project
maintainers who do not follow or enforce the Code of Conduct may be permanently removed
from the project team.
This Code of Conduct applies both within project spaces and in public spaces when an
individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
contacting a project maintainer at spring-code-of-conduct@pivotal.io . All complaints will
be reviewed and investigated and will result in a response that is deemed necessary and
appropriate to the circumstances. Maintainers are obligated to maintain confidentiality
with regard to the reporter of an incident.
This Code of Conduct is adapted from the
https://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
https://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]

View File

@@ -3,9 +3,16 @@
Spring Session is released under the Apache 2.0 license. If you would like to contribute
something, or simply want to hack on the code this document should help you get started.
== Code of Conduct
This project adheres to the Contributor Covenant link:CODE_OF_CONDUCT.adoc[code of conduct].
By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
Please see our https://github.com/spring-projects/.github/blob/main/CODE_OF_CONDUCT.md[code of conduct].
== Reporting Security Vulnerabilities
Please see our https://github.com/spring-projects/spring-session/security/policy[Security policy].
== Using GitHub issues
@@ -19,7 +26,6 @@ information as possible. Ideally, that would include a small sample project that
reproduces the problem.
== Sign the Contributor License Agreement
If you have not previously done so, please fill out and
submit the https://cla.pivotal.io/sign/spring[Contributor License Agreement].

179
Jenkinsfile vendored
View File

@@ -1,179 +0,0 @@
properties([
buildDiscarder(logRotator(numToKeepStr: '10')),
pipelineTriggers([
cron('@daily')
]),
])
def SUCCESS = hudson.model.Result.SUCCESS.toString()
currentBuild.result = SUCCESS
try {
parallel check: {
stage('Check') {
timeout(time: 45, unit: 'MINUTES') {
node('linux') {
checkout scm
sh "git clean -dfx"
try {
withEnv(["JAVA_HOME=${tool 'jdk8'}"]) {
sh './gradlew clean check --no-daemon --refresh-dependencies --stacktrace'
}
}
catch (e) {
currentBuild.result = 'FAILED: check'
throw e
}
finally {
junit '**/build/test-results/*/*.xml'
}
}
}
}
},
jdk9: {
stage('JDK 9') {
timeout(time: 45, unit: 'MINUTES') {
node('linux') {
checkout scm
sh "git clean -dfx"
try {
withEnv(["JAVA_HOME=${tool 'jdk9'}"]) {
sh './gradlew clean test --no-daemon --refresh-dependencies --stacktrace'
}
}
catch (e) {
currentBuild.result = 'FAILED: jdk9'
throw e
}
}
}
}
},
jdk10: {
stage('JDK 10') {
timeout(time: 45, unit: 'MINUTES') {
node('linux') {
checkout scm
sh "git clean -dfx"
try {
withEnv(["JAVA_HOME=${tool 'jdk10'}"]) {
sh './gradlew clean test --no-daemon --refresh-dependencies --stacktrace'
}
}
catch (e) {
currentBuild.result = 'FAILED: jdk10'
throw e
}
}
}
}
},
jdk11: {
stage('JDK 11') {
timeout(time: 45, unit: 'MINUTES') {
node('linux') {
checkout scm
sh "git clean -dfx"
try {
withEnv(["JAVA_HOME=${tool 'jdk11'}"]) {
sh './gradlew clean test integrationTest --no-daemon --refresh-dependencies --stacktrace'
}
}
catch (e) {
currentBuild.result = 'FAILED: jdk11'
throw e
}
}
}
}
},
jdk12: {
stage('JDK 12') {
timeout(time: 45, unit: 'MINUTES') {
node('linux') {
checkout scm
try {
withEnv(["JAVA_HOME=${tool 'openjdk12'}"]) {
sh './gradlew clean test integrationTest --no-daemon --refresh-dependencies --stacktrace'
}
}
catch (e) {
currentBuild.result = 'FAILED: jdk12'
throw e
}
}
}
}
}
if (currentBuild.result == 'SUCCESS') {
parallel artifacts: {
stage('Deploy Artifacts') {
node('linux') {
checkout scm
sh "git clean -dfx"
try {
withCredentials([file(credentialsId: 'spring-signing-secring.gpg', variable: 'SIGNING_KEYRING_FILE')]) {
withCredentials([string(credentialsId: 'spring-gpg-passphrase', variable: 'SIGNING_PASSWORD')]) {
withCredentials([usernamePassword(credentialsId: 'oss-token', passwordVariable: 'OSSRH_PASSWORD', usernameVariable: 'OSSRH_USERNAME')]) {
withCredentials([usernamePassword(credentialsId: '02bd1690-b54f-4c9f-819d-a77cb7a9822c', usernameVariable: 'ARTIFACTORY_USERNAME', passwordVariable: 'ARTIFACTORY_PASSWORD')]) {
withEnv(["JAVA_HOME=${tool 'jdk8'}"]) {
sh './gradlew deployArtifacts finalizeDeployArtifacts --no-daemon --refresh-dependencies --stacktrace -Psigning.secretKeyRingFile=$SIGNING_KEYRING_FILE -Psigning.keyId=$SPRING_SIGNING_KEYID -Psigning.password=$SIGNING_PASSWORD -PossrhUsername=$OSSRH_USERNAME -PossrhPassword=$OSSRH_PASSWORD -PartifactoryUsername=$ARTIFACTORY_USERNAME -PartifactoryPassword=$ARTIFACTORY_PASSWORD'
}
}
}
}
}
}
catch (e) {
currentBuild.result = 'FAILED: artifacts'
throw e
}
}
}
},
docs: {
stage('Deploy Docs') {
node('linux') {
checkout scm
sh "git clean -dfx"
try {
withCredentials([file(credentialsId: 'docs.spring.io-jenkins_private_ssh_key', variable: 'DEPLOY_SSH_KEY')]) {
withEnv(["JAVA_HOME=${tool 'jdk8'}"]) {
sh './gradlew deployDocs --no-daemon --refresh-dependencies --stacktrace -PdeployDocsSshKeyPath=$DEPLOY_SSH_KEY -PdeployDocsSshUsername=$SPRING_DOCS_USERNAME'
}
}
}
catch (e) {
currentBuild.result = 'FAILED: docs'
throw e
}
}
}
}
}
}
finally {
def buildStatus = currentBuild.result
def buildNotSuccess = !SUCCESS.equals(buildStatus)
def lastBuildNotSuccess = !SUCCESS.equals(currentBuild.previousBuild?.result)
if (buildNotSuccess || lastBuildNotSuccess) {
stage('Notify') {
node {
final def RECIPIENTS = [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']]
def subject = "${buildStatus}: Build ${env.JOB_NAME} ${env.BUILD_NUMBER} status is now ${buildStatus}"
def details = "The build status changed to ${buildStatus}. For details see ${env.BUILD_URL}"
emailext(
subject: subject,
body: details,
recipientProviders: RECIPIENTS,
to: "$SPRING_SESSION_TEAM_EMAILS"
)
}
}
}
}

View File

@@ -1,6 +1,8 @@
= Spring Session
image:https://travis-ci.org/spring-projects/spring-session.svg?branch=master["Build Status", link="https://travis-ci.org/spring-projects/spring-session"] image:https://badges.gitter.im/spring-projects/spring-session.svg[link="https://gitter.im/spring-projects/spring-session?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"]
image:https://badges.gitter.im/spring-projects/spring-session.svg[link="https://gitter.im/spring-projects/spring-session?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"]
image:https://github.com/spring-projects/spring-session/workflows/CI/badge.svg?branch=main["Build Status", link="https://github.com/spring-projects/spring-session/actions?query=workflow%3ACI"]
Spring Session provides an API and implementations for managing a user's session information, while also making it trivial to support clustered sessions without being tied to an application container specific solution.
It also provides transparent integration with:
@@ -11,21 +13,61 @@ It also provides transparent integration with:
== Modules
Spring Session consists of the following modules:
This Spring Session repository consists of the following modules:
* Spring Session Core - provides core Spring Session functionalities and APIs
* Spring Session Data Redis - provides `SessionRepository` and `ReactiveSessionRepository` implementation backed by Redis and configuration support
* Spring Session JDBC - provides `SessionRepository` implementation backed by a relational database and configuration support
* Spring Session Hazelcast - provides `SessionRepository` implementation backed by Hazelcast and configuration support
Additional Spring Session modules can be found in the https://github.com/spring-projects/spring-session-data-mongodb[spring-session-data-mongodb] repository
and https://github.com/spring-projects/spring-session-data-geode[spring-session-data-geode] repository.
== Getting Started
We recommend you visit the https://docs.spring.io/spring-session/docs/current/reference/html5/#samples[Spring Session Reference] and look through the "Samples and Guides" section to see which one best suits your needs.
== Samples
Spring Session samples are available in the https://github.com/spring-projects/spring-session/tree/main/spring-session-samples[spring-session-samples] directory.
== Contributing
Please see our https://github.com/spring-projects/spring-session/blob/main/CONTRIBUTING.adoc[Contributing guidelines]
for information on how to report issues, enhancements or security vulnerabilities.
== Building from Source
Spring Session uses a https://gradle.org[Gradle]-based build system.
In the instructions below, `./gradlew` is invoked from the root of the source tree and serves as
a cross-platform, self-contained bootstrap mechanism for the build.
Check out sources
----
git clone git@github.com:spring-projects/spring-session.git
----
Install all spring-\* jars into your local Maven cache
----
./gradlew install
----
Compile and test; build all jars, distribution zips, and docs
----
./gradlew build
----
== Documentation
You can find the documentation, samples, and guides for using Spring Session on the https://projects.spring.io/spring-session/[Spring Session project site].
For more in depth information, visit the https://docs.spring.io/spring-session/docs/current/reference/html5/[Spring Session Reference].
== Code of Conduct
This project adheres to the Contributor Covenant link:CODE_OF_CONDUCT.adoc[code of conduct].
By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
== Spring Session Project Site
You can find the documentation, issue management, support, samples, and guides for using Spring Session at https://projects.spring.io/spring-session/
Please see our https://github.com/spring-projects/.github/blob/main/CODE_OF_CONDUCT.md[code of conduct].
== License

View File

@@ -4,37 +4,42 @@ buildscript {
snapshotBuild = version.endsWith('SNAPSHOT')
milestoneBuild = !(releaseBuild || snapshotBuild)
springBootVersion = '2.2.0.M2'
springBootVersion = '2.4.5'
}
repositories {
gradlePluginPortal()
maven { url 'https://repo.spring.io/plugins-release/' }
maven {
url = 'https://repo.spring.io/plugins-snapshot'
if (project.hasProperty('artifactoryUsername')) {
credentials {
username "$artifactoryUsername"
password "$artifactoryPassword"
}
}
}
}
dependencies {
classpath 'io.spring.gradle:spring-build-conventions:0.0.25.RELEASE'
classpath 'io.spring.gradle:spring-build-conventions:0.0.37'
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
classpath 'io.spring.nohttp:nohttp-gradle:0.0.2.RELEASE'
}
}
apply plugin: 'io.spring.convention.root'
apply plugin: 'io.spring.nohttp'
repositories {
mavenCentral()
}
group = 'org.springframework.session'
description = 'Spring Session'
subprojects {
apply plugin: 'io.spring.javaformat'
plugins.withType(JavaPlugin) {
sourceCompatibility = JavaVersion.VERSION_1_8
}
tasks.withType(Test) {
useJUnitPlatform()
}
tasks.withType(Test) {
useJUnitPlatform()
}
}

View File

@@ -5,8 +5,10 @@
<module name="SuppressionFilter">
<property name="file" value="${config_loc}/suppressions.xml"/>
</module>
<module name="io.spring.nohttp.checkstyle.check.NoHttpCheck"/>
<module name="io.spring.javaformat.checkstyle.SpringChecks"/>
<module name="com.puppycrawl.tools.checkstyle.TreeWalker">
<module name="io.spring.javaformat.checkstyle.check.SpringJUnit5Check"/>
<module name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck">
<property name="regexp" value="true"/>
<property name="illegalPkgs"

View File

@@ -7,5 +7,5 @@
<suppress files="[\\/]spring-session-docs[\\/]" checks="InnerTypeLast"/>
<suppress files="[\\/]spring-session-samples[\\/]" checks="Javadoc*"/>
<suppress files="[\\/]spring-session-samples[\\/].+Application\.java" checks="HideUtilityClassConstructor"/>
<suppress files="SessionRepositoryFilterTests\.java" checks="SpringLambda"/>
<suppress files="CookieSerializer\.java" checks="SpringMethodVisibility"/>
</suppressions>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
<local-check-config name="Spring Session Checkstyle" location="${configDir}/checkstyle.xml" type="external" description="">
<property name="configDir" value="${configDir}"/>
<additional-data name="protect-config-file" value="false"/>
</local-check-config>
<fileset name="all" enabled="true" check-config-name="Spring Session Checkstyle" local="true">
<file-match-pattern match-pattern="." include-pattern="true"/>
</fileset>
</fileset-config>

View File

@@ -1,295 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="12">
<profile kind="CodeFormatterProfile" name="Spring Session Java Conventions" version="12">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="90"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="90"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
</profile>
</profiles>

View File

@@ -1,391 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.codeComplete.argumentPrefixes=
org.eclipse.jdt.core.codeComplete.argumentSuffixes=
org.eclipse.jdt.core.codeComplete.fieldPrefixes=
org.eclipse.jdt.core.codeComplete.fieldSuffixes=
org.eclipse.jdt.core.codeComplete.localPrefixes=
org.eclipse.jdt.core.codeComplete.localSuffixes=
org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.doc.comment.support=enabled
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
org.eclipse.jdt.core.compiler.problem.deadCode=warning
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=default
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags
org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=default
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.jdt.core.compiler.problem.nullReference=ignore
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.processAnnotations=disabled
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
org.eclipse.jdt.core.formatter.blank_lines_before_field=0
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
org.eclipse.jdt.core.formatter.comment.format_source_code=false
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.jdt.core.formatter.comment.indent_root_tags=false
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=do not insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
org.eclipse.jdt.core.formatter.comment.line_length=90
org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
org.eclipse.jdt.core.formatter.compact_else_if=true
org.eclipse.jdt.core.formatter.continuation_indentation=2
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_empty_lines=false
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.join_lines_in_comments=true
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.lineSplit=90
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=tab
org.eclipse.jdt.core.formatter.tabulation.size=4
org.eclipse.jdt.core.formatter.use_on_off_tags=true
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
org.eclipse.jdt.core.javaFormatter=org.springframework.ide.eclipse.jdt.formatter.javaformatter

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,128 @@
<code_scheme name="SpringSession" version="173">
<option name="AUTODETECT_INDENTS" value="false"/>
<option name="OTHER_INDENT_OPTIONS">
<value>
<option name="USE_TAB_CHARACTER" value="true"/>
</value>
</option>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="50"/>
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="500"/>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="java" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="javax" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="org.springframework" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="true"/>
</value>
</option>
<option name="RIGHT_MARGIN" value="90"/>
<option name="ENABLE_JAVADOC_FORMATTING" value="false"/>
<option name="JD_ALIGN_PARAM_COMMENTS" value="false"/>
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false"/>
<option name="JD_KEEP_EMPTY_LINES" value="false"/>
<GroovyCodeStyleSettings>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="500"/>
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="500"/>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<emptyLine/>
<package name="javax" withSubpackages="true" static="false"/>
<package name="java" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="org.springframework" withSubpackages="true"
static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="true"/>
</value>
</option>
</GroovyCodeStyleSettings>
<JavaCodeStyleSettings>
<option name="CLASS_NAMES_IN_JAVADOC" value="3"/>
<option name="INSERT_INNER_CLASS_IMPORTS" value="true"/>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="50"/>
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="500"/>
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
<value/>
</option>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="java" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="javax" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="org.springframework" withSubpackages="true"
static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="true"/>
</value>
</option>
<option name="ENABLE_JAVADOC_FORMATTING" value="false"/>
<option name="JD_ALIGN_PARAM_COMMENTS" value="false"/>
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false"/>
<option name="JD_KEEP_INVALID_TAGS" value="false"/>
<option name="JD_KEEP_EMPTY_LINES" value="false"/>
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="java.util" withSubpackages="false" static="false"/>
<package name="kotlinx.android.synthetic" withSubpackages="false"
static="false"/>
</value>
</option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="20"/>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="20"/>
</JetCodeStyleSettings>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true"/>
</XML>
<editorconfig>
<option name="ENABLED" value="false"/>
</editorconfig>
<codeStyleSettings language="Groovy">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
<option name="BLANK_LINES_AROUND_FIELD" value="1"/>
<option name="BLANK_LINES_AROUND_FIELD_IN_INTERFACE" value="1"/>
<option name="ELSE_ON_NEW_LINE" value="true"/>
<option name="CATCH_ON_NEW_LINE" value="true"/>
<option name="FINALLY_ON_NEW_LINE" value="true"/>
<option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
<option name="SPACE_WITHIN_ARRAY_INITIALIZER_BRACES" value="true"/>
<option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true"/>
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true"/>
<option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="true"/>
<option name="KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE" value="true"/>
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JSON">
<indentOptions>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true"/>
</indentOptions>
</codeStyleSettings>
</code_scheme>

View File

@@ -1 +1,3 @@
version=2.2.0.M2
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.parallel=true
version=2.5.0

View File

@@ -1,33 +1,36 @@
dependencyManagement {
imports {
mavenBom 'com.fasterxml.jackson:jackson-bom:2.9.6'
mavenBom 'io.projectreactor:reactor-bom:Dysprosium-M2'
mavenBom 'org.junit:junit-bom:5.4.2'
mavenBom 'org.springframework:spring-framework-bom:5.2.0.M3'
mavenBom 'org.springframework.data:spring-data-releasetrain:Moore-RC1'
mavenBom 'org.springframework.security:spring-security-bom:5.2.0.M3'
mavenBom 'org.testcontainers:testcontainers-bom:1.11.3'
mavenBom 'io.projectreactor:reactor-bom:2020.0.7'
mavenBom 'org.junit:junit-bom:5.7.2'
mavenBom 'org.springframework:spring-framework-bom:5.3.7'
mavenBom 'org.springframework.data:spring-data-bom:2021.0.1'
mavenBom 'org.springframework.security:spring-security-bom:5.5.0'
mavenBom 'org.testcontainers:testcontainers-bom:1.15.3'
}
dependencies {
dependencySet(group: 'com.hazelcast', version: '3.12.1') {
dependencySet(group: 'com.hazelcast', version: '3.12.12') {
entry 'hazelcast'
entry 'hazelcast-client'
}
dependency 'com.h2database:h2:1.4.199'
dependency 'com.microsoft.sqlserver:mssql-jdbc:7.2.2.jre8'
dependency 'com.zaxxer:HikariCP:3.3.1'
dependency 'org.aspectj:aspectjweaver:1.9.6'
dependency 'com.h2database:h2:1.4.200'
dependency 'com.ibm.db2:jcc:11.5.5.0'
dependency 'com.microsoft.sqlserver:mssql-jdbc:7.4.1.jre8'
dependency 'com.oracle.database.jdbc:ojdbc8:19.10.0.0'
dependency 'com.zaxxer:HikariCP:3.4.5'
dependency 'edu.umd.cs.mtc:multithreadedtc:1.01'
dependency 'io.lettuce:lettuce-core:5.1.7.RELEASE'
dependency 'io.lettuce:lettuce-core:6.1.2.RELEASE'
dependency 'javax.annotation:javax.annotation-api:1.3.2'
dependency 'javax.servlet:javax.servlet-api:4.0.1'
dependency 'mysql:mysql-connector-java:8.0.16'
dependency 'junit:junit:4.13.2'
dependency 'mysql:mysql-connector-java:8.0.25'
dependency 'org.apache.derby:derby:10.14.2.0'
dependency 'org.assertj:assertj-core:3.12.2'
dependency 'org.hsqldb:hsqldb:2.5.0'
dependency 'org.mariadb.jdbc:mariadb-java-client:2.4.1'
dependency 'org.mockito:mockito-core:2.28.2'
dependency 'org.postgresql:postgresql:42.2.5'
dependency 'org.assertj:assertj-core:3.19.0'
dependency 'org.hsqldb:hsqldb:2.5.1'
dependency 'org.mariadb.jdbc:mariadb-java-client:2.7.3'
dependency 'org.mockito:mockito-core:3.10.0'
dependency 'org.postgresql:postgresql:42.2.20'
}
}

Binary file not shown.

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

35
gradlew vendored
View File

@@ -82,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -125,10 +126,11 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
@@ -154,19 +156,19 @@ if $cygwin ; then
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
i=`expr $i + 1`
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
@@ -175,14 +177,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

25
gradlew.bat vendored
View File

@@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -51,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -61,28 +64,14 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell

View File

@@ -1,3 +1,15 @@
pluginManagement {
repositories {
gradlePluginPortal()
maven { url 'https://repo.spring.io/plugins-release' }
}
}
plugins {
id "com.gradle.enterprise" version "3.5.1"
id "io.spring.ge.conventions" version "0.0.7"
}
rootProject.name = 'spring-session-build'
include 'spring-session-core'
@@ -5,6 +17,8 @@ include 'spring-session-data-redis'
include 'spring-session-docs'
include 'spring-session-hazelcast'
include 'spring-session-jdbc'
include 'hazelcast4'
project(':hazelcast4').projectDir = file('spring-session-hazelcast/hazelcast4')
file('spring-session-samples').eachDirMatch(~/spring-session-sample-.*/) { dir ->
include dir.name

View File

@@ -25,5 +25,6 @@ dependencies {
testCompile "org.springframework.security:spring-security-core"
testCompile "org.junit.jupiter:junit-jupiter-api"
testCompile "org.junit.jupiter:junit-jupiter-params"
testCompile "org.aspectj:aspectjweaver"
testRuntime "org.junit.jupiter:junit-jupiter-engine"
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2014-2019 the original author or authors.
*
* 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
*
* https://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 org.springframework.session;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* An {@link IndexResolver} that resolves indexes using multiple @{link IndexResolver}
* delegates.
*
* @param <S> the type of Session being handled
* @author Vedran Pavic
* @since 2.2.0
*/
public class DelegatingIndexResolver<S extends Session> implements IndexResolver<S> {
private final List<IndexResolver<S>> delegates;
public DelegatingIndexResolver(List<IndexResolver<S>> delegates) {
this.delegates = Collections.unmodifiableList(delegates);
}
@SafeVarargs
public DelegatingIndexResolver(IndexResolver<S>... delegates) {
this(Arrays.asList(delegates));
}
public Map<String, String> resolveIndexesFor(S session) {
Map<String, String> indexes = new HashMap<>();
for (IndexResolver<S> delegate : this.delegates) {
indexes.putAll(delegate.resolveIndexesFor(session));
}
return indexes;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,8 +27,7 @@ import java.util.Map;
* @author Rob Winch
* @author Vedran Pavic
*/
public interface FindByIndexNameSessionRepository<S extends Session>
extends SessionRepository<S> {
public interface FindByIndexNameSessionRepository<S extends Session> extends SessionRepository<S> {
/**
* A session index that contains the current principal name (i.e. username).
@@ -44,7 +43,6 @@ public interface FindByIndexNameSessionRepository<S extends Session>
/**
* Find a {@link Map} of the session id to the {@link Session} of all sessions that
* contain the specified index name index value.
*
* @param indexName the name of the index (i.e.
* {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME})
* @param indexValue the value of the index to search for.
@@ -59,7 +57,6 @@ public interface FindByIndexNameSessionRepository<S extends Session>
* contain the index with the name
* {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME} and the
* specified principal name.
*
* @param principalName the principal name
* @return a {@code Map} (never {@code null}) of the session id to the {@code Session}
* of all sessions that contain the specified principal name. If no results are found,

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2014-2019 the original author or authors.
*
* 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
*
* https://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 org.springframework.session;
/**
* Supported modes of writing the session to session store.
*
* @author Rob Winch
* @author Vedran Pavic
* @since 2.2.0
*/
public enum FlushMode {
/**
* Only writes to session store when {@link SessionRepository#save(Session)} is
* invoked. In a web environment this is typically done as soon as the HTTP response
* is committed.
*/
ON_SAVE,
/**
* Writes to session store as soon as possible. For example
* {@link SessionRepository#createSession()} will write the session to session store.
* Another example is that setting an attribute using
* {@link Session#setAttribute(String, Object)} will also write to session store
* immediately.
*/
IMMEDIATE
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2014-2019 the original author or authors.
*
* 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
*
* https://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 org.springframework.session;
import java.util.Map;
/**
* Strategy interface for resolving the {@link Session}'s indexes.
*
* @param <S> the type of Session being handled
* @author Rob Winch
* @author Vedran Pavic
* @since 2.2.0
* @see FindByIndexNameSessionRepository
*/
public interface IndexResolver<S extends Session> {
/**
* Resolve indexes for the session.
* @param session the session
* @return a map of resolved indexes, never {@code null}
*/
Map<String, String> resolveIndexesFor(S session);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,15 +47,20 @@ import java.util.UUID;
* @since 1.0
*/
public final class MapSession implements Session, Serializable {
/**
* Default {@link #setMaxInactiveInterval(Duration)} (30 minutes).
*/
public static final int DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS = 1800;
private String id;
private final String originalId;
private Map<String, Object> sessionAttrs = new HashMap<>();
private Instant creationTime = Instant.now();
private Instant lastAccessedTime = this.creationTime;
/**
@@ -70,12 +75,10 @@ public final class MapSession implements Session, Serializable {
this(generateId());
}
/**
* Creates a new instance with the specified id. This is preferred to the default
* constructor when the id is known to prevent unnecessary consumption on entropy
* which can be slow.
*
* @param id the identifier to use
*/
public MapSession(String id) {
@@ -85,7 +88,6 @@ public final class MapSession implements Session, Serializable {
/**
* Creates a new instance from the provided {@link Session}.
*
* @param session the {@link Session} to initialize this {@link Session} with. Cannot
* be null.
*/
@@ -95,8 +97,7 @@ public final class MapSession implements Session, Serializable {
}
this.id = session.getId();
this.originalId = this.id;
this.sessionAttrs = new HashMap<>(
session.getAttributeNames().size());
this.sessionAttrs = new HashMap<>(session.getAttributeNames().size());
for (String attrName : session.getAttributeNames()) {
Object attrValue = session.getAttribute(attrName);
if (attrValue != null) {
@@ -205,7 +206,6 @@ public final class MapSession implements Session, Serializable {
* Sets the identifier for this {@link Session}. The id should be a secure random
* generated value to prevent malicious users from guessing this value. The default is
* a secure random generated identifier.
*
* @param id the identifier for this session.
*/
public void setId(String id) {
@@ -227,4 +227,5 @@ public final class MapSession implements Session, Serializable {
}
private static final long serialVersionUID = 7160779239673823561L;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,7 +49,6 @@ public class MapSessionRepository implements SessionRepository<MapSession> {
/**
* Creates a new instance backed by the provided {@link java.util.Map}. This allows
* injecting a distributed {@link java.util.Map}.
*
* @param sessions the {@link java.util.Map} to use. Cannot be null.
*/
public MapSessionRepository(Map<String, Session> sessions) {
@@ -99,8 +98,7 @@ public class MapSessionRepository implements SessionRepository<MapSession> {
public MapSession createSession() {
MapSession result = new MapSession();
if (this.defaultMaxInactiveInterval != null) {
result.setMaxInactiveInterval(
Duration.ofSeconds(this.defaultMaxInactiveInterval));
result.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));
}
return result;
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2014-2019 the original author or authors.
*
* 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
*
* https://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 org.springframework.session;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
/**
* {@link IndexResolver} to resolve the principal name from session attribute named
* {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME} or Spring Security
* context stored in the session under {@code SPRING_SECURITY_CONTEXT} attribute.
*
* @param <S> the type of Session being handled
* @author Vedran Pavic
* @since 2.2.0
*/
public class PrincipalNameIndexResolver<S extends Session> extends SingleIndexResolver<S> {
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
private static final Expression expression = new SpelExpressionParser().parseExpression("authentication?.name");
public PrincipalNameIndexResolver() {
super(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
}
public String resolveIndexValueFor(S session) {
String principalName = session.getAttribute(getIndexName());
if (principalName != null) {
return principalName;
}
Object authentication = session.getAttribute(SPRING_SECURITY_CONTEXT);
if (authentication != null) {
return expression.getValue(authentication, String.class);
}
return null;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,7 +51,6 @@ public class ReactiveMapSessionRepository implements ReactiveSessionRepository<M
/**
* Creates a new instance backed by the provided {@link Map}. This allows injecting a
* distributed {@link Map}.
*
* @param sessions the {@link Map} to use. Cannot be null.
*/
public ReactiveMapSessionRepository(Map<String, Session> sessions) {
@@ -101,8 +100,7 @@ public class ReactiveMapSessionRepository implements ReactiveSessionRepository<M
return Mono.defer(() -> {
MapSession result = new MapSession();
if (this.defaultMaxInactiveInterval != null) {
result.setMaxInactiveInterval(
Duration.ofSeconds(this.defaultMaxInactiveInterval));
result.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));
}
return Mono.just(result);
});

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,7 +36,6 @@ public interface ReactiveSessionRepository<S extends Session> {
* persisted. For example, the implementation returned might keep track of the changes
* ensuring that only the delta needs to be persisted on a save.
* </p>
*
* @return a new {@link Session} that is capable of being persisted by this
* {@link ReactiveSessionRepository}
*/
@@ -51,7 +50,6 @@ public interface ReactiveSessionRepository<S extends Session> {
* returning a {@link Session} that immediately persists any changes. In this case,
* this method may not actually do anything.
* </p>
*
* @param session the {@link Session} to save
* @return indicator of operation completion
*/
@@ -60,7 +58,6 @@ public interface ReactiveSessionRepository<S extends Session> {
/**
* Gets the {@link Session} by the {@link Session#getId()} or null if no
* {@link Session} is found.
*
* @param id the {@link Session#getId()} to lookup
* @return the {@link Session} by the {@link Session#getId()} or null if no
* {@link Session} is found.

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2014-2019 the original author or authors.
*
* 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
*
* https://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 org.springframework.session;
/**
* Supported modes of tracking and saving session changes to session store.
*
* @author Rob Winch
* @author Vedran Pavic
* @since 2.2.0
*/
public enum SaveMode {
/**
* Save only changes made to session, for instance using
* {@link Session#setAttribute(String, Object)}. In highly concurrent environments,
* this mode minimizes the risk of attributes being overwritten during processing of
* parallel requests.
*/
ON_SET_ATTRIBUTE,
/**
* Same as {@link #ON_SET_ATTRIBUTE} with addition of saving attributes that have been
* read using {@link Session#getAttribute(String)}.
*/
ON_GET_ATTRIBUTE,
/**
* Always save all session attributes, regardless of the interaction with the session.
* In highly concurrent environments, this mode increases the risk of attributes being
* overwritten during processing of parallel requests.
*/
ALWAYS
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,13 +32,13 @@ public interface Session {
/**
* Gets a unique string that identifies the {@link Session}.
*
* @return a unique string that identifies the {@link Session}
*/
String getId();
/**
* Changes the session id. After invoking the {@link #getId()} will return a new identifier.
* Changes the session id. After invoking the {@link #getId()} will return a new
* identifier.
* @return the new session id which {@link #getId()} will now return
*/
String changeSessionId();
@@ -46,7 +46,6 @@ public interface Session {
/**
* Gets the Object associated with the specified name or null if no Object is
* associated to that name.
*
* @param <T> the return type of the attribute
* @param attributeName the name of the attribute to get
* @return the Object associated with the specified name or null if no Object is
@@ -65,8 +64,7 @@ public interface Session {
default <T> T getRequiredAttribute(String name) {
T result = getAttribute(name);
if (result == null) {
throw new IllegalArgumentException(
"Required attribute '" + name + "' is missing.");
throw new IllegalArgumentException("Required attribute '" + name + "' is missing.");
}
return result;
}
@@ -88,7 +86,6 @@ public interface Session {
* Gets the attribute names that have a value associated with it. Each value can be
* passed into {@link org.springframework.session.Session#getAttribute(String)} to
* obtain the attribute value.
*
* @return the attribute names that have a value associated with it.
* @see #getAttribute(String)
*/
@@ -98,7 +95,6 @@ public interface Session {
* Sets the attribute value for the provided attribute name. If the attributeValue is
* null, it has the same result as removing the attribute with
* {@link org.springframework.session.Session#removeAttribute(String)} .
*
* @param attributeName the attribute name to set
* @param attributeValue the value of the attribute to set. If null, the attribute
* will be removed.
@@ -113,21 +109,18 @@ public interface Session {
/**
* Gets the time when this session was created.
*
* @return the time when this session was created.
*/
Instant getCreationTime();
/**
* Sets the last accessed time.
*
* @param lastAccessedTime the last accessed time
*/
void setLastAccessedTime(Instant lastAccessedTime);
/**
* Gets the last time this {@link Session} was accessed.
*
* @return the last time the client sent a request associated with the session
*/
Instant getLastAccessedTime();
@@ -135,7 +128,6 @@ public interface Session {
/**
* Sets the maximum inactive interval between requests before this session will be
* invalidated. A negative time indicates that the session will never timeout.
*
* @param interval the amount of time that the {@link Session} should be kept alive
* between client requests.
*/
@@ -144,7 +136,6 @@ public interface Session {
/**
* Gets the maximum inactive interval between requests before this session will be
* invalidated. A negative time indicates that the session will never timeout.
*
* @return the maximum inactive interval between requests before this session will be
* invalidated. A negative time indicates that the session will never timeout.
*/
@@ -152,7 +143,6 @@ public interface Session {
/**
* Returns true if the session is expired.
*
* @return true if the session is expired, else false.
*/
boolean isExpired();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,6 @@ public interface SessionRepository<S extends Session> {
* persisted. For example, the implementation returned might keep track of the changes
* ensuring that only the delta needs to be persisted on a save.
* </p>
*
* @return a new {@link Session} that is capable of being persisted by this
* {@link SessionRepository}
*/
@@ -49,7 +48,6 @@ public interface SessionRepository<S extends Session> {
* returning a {@link Session} that immediately persists any changes. In this case,
* this method may not actually do anything.
* </p>
*
* @param session the {@link Session} to save
*/
void save(S session);
@@ -57,7 +55,6 @@ public interface SessionRepository<S extends Session> {
/**
* Gets the {@link Session} by the {@link Session#getId()} or null if no
* {@link Session} is found.
*
* @param id the {@link org.springframework.session.Session#getId()} to lookup
* @return the {@link Session} by the {@link Session#getId()} or null if no
* {@link Session} is found.
@@ -70,4 +67,5 @@ public interface SessionRepository<S extends Session> {
* @param id the {@link org.springframework.session.Session#getId()} to delete
*/
void deleteById(String id);
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2014-2019 the original author or authors.
*
* 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
*
* https://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 org.springframework.session;
import java.util.Collections;
import java.util.Map;
import org.springframework.util.Assert;
/**
* Base class for {@link IndexResolver}s that resolve a single index.
*
* @param <S> the type of Session being handled
* @author Rob Winch
* @author Vedran Pavic
* @since 2.2.0
*/
public abstract class SingleIndexResolver<S extends Session> implements IndexResolver<S> {
private final String indexName;
protected SingleIndexResolver(String indexName) {
Assert.notNull(indexName, "Index name must not be null");
this.indexName = indexName;
}
protected String getIndexName() {
return this.indexName;
}
public abstract String resolveIndexValueFor(S session);
public final Map<String, String> resolveIndexesFor(S session) {
String indexValue = resolveIndexValueFor(session);
return (indexValue != null) ? Collections.singletonMap(this.indexName, indexValue) : Collections.emptyMap();
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2014-2019 the original author or authors.
*
* 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
*
* https://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 org.springframework.session.config;
import org.springframework.session.ReactiveSessionRepository;
/**
* Strategy that can be used to customize the {@link ReactiveSessionRepository} before it
* is fully initialized, in particular to tune its configuration.
*
* @param <T> the {@link ReactiveSessionRepository} type
* @author Vedran Pavic
* @since 2.2.0
*/
@FunctionalInterface
public interface ReactiveSessionRepositoryCustomizer<T extends ReactiveSessionRepository> {
/**
* Customize the {@link ReactiveSessionRepository}.
* @param sessionRepository the {@link ReactiveSessionRepository} to customize
*/
void customize(T sessionRepository);
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2014-2019 the original author or authors.
*
* 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
*
* https://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 org.springframework.session.config;
import org.springframework.session.SessionRepository;
/**
* Strategy that can be used to customize the {@link SessionRepository} before it is fully
* initialized, in particular to tune its configuration.
*
* @param <T> the {@link SessionRepository} type
* @author Vedran Pavic
* @since 2.2.0
*/
@FunctionalInterface
public interface SessionRepositoryCustomizer<T extends SessionRepository> {
/**
* Customize the {@link SessionRepository}.
* @param sessionRepository the {@link SessionRepository} to customize
*/
void customize(T sessionRepository);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@ import org.springframework.session.events.SessionDestroyedEvent;
*
* {@literal @Bean}
* public MapSessionRepository sessionRepository() {
* return new MapSessionRepository();
* return new MapSessionRepository(new ConcurrentHashMap<>());
* }
*
* }
@@ -74,6 +74,7 @@ import org.springframework.session.events.SessionDestroyedEvent;
@Target({ java.lang.annotation.ElementType.TYPE })
@Documented
@Import(SpringHttpSessionConfiguration.class)
@Configuration
@Configuration(proxyBeanMethods = false)
public @interface EnableSpringHttpSession {
}

View File

@@ -58,7 +58,7 @@ import org.springframework.util.ObjectUtils;
*
* {@literal @Bean}
* public MapSessionRepository sessionRepository() {
* return new MapSessionRepository();
* return new MapSessionRepository(new ConcurrentHashMap<>());
* }
*
* }
@@ -88,7 +88,6 @@ import org.springframework.util.ObjectUtils;
* @author Rob Winch
* @author Vedran Pavic
* @since 1.1
*
* @see EnableSpringHttpSession
*/
@Configuration(proxyBeanMethods = false)
@@ -110,8 +109,7 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
@PostConstruct
public void init() {
CookieSerializer cookieSerializer = (this.cookieSerializer != null)
? this.cookieSerializer
CookieSerializer cookieSerializer = (this.cookieSerializer != null) ? this.cookieSerializer
: createDefaultCookieSerializer();
this.defaultHttpSessionIdResolver.setCookieSerializer(cookieSerializer);
}
@@ -124,21 +122,16 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
@Bean
public <S extends Session> SessionRepositoryFilter<? extends Session> springSessionRepositoryFilter(
SessionRepository<S> sessionRepository) {
SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<>(
sessionRepository);
SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<>(sessionRepository);
sessionRepositoryFilter.setHttpSessionIdResolver(this.httpSessionIdResolver);
return sessionRepositoryFilter;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
if (ClassUtils.isPresent(
"org.springframework.security.web.authentication.RememberMeServices",
null)) {
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (ClassUtils.isPresent("org.springframework.security.web.authentication.RememberMeServices", null)) {
this.usesSpringSessionRememberMeServices = !ObjectUtils
.isEmpty(applicationContext
.getBeanNamesForType(SpringSessionRememberMeServices.class));
.isEmpty(applicationContext.getBeanNamesForType(SpringSessionRememberMeServices.class));
}
}
@@ -170,8 +163,7 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
sessionCookieConfig = this.servletContext.getSessionCookieConfig();
}
catch (UnsupportedOperationException ex) {
this.logger
.warn("Unable to obtain SessionCookieConfig: " + ex.getMessage());
this.logger.warn("Unable to obtain SessionCookieConfig: " + ex.getMessage());
}
if (sessionCookieConfig != null) {
if (sessionCookieConfig.getName() != null) {
@@ -189,8 +181,7 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
}
}
if (this.usesSpringSessionRememberMeServices) {
cookieSerializer.setRememberMeRequestAttribute(
SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);
cookieSerializer.setRememberMeRequestAttribute(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);
}
return cookieSerializer;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,9 +23,10 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Add this annotation to a {@code @Configuration} class to configure a {@code WebSessionManager} for a WebFlux
* application. This annotation assumes a {@code ReactiveSessionRepository} is defined somewhere in the application
* context. If not, it will fail with a clear error message. For example:
* Add this annotation to a {@code @Configuration} class to configure a
* {@code WebSessionManager} for a WebFlux application. This annotation assumes a
* {@code ReactiveSessionRepository} is defined somewhere in the application context. If
* not, it will fail with a clear error message. For example:
*
* <pre>
* <code>
@@ -35,12 +36,11 @@ import org.springframework.context.annotation.Import;
*
* {@literal @Bean}
* public ReactiveSessionRepository sessionRepository() {
* return new ReactiveMapSessionRepository();
* return new ReactiveMapSessionRepository(new ConcurrentHashMap<>());
* }
*
* }
* </code>
* </pre>
* </code> </pre>
*
* @author Greg Turnquist
* @since 2.0
@@ -49,6 +49,7 @@ import org.springframework.context.annotation.Import;
@Target({ java.lang.annotation.ElementType.TYPE })
@Documented
@Import(SpringWebSessionConfiguration.class)
@Configuration
@Configuration(proxyBeanMethods = false)
public @interface EnableSpringWebSession {
}

View File

@@ -27,12 +27,12 @@ import org.springframework.web.server.session.WebSessionIdResolver;
import org.springframework.web.server.session.WebSessionManager;
/**
* Wire up a {@link WebSessionManager} using a Reactive {@link ReactiveSessionRepository} from the application context.
* Wire up a {@link WebSessionManager} using a Reactive {@link ReactiveSessionRepository}
* from the application context.
*
* @author Greg Turnquist
* @author Rob Winch
* @since 2.0
*
* @see EnableSpringWebSession
*/
@Configuration(proxyBeanMethods = false)
@@ -45,10 +45,11 @@ public class SpringWebSessionConfiguration {
private WebSessionIdResolver webSessionIdResolver;
/**
* Configure a {@link WebSessionManager} using a provided {@link ReactiveSessionRepository}.
*
* Configure a {@link WebSessionManager} using a provided
* {@link ReactiveSessionRepository}.
* @param repository a bean that implements {@link ReactiveSessionRepository}.
* @return a configured {@link WebSessionManager} registered with a preconfigured name.
* @return a configured {@link WebSessionManager} registered with a preconfigured
* name.
*/
@Bean(WebHttpHandlerBuilder.WEB_SESSION_MANAGER_BEAN_NAME)
public WebSessionManager webSessionManager(ReactiveSessionRepository<? extends Session> repository) {
@@ -62,4 +63,5 @@ public class SpringWebSessionConfiguration {
return manager;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,7 +44,6 @@ public abstract class AbstractSessionEvent extends ApplicationEvent {
* Gets the {@link Session} that was destroyed. For some {@link SessionRepository}
* implementations it may not be possible to get the original session in which case
* this may be null.
*
* @param <S> the type of Session
* @return the expired {@link Session} or null if the data store does not support
* obtaining it

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,23 +36,18 @@ import org.springframework.session.SessionRepository;
* @author Vedran Pavic
* @since 1.3
*/
class SpringSessionBackedSessionInformation<S extends Session>
extends SessionInformation {
class SpringSessionBackedSessionInformation<S extends Session> extends SessionInformation {
static final String EXPIRED_ATTR = SpringSessionBackedSessionInformation.class
.getName() + ".EXPIRED";
static final String EXPIRED_ATTR = SpringSessionBackedSessionInformation.class.getName() + ".EXPIRED";
private static final Log logger = LogFactory
.getLog(SpringSessionBackedSessionInformation.class);
private static final Log logger = LogFactory.getLog(SpringSessionBackedSessionInformation.class);
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
private final SessionRepository<S> sessionRepository;
SpringSessionBackedSessionInformation(S session,
SessionRepository<S> sessionRepository) {
super(resolvePrincipal(session), session.getId(),
Date.from(session.getLastAccessedTime()));
SpringSessionBackedSessionInformation(S session, SessionRepository<S> sessionRepository) {
super(resolvePrincipal(session), session.getId(), Date.from(session.getLastAccessedTime()));
this.sessionRepository = sessionRepository;
Boolean expired = session.getAttribute(EXPIRED_ATTR);
if (Boolean.TRUE.equals(expired)) {
@@ -62,20 +57,16 @@ class SpringSessionBackedSessionInformation<S extends Session>
/**
* Tries to determine the principal's name from the given Session.
*
* @param session the session
* @return the principal's name, or empty String if it couldn't be determined
*/
private static String resolvePrincipal(Session session) {
String principalName = session
.getAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
String principalName = session.getAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
if (principalName != null) {
return principalName;
}
SecurityContext securityContext = session
.getAttribute(SPRING_SECURITY_CONTEXT);
if (securityContext != null
&& securityContext.getAuthentication() != null) {
SecurityContext securityContext = session.getAttribute(SPRING_SECURITY_CONTEXT);
if (securityContext != null && securityContext.getAuthentication() != null) {
return securityContext.getAuthentication().getName();
}
return "";
@@ -84,9 +75,8 @@ class SpringSessionBackedSessionInformation<S extends Session>
@Override
public void expireNow() {
if (logger.isDebugEnabled()) {
logger.debug("Expiring session " + getSessionId() + " for user '"
+ getPrincipal() + "', presumably because maximum allowed concurrent "
+ "sessions was exceeded");
logger.debug("Expiring session " + getSessionId() + " for user '" + getPrincipal()
+ "', presumably because maximum allowed concurrent " + "sessions was exceeded");
}
super.expireNow();
S session = this.sessionRepository.findById(getSessionId());
@@ -95,8 +85,7 @@ class SpringSessionBackedSessionInformation<S extends Session>
this.sessionRepository.save(session);
}
else {
logger.info("Could not find Session with id " + getSessionId()
+ " to mark as expired");
logger.info("Could not find Session with id " + getSessionId() + " to mark as expired");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,14 +16,13 @@
package org.springframework.session.security;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.util.Assert;
@@ -44,13 +43,11 @@ import org.springframework.util.Assert;
* @author Vedran Pavic
* @since 1.3
*/
public class SpringSessionBackedSessionRegistry<S extends Session>
implements SessionRegistry {
public class SpringSessionBackedSessionRegistry<S extends Session> implements SessionRegistry {
private final FindByIndexNameSessionRepository<S> sessionRepository;
public SpringSessionBackedSessionRegistry(
FindByIndexNameSessionRepository<S> sessionRepository) {
public SpringSessionBackedSessionRegistry(FindByIndexNameSessionRepository<S> sessionRepository) {
Assert.notNull(sessionRepository, "sessionRepository cannot be null");
this.sessionRepository = sessionRepository;
}
@@ -63,16 +60,13 @@ public class SpringSessionBackedSessionRegistry<S extends Session>
}
@Override
public List<SessionInformation> getAllSessions(Object principal,
boolean includeExpiredSessions) {
Collection<S> sessions = this.sessionRepository
.findByPrincipalName(name(principal)).values();
public List<SessionInformation> getAllSessions(Object principal, boolean includeExpiredSessions) {
Collection<S> sessions = this.sessionRepository.findByPrincipalName(name(principal)).values();
List<SessionInformation> infos = new ArrayList<>();
for (S session : sessions) {
if (includeExpiredSessions || !Boolean.TRUE.equals(session
.getAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR))) {
infos.add(new SpringSessionBackedSessionInformation<>(session,
this.sessionRepository));
if (includeExpiredSessions
|| !Boolean.TRUE.equals(session.getAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR))) {
infos.add(new SpringSessionBackedSessionInformation<>(session, this.sessionRepository));
}
}
return infos;
@@ -82,8 +76,7 @@ public class SpringSessionBackedSessionRegistry<S extends Session>
public SessionInformation getSessionInformation(String sessionId) {
S session = this.sessionRepository.findById(sessionId);
if (session != null) {
return new SpringSessionBackedSessionInformation<>(session,
this.sessionRepository);
return new SpringSessionBackedSessionInformation<>(session, this.sessionRepository);
}
return null;
}
@@ -111,19 +104,13 @@ public class SpringSessionBackedSessionRegistry<S extends Session>
/**
* Derives a String name for the given principal.
*
* @param principal as provided by Spring Security
* @return name of the principal, or its {@code toString()} representation if no name
* could be derived
*/
protected String name(Object principal) {
if (principal instanceof UserDetails) {
return ((UserDetails) principal).getUsername();
}
if (principal instanceof Principal) {
return ((Principal) principal).getName();
}
return principal.toString();
// We are reusing the logic from AbstractAuthenticationToken#getName
return new TestingAuthenticationToken(principal, null).getName();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,21 +36,19 @@ import org.springframework.util.Assert;
* @author Vedran Pavic
* @since 1.3.0
*/
public class SpringSessionRememberMeServices
implements RememberMeServices, LogoutHandler {
public class SpringSessionRememberMeServices implements RememberMeServices, LogoutHandler {
/**
* Remember-me login request attribute name.
*/
public static final String REMEMBER_ME_LOGIN_ATTR = SpringSessionRememberMeServices.class
.getName() + "REMEMBER_ME_LOGIN_ATTR";
public static final String REMEMBER_ME_LOGIN_ATTR = SpringSessionRememberMeServices.class.getName()
+ "REMEMBER_ME_LOGIN_ATTR";
private static final String DEFAULT_REMEMBERME_PARAMETER = "remember-me";
private static final int THIRTY_DAYS_SECONDS = 2592000;
private static final Log logger = LogFactory
.getLog(SpringSessionRememberMeServices.class);
private static final Log logger = LogFactory.getLog(SpringSessionRememberMeServices.class);
private String rememberMeParameterName = DEFAULT_REMEMBERME_PARAMETER;
@@ -58,25 +56,20 @@ public class SpringSessionRememberMeServices
private int validitySeconds = THIRTY_DAYS_SECONDS;
private String sessionAttrToDeleteOnLoginFail = HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY;
@Override
public final Authentication autoLogin(HttpServletRequest request,
HttpServletResponse response) {
public final Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) {
return null;
}
@Override
public final void loginFail(HttpServletRequest request,
HttpServletResponse response) {
public final void loginFail(HttpServletRequest request, HttpServletResponse response) {
logout(request);
}
@Override
public final void loginSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication successfulAuthentication) {
if (!this.alwaysRemember
&& !rememberMeRequested(request, this.rememberMeParameterName)) {
public final void loginSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication successfulAuthentication) {
if (!this.alwaysRemember && !rememberMeRequested(request, this.rememberMeParameterName)) {
logger.debug("Remember-me login not requested.");
return;
}
@@ -103,8 +96,7 @@ public class SpringSessionRememberMeServices
}
}
if (logger.isDebugEnabled()) {
logger.debug("Did not send remember-me cookie (principal did not set "
+ "parameter '" + parameter + "')");
logger.debug("Did not send remember-me cookie (principal did not set " + "parameter '" + parameter + "')");
}
return false;
}
@@ -116,8 +108,7 @@ public class SpringSessionRememberMeServices
* @param rememberMeParameterName the request parameter
*/
public void setRememberMeParameterName(String rememberMeParameterName) {
Assert.hasText(rememberMeParameterName,
"rememberMeParameterName cannot be empty or null");
Assert.hasText(rememberMeParameterName, "rememberMeParameterName cannot be empty or null");
this.rememberMeParameterName = rememberMeParameterName;
}
@@ -130,8 +121,7 @@ public class SpringSessionRememberMeServices
}
@Override
public void logout(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) {
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
logout(request);
}
@@ -139,7 +129,8 @@ public class SpringSessionRememberMeServices
logger.debug("Interactive login attempt was unsuccessful.");
HttpSession session = request.getSession(false);
if (session != null) {
session.removeAttribute(this.sessionAttrToDeleteOnLoginFail);
session.removeAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@ import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration.Dynamic;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.springframework.context.ApplicationContext;
import org.springframework.core.Conventions;
@@ -71,8 +70,7 @@ import org.springframework.web.filter.DelegatingFilterProxy;
*
*/
@Order(100)
public abstract class AbstractHttpSessionApplicationInitializer
implements WebApplicationInitializer {
public abstract class AbstractHttpSessionApplicationInitializer implements WebApplicationInitializer {
private static final String SERVLET_CONTEXT_PREFIX = "org.springframework.web.servlet.FrameworkServlet.CONTEXT.";
@@ -98,17 +96,15 @@ public abstract class AbstractHttpSessionApplicationInitializer
/**
* Creates a new instance that will instantiate the {@link ContextLoaderListener} with
* the specified classes.
*
* @param configurationClasses {@code @Configuration} classes that will be used to
* configure the context
*/
protected AbstractHttpSessionApplicationInitializer(
Class<?>... configurationClasses) {
protected AbstractHttpSessionApplicationInitializer(Class<?>... configurationClasses) {
this.configurationClasses = configurationClasses;
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
public void onStartup(ServletContext servletContext) {
beforeSessionRepositoryFilter(servletContext);
if (this.configurationClasses != null) {
AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
@@ -125,8 +121,7 @@ public abstract class AbstractHttpSessionApplicationInitializer
*/
private void insertSessionRepositoryFilter(ServletContext servletContext) {
String filterName = DEFAULT_FILTER_NAME;
DelegatingFilterProxy springSessionRepositoryFilter = new DelegatingFilterProxy(
filterName);
DelegatingFilterProxy springSessionRepositoryFilter = new DelegatingFilterProxy(filterName);
String contextAttribute = getWebApplicationContextAttribute();
if (contextAttribute != null) {
springSessionRepositoryFilter.setContextAttribute(contextAttribute);
@@ -138,7 +133,6 @@ public abstract class AbstractHttpSessionApplicationInitializer
* Inserts the provided {@link Filter}s before existing {@link Filter}s using default
* generated names, {@link #getSessionDispatcherTypes()}, and
* {@link #isAsyncSessionSupported()}.
*
* @param servletContext the {@link ServletContext} to use
* @param filters the {@link Filter}s to register
*/
@@ -150,7 +144,6 @@ public abstract class AbstractHttpSessionApplicationInitializer
* Inserts the provided {@link Filter}s after existing {@link Filter}s using default
* generated names, {@link #getSessionDispatcherTypes()}, and
* {@link #isAsyncSessionSupported()}.
*
* @param servletContext the {@link ServletContext} to use
* @param filters the {@link Filter}s to register
*/
@@ -161,22 +154,18 @@ public abstract class AbstractHttpSessionApplicationInitializer
/**
* Registers the provided {@link Filter}s using default generated names,
* {@link #getSessionDispatcherTypes()}, and {@link #isAsyncSessionSupported()}.
*
* @param servletContext the {@link ServletContext} to use
* @param insertBeforeOtherFilters if true, will insert the provided {@link Filter}s
* before other {@link Filter}s. Otherwise, will insert the {@link Filter}s after
* other {@link Filter}s.
* @param filters the {@link Filter}s to register
*/
private void registerFilters(ServletContext servletContext,
boolean insertBeforeOtherFilters, Filter... filters) {
private void registerFilters(ServletContext servletContext, boolean insertBeforeOtherFilters, Filter... filters) {
Assert.notEmpty(filters, "filters cannot be null or empty");
for (Filter filter : filters) {
if (filter == null) {
throw new IllegalArgumentException(
"filters cannot contain null values. Got "
+ Arrays.asList(filters));
throw new IllegalArgumentException("filters cannot contain null values. Got " + Arrays.asList(filters));
}
String filterName = Conventions.getVariableName(filter);
registerFilter(servletContext, insertBeforeOtherFilters, filterName, filter);
@@ -186,25 +175,22 @@ public abstract class AbstractHttpSessionApplicationInitializer
/**
* Registers the provided filter using the {@link #isAsyncSessionSupported()} and
* {@link #getSessionDispatcherTypes()}.
*
* @param servletContext the servlet context
* @param insertBeforeOtherFilters should this Filter be inserted before or after
* other {@link Filter}
* @param filterName the filter name
* @param filter the filter
*/
private void registerFilter(ServletContext servletContext,
boolean insertBeforeOtherFilters, String filterName, Filter filter) {
private void registerFilter(ServletContext servletContext, boolean insertBeforeOtherFilters, String filterName,
Filter filter) {
Dynamic registration = servletContext.addFilter(filterName, filter);
if (registration == null) {
throw new IllegalStateException(
"Duplicate Filter registration for '" + filterName
+ "'. Check to ensure the Filter is only configured once.");
throw new IllegalStateException("Duplicate Filter registration for '" + filterName
+ "'. Check to ensure the Filter is only configured once.");
}
registration.setAsyncSupported(isAsyncSessionSupported());
EnumSet<DispatcherType> dispatcherTypes = getSessionDispatcherTypes();
registration.addMappingForUrlPatterns(dispatcherTypes, !insertBeforeOtherFilters,
"/*");
registration.addMappingForUrlPatterns(dispatcherTypes, !insertBeforeOtherFilters, "/*");
}
/**
@@ -218,7 +204,6 @@ public abstract class AbstractHttpSessionApplicationInitializer
* {@link ApplicationContext} is used to look up the springSessionRepositoryFilter
* bean.
* </p>
*
* @return the {@link DelegatingFilterProxy#getContextAttribute()} or null if the
* parent {@link ApplicationContext} should be used
*/
@@ -241,7 +226,6 @@ public abstract class AbstractHttpSessionApplicationInitializer
* name, you can return "dispatcher" from this method to use the DispatcherServlet's
* {@link WebApplicationContext}.
* </p>
*
* @return the {@code <servlet-name>} of the DispatcherServlet to use its
* {@link WebApplicationContext} or null (default) to use the parent
* {@link ApplicationContext}.
@@ -271,17 +255,16 @@ public abstract class AbstractHttpSessionApplicationInitializer
* @return the {@link DispatcherType} for the filter
*/
protected EnumSet<DispatcherType> getSessionDispatcherTypes() {
return EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR,
DispatcherType.ASYNC);
return EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.ASYNC);
}
/**
* Determine if the springSessionRepositoryFilter should be marked as supporting
* asynch. Default is true.
*
* @return true if springSessionRepositoryFilter should be marked as supporting asynch
*/
protected boolean isAsyncSessionSupported() {
return true;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -63,8 +63,8 @@ import org.springframework.session.web.http.CookieSerializer.CookieValue;
*/
public final class CookieHttpSessionIdResolver implements HttpSessionIdResolver {
private static final String WRITTEN_SESSION_ID_ATTR = CookieHttpSessionIdResolver.class
.getName().concat(".WRITTEN_SESSION_ID_ATTR");
private static final String WRITTEN_SESSION_ID_ATTR = CookieHttpSessionIdResolver.class.getName()
.concat(".WRITTEN_SESSION_ID_ATTR");
private CookieSerializer cookieSerializer = new DefaultCookieSerializer();
@@ -74,14 +74,12 @@ public final class CookieHttpSessionIdResolver implements HttpSessionIdResolver
}
@Override
public void setSessionId(HttpServletRequest request, HttpServletResponse response,
String sessionId) {
public void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId) {
if (sessionId.equals(request.getAttribute(WRITTEN_SESSION_ID_ATTR))) {
return;
}
request.setAttribute(WRITTEN_SESSION_ID_ATTR, sessionId);
this.cookieSerializer
.writeCookieValue(new CookieValue(request, response, sessionId));
this.cookieSerializer.writeCookieValue(new CookieValue(request, response, sessionId));
}
@Override
@@ -91,7 +89,6 @@ public final class CookieHttpSessionIdResolver implements HttpSessionIdResolver
/**
* Sets the {@link CookieSerializer} to be used.
*
* @param cookieSerializer the cookieSerializer to set. Cannot be null.
*/
public void setCookieSerializer(CookieSerializer cookieSerializer) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,7 +32,6 @@ public interface CookieSerializer {
/**
* Writes a given {@link CookieValue} to the provided {@link HttpServletResponse}.
*
* @param cookieValue the {@link CookieValue} to write to
* {@link CookieValue#getResponse()}. Cannot be null.
*/
@@ -43,7 +42,6 @@ public interface CookieSerializer {
* List since there can be multiple {@link Cookie} in a single request with a matching
* name. For example, one Cookie may have a path of / and another of /context, but the
* path is not transmitted in the request.
*
* @param request the {@link HttpServletRequest} to read the cookie from. Cannot be
* null.
* @return the values of all the matching cookies
@@ -70,7 +68,6 @@ public interface CookieSerializer {
/**
* Creates a new instance.
*
* @param request the {@link HttpServletRequest} to use. Useful for determining
* the context in which the cookie is set. Cannot be null.
* @param response the {@link HttpServletResponse} to use.
@@ -78,8 +75,7 @@ public interface CookieSerializer {
* modified by the {@link CookieSerializer} when writing to the actual cookie so
* long as the original value is returned when the cookie is read.
*/
public CookieValue(HttpServletRequest request, HttpServletResponse response,
String cookieValue) {
public CookieValue(HttpServletRequest request, HttpServletResponse response, String cookieValue) {
this.request = request;
this.response = response;
this.cookieValue = cookieValue;
@@ -108,7 +104,6 @@ public interface CookieSerializer {
* The value to be written. This value may be modified by the
* {@link CookieSerializer} before written to the cookie. However, the value must
* be the same as the original when it is read back in.
*
* @return the value to be written
*/
public String getCookieValue() {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,9 +16,10 @@
package org.springframework.session.web.http;
import java.time.Clock;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Base64;
@@ -62,6 +63,8 @@ public class DefaultCookieSerializer implements CookieSerializer {
domainValid.set('-');
}
private Clock clock = Clock.systemUTC();
private String cookieName = "SESSION";
private Boolean useSecureCookie;
@@ -97,15 +100,12 @@ public class DefaultCookieSerializer implements CookieSerializer {
if (cookies != null) {
for (Cookie cookie : cookies) {
if (this.cookieName.equals(cookie.getName())) {
String sessionId = (this.useBase64Encoding
? base64Decode(cookie.getValue())
: cookie.getValue());
String sessionId = (this.useBase64Encoding ? base64Decode(cookie.getValue()) : cookie.getValue());
if (sessionId == null) {
continue;
}
if (this.jvmRoute != null && sessionId.endsWith(this.jvmRoute)) {
sessionId = sessionId.substring(0,
sessionId.length() - this.jvmRoute.length());
sessionId = sessionId.substring(0, sessionId.length() - this.jvmRoute.length());
}
matchingCookieValues.add(sessionId);
}
@@ -124,7 +124,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
public void writeCookieValue(CookieValue cookieValue) {
HttpServletRequest request = cookieValue.getRequest();
HttpServletResponse response = cookieValue.getResponse();
StringBuilder sb = new StringBuilder();
sb.append(this.cookieName).append('=');
String value = getValue(cookieValue);
@@ -135,11 +134,9 @@ public class DefaultCookieSerializer implements CookieSerializer {
int maxAge = getMaxAge(cookieValue);
if (maxAge > -1) {
sb.append("; Max-Age=").append(cookieValue.getCookieMaxAge());
OffsetDateTime expires = (maxAge != 0)
? OffsetDateTime.now().plusSeconds(maxAge)
: Instant.EPOCH.atOffset(ZoneOffset.UTC);
sb.append("; Expires=")
.append(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME));
ZonedDateTime expires = (maxAge != 0) ? ZonedDateTime.now(this.clock).plusSeconds(maxAge)
: Instant.EPOCH.atZone(ZoneOffset.UTC);
sb.append("; Expires=").append(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME));
}
String domain = getDomainName(request);
if (domain != null && domain.length() > 0) {
@@ -160,7 +157,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
if (this.sameSite != null) {
sb.append("; SameSite=").append(this.sameSite);
}
response.addHeader("Set-Cookie", sb.toString());
}
@@ -214,10 +210,8 @@ public class DefaultCookieSerializer implements CookieSerializer {
char[] chars = value.toCharArray();
for (int i = start; i < end; i++) {
char c = chars[i];
if (c < 0x21 || c == 0x22 || c == 0x2c || c == 0x3b || c == 0x5c
|| c == 0x7f) {
throw new IllegalArgumentException(
"Invalid character in cookie value: " + Integer.toString(c));
if (c < 0x21 || c == 0x22 || c == 0x2c || c == 0x3b || c == 0x5c || c == 0x7f) {
throw new IllegalArgumentException("Invalid character in cookie value: " + c);
}
}
}
@@ -225,8 +219,8 @@ public class DefaultCookieSerializer implements CookieSerializer {
private int getMaxAge(CookieValue cookieValue) {
int maxAge = cookieValue.getCookieMaxAge();
if (maxAge < 0) {
if (this.rememberMeRequestAttribute != null && cookieValue.getRequest()
.getAttribute(this.rememberMeRequestAttribute) != null) {
if (this.rememberMeRequestAttribute != null
&& cookieValue.getRequest().getAttribute(this.rememberMeRequestAttribute) != null) {
// the cookie is only written at time of session creation, so we rely on
// session expiration rather than cookie expiration if remember me is
// enabled
@@ -247,8 +241,7 @@ public class DefaultCookieSerializer implements CookieSerializer {
while (i < chars.length) {
prev = cur;
cur = chars[i];
if (!domainValid.get(cur)
|| ((prev == '.' || prev == -1) && (cur == '.' || cur == '-'))
if (!domainValid.get(cur) || ((prev == '.' || prev == -1) && (cur == '.' || cur == '-'))
|| (prev == '-' && cur == '.')) {
throw new IllegalArgumentException("Invalid cookie domain: " + domain);
}
@@ -267,10 +260,13 @@ public class DefaultCookieSerializer implements CookieSerializer {
}
}
void setClock(Clock clock) {
this.clock = clock.withZone(ZoneOffset.UTC);
}
/**
* Sets if a Cookie marked as secure should be used. The default is to use the value
* of {@link HttpServletRequest#isSecure()}.
*
* @param useSecureCookie determines if the cookie should be marked as secure.
*/
public void setUseSecureCookie(boolean useSecureCookie) {
@@ -279,7 +275,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
/**
* Sets if a Cookie marked as HTTP Only should be used. The default is true.
*
* @param useHttpOnlyCookie determines if the cookie should be marked as HTTP Only.
*/
public void setUseHttpOnlyCookie(boolean useHttpOnlyCookie) {
@@ -296,7 +291,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
/**
* Sets the path of the Cookie. The default is to use the context path from the
* {@link HttpServletRequest}.
*
* @param cookiePath the path of the Cookie. If null, the default of the context path
* will be used.
*/
@@ -314,8 +308,7 @@ public class DefaultCookieSerializer implements CookieSerializer {
/**
* Sets the maxAge property of the Cookie. The default is to delete the cookie when
* the browser is closed.
*
* @param cookieMaxAge the maxAge property of the Cookie
* @param cookieMaxAge the maxAge property of the Cookie (defined in seconds)
*/
public void setCookieMaxAge(int cookieMaxAge) {
this.cookieMaxAge = cookieMaxAge;
@@ -325,14 +318,12 @@ public class DefaultCookieSerializer implements CookieSerializer {
* Sets an explicit Domain Name. This allow the domain of "example.com" to be used
* when the request comes from www.example.com. This allows for sharing the cookie
* across subdomains. The default is to use the current domain.
*
* @param domainName the name of the domain to use. (i.e. "example.com")
* @throws IllegalStateException if the domainNamePattern is also set
*/
public void setDomainName(String domainName) {
if (this.domainNamePattern != null) {
throw new IllegalStateException(
"Cannot set both domainName and domainNamePattern");
throw new IllegalStateException("Cannot set both domainName and domainNamePattern");
}
this.domainName = domainName;
}
@@ -362,18 +353,15 @@ public class DefaultCookieSerializer implements CookieSerializer {
* <li>localhost - null</li>
* <li>127.0.1.1 - null</li>
* </ul>
*
* @param domainNamePattern the case insensitive pattern to extract the domain name
* with
* @throws IllegalStateException if the domainName is also set
*/
public void setDomainNamePattern(String domainNamePattern) {
if (this.domainName != null) {
throw new IllegalStateException(
"Cannot set both domainName and domainNamePattern");
throw new IllegalStateException("Cannot set both domainName and domainNamePattern");
}
this.domainNamePattern = Pattern.compile(domainNamePattern,
Pattern.CASE_INSENSITIVE);
this.domainNamePattern = Pattern.compile(domainNamePattern, Pattern.CASE_INSENSITIVE);
}
/**
@@ -390,7 +378,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
* To use set a custom route on each JVM instance and setup a frontend proxy to
* forward all requests to the JVM based on the route.
* </p>
*
* @param jvmRoute the JVM Route to use (i.e. "node01jvmA", "n01ja", etc)
*/
public void setJvmRoute(String jvmRoute) {
@@ -401,7 +388,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
* Set if the Base64 encoding of cookie value should be used. This is valuable in
* order to support <a href="https://tools.ietf.org/html/rfc6265">RFC 6265</a> which
* recommends using Base 64 encoding to the cookie value.
*
* @param useBase64Encoding the flag to indicate whether to use Base64 encoding
*/
public void setUseBase64Encoding(boolean useBase64Encoding) {
@@ -416,8 +402,7 @@ public class DefaultCookieSerializer implements CookieSerializer {
*/
public void setRememberMeRequestAttribute(String rememberMeRequestAttribute) {
if (rememberMeRequestAttribute == null) {
throw new IllegalArgumentException(
"rememberMeRequestAttribute cannot be null");
throw new IllegalArgumentException("rememberMeRequestAttribute cannot be null");
}
this.rememberMeRequestAttribute = rememberMeRequestAttribute;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -98,13 +98,11 @@ public class HeaderHttpSessionIdResolver implements HttpSessionIdResolver {
@Override
public List<String> resolveSessionIds(HttpServletRequest request) {
String headerValue = request.getHeader(this.headerName);
return (headerValue != null) ? Collections.singletonList(headerValue)
: Collections.emptyList();
return (headerValue != null) ? Collections.singletonList(headerValue) : Collections.emptyList();
}
@Override
public void setSessionId(HttpServletRequest request, HttpServletResponse response,
String sessionId) {
public void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId) {
response.setHeader(this.headerName, sessionId);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,11 +65,7 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
this.servletContext = servletContext;
}
public void setSession(S session) {
this.session = session;
}
public S getSession() {
S getSession() {
return this.session;
}
@@ -142,8 +138,8 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
if (value != oldValue) {
if (oldValue instanceof HttpSessionBindingListener) {
try {
((HttpSessionBindingListener) oldValue).valueUnbound(
new HttpSessionBindingEvent(this, name, oldValue));
((HttpSessionBindingListener) oldValue)
.valueUnbound(new HttpSessionBindingEvent(this, name, oldValue));
}
catch (Throwable th) {
logger.error("Error invoking session binding event listener", th);
@@ -151,8 +147,7 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
}
if (value instanceof HttpSessionBindingListener) {
try {
((HttpSessionBindingListener) value)
.valueBound(new HttpSessionBindingEvent(this, name, value));
((HttpSessionBindingListener) value).valueBound(new HttpSessionBindingEvent(this, name, value));
}
catch (Throwable th) {
logger.error("Error invoking session binding event listener", th);
@@ -173,8 +168,7 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
this.session.removeAttribute(name);
if (oldValue instanceof HttpSessionBindingListener) {
try {
((HttpSessionBindingListener) oldValue)
.valueUnbound(new HttpSessionBindingEvent(this, name, oldValue));
((HttpSessionBindingListener) oldValue).valueUnbound(new HttpSessionBindingEvent(this, name, oldValue));
}
catch (Throwable th) {
logger.error("Error invoking session binding event listener", th);
@@ -193,20 +187,19 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
this.invalidated = true;
}
public void setNew(boolean isNew) {
this.old = !isNew;
}
@Override
public boolean isNew() {
checkState();
return !this.old;
}
void markNotNew() {
this.old = true;
}
private void checkState() {
if (this.invalidated) {
throw new IllegalStateException(
"The HttpSession has already be invalidated.");
throw new IllegalStateException("The HttpSession has already be invalidated.");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,8 +49,7 @@ public interface HttpSessionIdResolver {
* @param response the current response
* @param sessionId the session id
*/
void setSessionId(HttpServletRequest request, HttpServletResponse response,
String sessionId);
void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId);
/**
* Instruct the client to end the current session. This method is invoked when a

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,9 +25,6 @@ import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Base class for response wrappers which encapsulate the logic for handling an event when
* the {@link javax.servlet.http.HttpServletResponse} is committed.
@@ -36,7 +33,6 @@ import org.apache.commons.logging.LogFactory;
* @since 1.0
*/
abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
private final Log logger = LogFactory.getLog(getClass());
private boolean disableOnCommitted;
@@ -68,6 +64,12 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
super.addHeader(name, value);
}
@Override
public void setContentLengthLong(long len) {
setContentLength(len);
super.setContentLengthLong(len);
}
@Override
public void setContentLength(int len) {
setContentLength((long) len);
@@ -85,7 +87,7 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
* {@link javax.servlet.http.HttpServletResponse} is committed. This can be useful in
* the event that Async Web Requests are made.
*/
public void disableOnResponseCommitted() {
private void disableOnResponseCommitted() {
this.disableOnCommitted = true;
}
@@ -204,13 +206,11 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
/**
* Adds the contentLengthToWrite to the total contentWritten size and checks to see if
* the response should be written.
*
* @param contentLengthToWrite the size of the content that is about to be written.
*/
private void checkContentLength(long contentLengthToWrite) {
this.contentWritten += contentLengthToWrite;
boolean isBodyFullyWritten = this.contentLength > 0
&& this.contentWritten >= this.contentLength;
boolean isBodyFullyWritten = this.contentLength > 0 && this.contentWritten >= this.contentLength;
int bufferSize = getBufferSize();
boolean requiresFlush = bufferSize > 0 && this.contentWritten >= bufferSize;
if (isBodyFullyWritten || requiresFlush) {
@@ -234,9 +234,11 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
* calling the prior to methods that commit the response. We delegate all methods to
* the original {@link java.io.PrintWriter} to ensure that the behavior is as close to
* the original {@link java.io.PrintWriter} as possible. See SEC-2039
*
* @author Rob Winch
*/
private class SaveContextPrintWriter extends PrintWriter {
private final PrintWriter delegate;
SaveContextPrintWriter(PrintWriter delegate) {
@@ -466,6 +468,7 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
trackContentLength(c);
return this.delegate.append(c);
}
}
/**
@@ -477,6 +480,7 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
* @author Rob Winch
*/
private class SaveContextServletOutputStream extends ServletOutputStream {
private final ServletOutputStream delegate;
SaveContextServletOutputStream(ServletOutputStream delegate) {
@@ -634,5 +638,7 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
public void setWriteListener(WriteListener writeListener) {
this.delegate.setWriteListener(writeListener);
}
}
}

View File

@@ -37,19 +37,18 @@ import javax.servlet.http.HttpServletResponse;
* @since 1.0
*/
abstract class OncePerRequestFilter implements Filter {
/**
* Suffix that gets appended to the filter name for the "already filtered" request
* attribute.
*/
public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED";
private String alreadyFilteredAttributeName = getClass().getName()
.concat(ALREADY_FILTERED_SUFFIX);
private String alreadyFilteredAttributeName = getClass().getName().concat(ALREADY_FILTERED_SUFFIX);
/**
* This {@code doFilter} implementation stores a request attribute for
* "already filtered", proceeding without filtering again if the attribute is already
* there.
* This {@code doFilter} implementation stores a request attribute for "already
* filtered", proceeding without filtering again if the attribute is already there.
* @param request the request
* @param response the response
* @param filterChain the filter chain
@@ -57,24 +56,22 @@ abstract class OncePerRequestFilter implements Filter {
* @throws IOException in case of I/O operation exception
*/
@Override
public final void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (!(request instanceof HttpServletRequest)
|| !(response instanceof HttpServletResponse)) {
throw new ServletException(
"OncePerRequestFilter just supports HTTP requests");
if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
throw new ServletException("OncePerRequestFilter just supports HTTP requests");
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String alreadyFilteredAttributeName = this.alreadyFilteredAttributeName;
alreadyFilteredAttributeName = updateForErrorDispatch(
alreadyFilteredAttributeName, request);
boolean hasAlreadyFilteredAttribute = request
.getAttribute(alreadyFilteredAttributeName) != null;
String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
boolean hasAlreadyFilteredAttribute = request.getAttribute(alreadyFilteredAttributeName) != null;
if (hasAlreadyFilteredAttribute) {
if (DispatcherType.ERROR.equals(request.getDispatcherType())) {
doFilterNestedErrorDispatch(httpRequest, httpResponse, filterChain);
return;
}
// Proceed without invoking this filter...
filterChain.doFilter(request, response);
}
@@ -91,15 +88,39 @@ abstract class OncePerRequestFilter implements Filter {
}
}
private String updateForErrorDispatch(String alreadyFilteredAttributeName,
ServletRequest request) {
// Jetty does ERROR dispatch within sendError, so request attribute is still present
// Use a separate attribute for ERROR dispatches
if (DispatcherType.ERROR.equals(request.getDispatcherType())
&& request.getAttribute(alreadyFilteredAttributeName) != null) {
return alreadyFilteredAttributeName + ".ERROR";
}
return alreadyFilteredAttributeName;
/**
* Return the name of the request attribute that identifies that a request is already
* filtered.
* <p>
* The default implementation takes the configured name of the concrete filter
* instance and appends ".FILTERED". If the filter is not fully initialized, it falls
* back to its class name.
* @return the name of request attribute indicating already filtered request
* @see #ALREADY_FILTERED_SUFFIX
*/
protected String getAlreadyFilteredAttributeName() {
return this.alreadyFilteredAttributeName;
}
/**
* Typically an ERROR dispatch happens after the REQUEST dispatch completes, and the
* filter chain starts anew. On some servers however the ERROR dispatch may be nested
* within the REQUEST dispatch, e.g. as a result of calling {@code sendError} on the
* response. In that case we are still in the filter chain, on the same thread, but
* the request and response have been switched to the original, unwrapped ones.
* <p>
* Sub-classes may use this method to filter such nested ERROR dispatches and re-apply
* wrapping on the request or response. {@code ThreadLocal} context, if any, should
* still be active as we are still nested within the filter chain.
* @param request the request
* @param response the response
* @param filterChain the filter chain
* @throws ServletException if request is not HTTP request
* @throws IOException in case of I/O operation exception
*/
protected void doFilterNestedErrorDispatch(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
doFilter(request, response, filterChain);
}
/**
@@ -108,7 +129,6 @@ abstract class OncePerRequestFilter implements Filter {
* <p>
* Provides HttpServletRequest and HttpServletResponse arguments instead of the
* default ServletRequest and ServletResponse ones.
*
* @param request the request
* @param response the response
* @param filterChain the FilterChain
@@ -116,9 +136,8 @@ abstract class OncePerRequestFilter implements Filter {
* @throws IOException thrown when an I/O exception of some sort has occurred
* @see Filter#doFilter
*/
protected abstract void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException;
protected abstract void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException;
@Override
public void init(FilterConfig config) {
@@ -127,4 +146,5 @@ abstract class OncePerRequestFilter implements Filter {
@Override
public void destroy() {
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@ import org.springframework.web.context.ServletContextAware;
*/
public class SessionEventHttpSessionListenerAdapter
implements ApplicationListener<AbstractSessionEvent>, ServletContextAware {
private final List<HttpSessionListener> listeners;
private ServletContext context;
@@ -75,8 +76,7 @@ public class SessionEventHttpSessionListenerAdapter
private HttpSessionEvent createHttpSessionEvent(AbstractSessionEvent event) {
Session session = event.getSession();
HttpSession httpSession = new HttpSessionAdapter<>(session,
this.context);
HttpSession httpSession = new HttpSessionAdapter<>(session, this.context);
return new HttpSessionEvent(httpSession);
}
@@ -91,4 +91,5 @@ public class SessionEventHttpSessionListenerAdapter
public void setServletContext(ServletContext servletContext) {
this.context = servletContext;
}
}

View File

@@ -59,6 +59,7 @@ import org.springframework.session.SessionRepository;
* . The default is to look in a cookie named SESSION.</li>
* <li>The session id of newly created {@link org.springframework.session.Session} is sent
* to the client using
* {@link HttpSessionIdResolver#setSessionId(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, String)}
* <li>The client is notified that the session id is no longer valid with
* {@link HttpSessionIdResolver#expireSession(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
* </li>
@@ -79,25 +80,21 @@ import org.springframework.session.SessionRepository;
@Order(SessionRepositoryFilter.DEFAULT_ORDER)
public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFilter {
private static final String SESSION_LOGGER_NAME = SessionRepositoryFilter.class
.getName().concat(".SESSION_LOGGER");
private static final String SESSION_LOGGER_NAME = SessionRepositoryFilter.class.getName().concat(".SESSION_LOGGER");
private static final Log SESSION_LOGGER = LogFactory.getLog(SESSION_LOGGER_NAME);
/**
* The session repository request attribute name.
*/
public static final String SESSION_REPOSITORY_ATTR = SessionRepository.class
.getName();
public static final String SESSION_REPOSITORY_ATTR = SessionRepository.class.getName();
/**
* Invalid session id (not backed by the session repository) request attribute name.
*/
public static final String INVALID_SESSION_ID_ATTR = SESSION_REPOSITORY_ATTR
+ ".invalidSessionId";
public static final String INVALID_SESSION_ID_ATTR = SESSION_REPOSITORY_ATTR + ".invalidSessionId";
private static final String CURRENT_SESSION_ATTR = SESSION_REPOSITORY_ATTR
+ ".CURRENT_SESSION";
private static final String CURRENT_SESSION_ATTR = SESSION_REPOSITORY_ATTR + ".CURRENT_SESSION";
/**
* The default filter order.
@@ -110,7 +107,6 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
/**
* Creates a new instance.
*
* @param sessionRepository the <code>SessionRepository</code> to use. Cannot be null.
*/
public SessionRepositoryFilter(SessionRepository<S> sessionRepository) {
@@ -123,7 +119,6 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
/**
* Sets the {@link HttpSessionIdResolver} to be used. The default is a
* {@link CookieHttpSessionIdResolver}.
*
* @param httpSessionIdResolver the {@link HttpSessionIdResolver} to use. Cannot be
* null.
*/
@@ -135,15 +130,13 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository);
SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(
request, response);
SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(
wrappedRequest, response);
SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(request, response);
SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(wrappedRequest,
response);
try {
filterChain.doFilter(wrappedRequest, wrappedResponse);
@@ -153,14 +146,19 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
}
}
@Override
protected void doFilterNestedErrorDispatch(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
doFilterInternal(request, response, filterChain);
}
/**
* Allows ensuring that the session is saved if the response is committed.
*
* @author Rob Winch
* @since 1.0
*/
private final class SessionRepositoryResponseWrapper
extends OnCommittedResponseWrapper {
private final class SessionRepositoryResponseWrapper extends OnCommittedResponseWrapper {
private final SessionRepositoryRequestWrapper request;
@@ -169,8 +167,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
* @param request the request to be wrapped
* @param response the response to be wrapped
*/
SessionRepositoryResponseWrapper(SessionRepositoryRequestWrapper request,
HttpServletResponse response) {
SessionRepositoryResponseWrapper(SessionRepositoryRequestWrapper request, HttpServletResponse response) {
super(response);
if (request == null) {
throw new IllegalArgumentException("request cannot be null");
@@ -182,6 +179,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
protected void onResponseCommitted() {
this.request.commitSession();
}
}
/**
@@ -192,8 +190,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
* @author Rob Winch
* @since 1.0
*/
private final class SessionRepositoryRequestWrapper
extends HttpServletRequestWrapper {
private final class SessionRepositoryRequestWrapper extends HttpServletRequestWrapper {
private final HttpServletResponse response;
@@ -207,8 +204,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
private boolean requestedSessionInvalidated;
private SessionRepositoryRequestWrapper(HttpServletRequest request,
HttpServletResponse response) {
private SessionRepositoryRequestWrapper(HttpServletRequest request, HttpServletResponse response) {
super(request);
this.response = response;
}
@@ -221,8 +217,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
HttpSessionWrapper wrappedSession = getCurrentSession();
if (wrappedSession == null) {
if (isInvalidateClientSession()) {
SessionRepositoryFilter.this.httpSessionIdResolver.expireSession(this,
this.response);
SessionRepositoryFilter.this.httpSessionIdResolver.expireSession(this, this.response);
}
}
else {
@@ -230,10 +225,8 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
clearRequestedSessionCache();
SessionRepositoryFilter.this.sessionRepository.save(session);
String sessionId = session.getId();
if (!isRequestedSessionIdValid()
|| !sessionId.equals(getRequestedSessionId())) {
SessionRepositoryFilter.this.httpSessionIdResolver.setSessionId(this,
this.response, sessionId);
if (!isRequestedSessionIdValid() || !sessionId.equals(getRequestedSessionId())) {
SessionRepositoryFilter.this.httpSessionIdResolver.setSessionId(this, this.response, sessionId);
}
}
}
@@ -300,7 +293,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
requestedSession.setLastAccessedTime(Instant.now());
this.requestedSessionIdValid = true;
currentSession = new HttpSessionWrapper(requestedSession, getServletContext());
currentSession.setNew(false);
currentSession.markNotNew();
setCurrentSession(currentSession);
return currentSession;
}
@@ -317,12 +310,15 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
if (!create) {
return null;
}
if (SessionRepositoryFilter.this.httpSessionIdResolver instanceof CookieHttpSessionIdResolver
&& this.response.isCommitted()) {
throw new IllegalStateException("Cannot create a session after the response has been committed");
}
if (SESSION_LOGGER.isDebugEnabled()) {
SESSION_LOGGER.debug(
"A new session was created. To help you troubleshoot where the session was created we provided a StackTrace (this is not an error). You can prevent this from appearing by disabling DEBUG logging for "
+ SESSION_LOGGER_NAME,
new RuntimeException(
"For debugging purposes only (not an error)"));
new RuntimeException("For debugging purposes only (not an error)"));
}
S session = SessionRepositoryFilter.this.sessionRepository.createSession();
session.setLastAccessedTime(Instant.now());
@@ -352,14 +348,12 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
private S getRequestedSession() {
if (!this.requestedSessionCached) {
List<String> sessionIds = SessionRepositoryFilter.this.httpSessionIdResolver
.resolveSessionIds(this);
List<String> sessionIds = SessionRepositoryFilter.this.httpSessionIdResolver.resolveSessionIds(this);
for (String sessionId : sessionIds) {
if (this.requestedSessionId == null) {
this.requestedSessionId = sessionId;
}
S session = SessionRepositoryFilter.this.sessionRepository
.findById(sessionId);
S session = SessionRepositoryFilter.this.sessionRepository.findById(sessionId);
if (session != null) {
this.requestedSession = session;
this.requestedSessionId = sessionId;
@@ -397,6 +391,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
clearRequestedSessionCache();
SessionRepositoryFilter.this.sessionRepository.deleteById(getId());
}
}
/**
@@ -404,8 +399,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
*
* @since 1.3.4
*/
private final class SessionCommittingRequestDispatcher
implements RequestDispatcher {
private final class SessionCommittingRequestDispatcher implements RequestDispatcher {
private final RequestDispatcher delegate;
@@ -414,14 +408,12 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
}
@Override
public void forward(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException {
this.delegate.forward(request, response);
}
@Override
public void include(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException {
SessionRepositoryRequestWrapper.this.commitSession();
this.delegate.include(request, response);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -61,12 +61,14 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
}
/**
* Configure the {@link Clock} to use to set lastAccessTime on every created
* session and to calculate if it is expired.
* <p>This may be useful to align to different timezone or to set the clock
* back in a test, e.g. {@code Clock.offset(clock, Duration.ofMinutes(-31))}
* in order to simulate session expiration.
* <p>By default this is {@code Clock.system(ZoneId.of("GMT"))}.
* Configure the {@link Clock} to use to set lastAccessTime on every created session
* and to calculate if it is expired.
* <p>
* This may be useful to align to different timezone or to set the clock back in a
* test, e.g. {@code Clock.offset(clock, Duration.ofMinutes(-31))} in order to
* simulate session expiration.
* <p>
* By default this is {@code Clock.system(ZoneId.of("GMT"))}.
* @param clock the clock to use
*/
public void setClock(Clock clock) {
@@ -90,8 +92,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
@Override
public Mono<WebSession> retrieveSession(String sessionId) {
return this.sessions.findById(sessionId)
.doOnNext((session) -> session.setLastAccessedTime(this.clock.instant()))
.map(this::existingSession);
.doOnNext((session) -> session.setLastAccessedTime(this.clock.instant())).map(this::existingSession);
}
@Override
@@ -133,8 +134,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
@Override
public Mono<Void> changeSessionId() {
return Mono.defer(() -> {
this.session
.changeSessionId();
this.session.changeSessionId();
return save();
});
}
@@ -152,8 +152,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
@Override
public boolean isStarted() {
State value = this.state.get();
return (State.STARTED.equals(value)
|| (State.NEW.equals(value) && !getAttributes().isEmpty()));
return (State.STARTED.equals(value) || (State.NEW.equals(value) && !getAttributes().isEmpty()));
}
@Override
@@ -198,10 +197,13 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
public void setMaxIdleTime(Duration maxIdleTime) {
this.session.setMaxInactiveInterval(maxIdleTime);
}
}
private enum State {
NEW, STARTED, EXPIRED
}
private static class SpringSessionMap implements Map<String, Object> {
@@ -226,8 +228,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
@Override
public boolean containsKey(Object key) {
return key instanceof String
&& this.session.getAttributeNames().contains(key);
return key instanceof String && this.session.getAttributeNames().contains(key);
}
@Override
@@ -346,5 +347,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -93,8 +93,7 @@ public abstract class AbstractSessionWebSocketMessageBrokerConfigurer<S extends
public final void registerStompEndpoints(StompEndpointRegistry registry) {
if (registry instanceof WebMvcStompEndpointRegistry) {
WebMvcStompEndpointRegistry mvcRegistry = (WebMvcStompEndpointRegistry) registry;
configureStompEndpoints(new SessionStompEndpointRegistry(mvcRegistry,
sessionRepositoryInterceptor()));
configureStompEndpoints(new SessionStompEndpointRegistry(mvcRegistry, sessionRepositoryInterceptor()));
}
}
@@ -102,7 +101,6 @@ public abstract class AbstractSessionWebSocketMessageBrokerConfigurer<S extends
* Register STOMP endpoints mapping each to a specific URL and (optionally) enabling
* and configuring SockJS fallback options with a
* {@link SessionRepositoryMessageInterceptor} automatically added as an interceptor.
*
* @param registry the {@link StompEndpointRegistry} which automatically has a
* {@link SessionRepositoryMessageInterceptor} added to it.
*/
@@ -133,19 +131,19 @@ public abstract class AbstractSessionWebSocketMessageBrokerConfigurer<S extends
* A {@link StompEndpointRegistry} that applies {@link HandshakeInterceptor}.
*/
static class SessionStompEndpointRegistry implements StompEndpointRegistry {
private final WebMvcStompEndpointRegistry registry;
private final HandshakeInterceptor interceptor;
SessionStompEndpointRegistry(WebMvcStompEndpointRegistry registry,
HandshakeInterceptor interceptor) {
SessionStompEndpointRegistry(WebMvcStompEndpointRegistry registry, HandshakeInterceptor interceptor) {
this.registry = registry;
this.interceptor = interceptor;
}
@Override
public StompWebSocketEndpointRegistration addEndpoint(String... paths) {
StompWebSocketEndpointRegistration endpoints = this.registry
.addEndpoint(paths);
StompWebSocketEndpointRegistration endpoints = this.registry.addEndpoint(paths);
endpoints.addInterceptors(this.interceptor);
return endpoints;
}
@@ -161,9 +159,10 @@ public abstract class AbstractSessionWebSocketMessageBrokerConfigurer<S extends
}
@Override
public WebMvcStompEndpointRegistry setErrorHandler(
StompSubProtocolErrorHandler errorHandler) {
public WebMvcStompEndpointRegistry setErrorHandler(StompSubProtocolErrorHandler errorHandler) {
return this.registry.setErrorHandler(errorHandler);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,4 +44,5 @@ public class SessionConnectEvent extends ApplicationEvent {
public WebSocketSession getWebSocketSession() {
return this.webSocketSession;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,24 +38,19 @@ import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;
*
* @author Rob Winch
* @since 1.0
*
* @see WebSocketRegistryListener
*/
public final class WebSocketConnectHandlerDecoratorFactory
implements WebSocketHandlerDecoratorFactory {
public final class WebSocketConnectHandlerDecoratorFactory implements WebSocketHandlerDecoratorFactory {
private static final Log logger = LogFactory
.getLog(WebSocketConnectHandlerDecoratorFactory.class);
private static final Log logger = LogFactory.getLog(WebSocketConnectHandlerDecoratorFactory.class);
private final ApplicationEventPublisher eventPublisher;
/**
* Creates a new instance.
*
* @param eventPublisher the {@link ApplicationEventPublisher} to use. Cannot be null.
*/
public WebSocketConnectHandlerDecoratorFactory(
ApplicationEventPublisher eventPublisher) {
public WebSocketConnectHandlerDecoratorFactory(ApplicationEventPublisher eventPublisher) {
Assert.notNull(eventPublisher, "eventPublisher cannot be null");
this.eventPublisher = eventPublisher;
}
@@ -72,8 +67,7 @@ public final class WebSocketConnectHandlerDecoratorFactory
}
@Override
public void afterConnectionEstablished(WebSocketSession wsSession)
throws Exception {
public void afterConnectionEstablished(WebSocketSession wsSession) throws Exception {
super.afterConnectionEstablished(wsSession);
publishEvent(new SessionConnectEvent(this, wsSession));
@@ -81,12 +75,13 @@ public final class WebSocketConnectHandlerDecoratorFactory
private void publishEvent(ApplicationEvent event) {
try {
WebSocketConnectHandlerDecoratorFactory.this.eventPublisher
.publishEvent(event);
WebSocketConnectHandlerDecoratorFactory.this.eventPublisher.publishEvent(event);
}
catch (Throwable ex) {
logger.error("Error publishing " + event + ".", ex);
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,18 +41,15 @@ import org.springframework.web.socket.messaging.SessionDisconnectEvent;
* {@link WebSocketSession} is closed.
* </p>
*
*
* @author Rob Winch
* @author Mark Anderson
* @since 1.0
*/
public final class WebSocketRegistryListener
implements ApplicationListener<ApplicationEvent> {
public final class WebSocketRegistryListener implements ApplicationListener<ApplicationEvent> {
private static final Log logger = LogFactory.getLog(WebSocketRegistryListener.class);
static final CloseStatus SESSION_EXPIRED_STATUS = new CloseStatus(
CloseStatus.POLICY_VIOLATION.getCode(),
static final CloseStatus SESSION_EXPIRED_STATUS = new CloseStatus(CloseStatus.POLICY_VIOLATION.getCode(),
"This connection was established under an authenticated HTTP Session that has expired");
private final ConcurrentHashMap<String, Map<String, WebSocketSession>> httpSessionIdToWsSessions = new ConcurrentHashMap<>();
@@ -72,8 +69,7 @@ public final class WebSocketRegistryListener
Map<String, Object> sessionAttributes = SimpMessageHeaderAccessor
.getSessionAttributes(e.getMessage().getHeaders());
String httpSessionId = (sessionAttributes != null)
? SessionRepositoryMessageInterceptor.getSessionId(sessionAttributes)
: null;
? SessionRepositoryMessageInterceptor.getSessionId(sessionAttributes) : null;
afterConnectionClosed(httpSessionId, e.getSessionId());
}
}
@@ -98,8 +94,7 @@ public final class WebSocketRegistryListener
return;
}
Map<String, WebSocketSession> sessions = this.httpSessionIdToWsSessions
.get(httpSessionId);
Map<String, WebSocketSession> sessions = this.httpSessionIdToWsSessions.get(httpSessionId);
if (sessions != null) {
boolean result = sessions.remove(wsSessionId) != null;
if (logger.isDebugEnabled()) {
@@ -108,16 +103,15 @@ public final class WebSocketRegistryListener
if (sessions.isEmpty()) {
this.httpSessionIdToWsSessions.remove(httpSessionId);
if (logger.isDebugEnabled()) {
logger.debug("Removed the corresponding HTTP Session for "
+ wsSessionId + " since it contained no WebSocket mappings");
logger.debug("Removed the corresponding HTTP Session for " + wsSessionId
+ " since it contained no WebSocket mappings");
}
}
}
}
private void registerWsSession(String httpSessionId, WebSocketSession wsSession) {
Map<String, WebSocketSession> sessions = this.httpSessionIdToWsSessions
.get(httpSessionId);
Map<String, WebSocketSession> sessions = this.httpSessionIdToWsSessions.get(httpSessionId);
if (sessions == null) {
sessions = new ConcurrentHashMap<>();
this.httpSessionIdToWsSessions.putIfAbsent(httpSessionId, sessions);
@@ -127,25 +121,22 @@ public final class WebSocketRegistryListener
}
private void closeWsSessions(String httpSessionId) {
Map<String, WebSocketSession> sessionsToClose = this.httpSessionIdToWsSessions
.remove(httpSessionId);
Map<String, WebSocketSession> sessionsToClose = this.httpSessionIdToWsSessions.remove(httpSessionId);
if (sessionsToClose == null) {
return;
}
if (logger.isDebugEnabled()) {
logger.debug(
"Closing WebSocket connections associated to expired HTTP Session "
+ httpSessionId);
logger.debug("Closing WebSocket connections associated to expired HTTP Session " + httpSessionId);
}
for (WebSocketSession toClose : sessionsToClose.values()) {
try {
toClose.close(SESSION_EXPIRED_STATUS);
}
catch (IOException ex) {
logger.debug(
"Failed to close WebSocketSession (this is nothing to worry about but for debugging only)",
logger.debug("Failed to close WebSocketSession (this is nothing to worry about but for debugging only)",
ex);
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -72,15 +72,13 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
/**
* Creates a new instance.
*
* @param sessionRepository the {@link SessionRepository} to use. Cannot be null.
*/
public SessionRepositoryMessageInterceptor(SessionRepository<S> sessionRepository) {
Assert.notNull(sessionRepository, "sessionRepository cannot be null");
this.sessionRepository = sessionRepository;
this.matchingMessageTypes = EnumSet.of(SimpMessageType.CONNECT,
SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE,
SimpMessageType.UNSUBSCRIBE);
this.matchingMessageTypes = EnumSet.of(SimpMessageType.CONNECT, SimpMessageType.MESSAGE,
SimpMessageType.SUBSCRIBE, SimpMessageType.UNSUBSCRIBE);
}
/**
@@ -94,14 +92,12 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
* The default is: SimpMessageType.CONNECT, SimpMessageType.MESSAGE,
* SimpMessageType.SUBSCRIBE, SimpMessageType.UNSUBSCRIBE.
* </p>
*
* @param matchingMessageTypes the {@link SimpMessageType} to match on in
* {@link #preSend(Message, MessageChannel)}, else the {@link Message} is continued
* without accessing or updating the {@link Session}
*/
public void setMatchingMessageTypes(Set<SimpMessageType> matchingMessageTypes) {
Assert.notEmpty(matchingMessageTypes,
"matchingMessageTypes cannot be null or empty");
Assert.notEmpty(matchingMessageTypes, "matchingMessageTypes cannot be null or empty");
this.matchingMessageTypes = matchingMessageTypes;
}
@@ -110,16 +106,12 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
if (message == null) {
return message;
}
SimpMessageType messageType = SimpMessageHeaderAccessor
.getMessageType(message.getHeaders());
SimpMessageType messageType = SimpMessageHeaderAccessor.getMessageType(message.getHeaders());
if (!this.matchingMessageTypes.contains(messageType)) {
return message;
}
Map<String, Object> sessionHeaders = SimpMessageHeaderAccessor
.getSessionAttributes(message.getHeaders());
String sessionId = (sessionHeaders != null)
? (String) sessionHeaders.get(SPRING_SESSION_ID_ATTR_NAME)
: null;
Map<String, Object> sessionHeaders = SimpMessageHeaderAccessor.getSessionAttributes(message.getHeaders());
String sessionId = (sessionHeaders != null) ? (String) sessionHeaders.get(SPRING_SESSION_ID_ATTR_NAME) : null;
if (sessionId != null) {
S session = this.sessionRepository.findById(sessionId);
if (session != null) {
@@ -132,8 +124,8 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
}
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
HttpSession session = servletRequest.getServletRequest().getSession(false);
@@ -145,8 +137,8 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Exception exception) {
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception exception) {
}
public static String getSessionId(Map<String, Object> attributes) {
@@ -156,4 +148,5 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
public static void setSessionId(Map<String, Object> attributes, String sessionId) {
attributes.put(SPRING_SESSION_ID_ATTR_NAME, sessionId);
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2014-2019 the original author or authors.
*
* 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
*
* https://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 org.springframework.session;
import java.util.Collections;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DelegatingIndexResolver}.
*
* @author Vedran Pavic
*/
class DelegatingIndexResolverTests {
private DelegatingIndexResolver<MapSession> indexResolver;
@BeforeEach
void setUp() {
this.indexResolver = new DelegatingIndexResolver<>(new TestIndexResolver("one"), new TestIndexResolver("two"));
}
@Test
void resolve() {
MapSession session = new MapSession();
session.setAttribute("one", "first");
session.setAttribute("two", "second");
Map<String, String> indexes = this.indexResolver.resolveIndexesFor(session);
assertThat(indexes).hasSize(2);
assertThat(indexes.get("one")).isEqualTo("first");
assertThat(indexes.get("two")).isEqualTo("second");
}
private static class TestIndexResolver implements IndexResolver<MapSession> {
private final String supportedIndex;
TestIndexResolver(String supportedIndex) {
this.supportedIndex = supportedIndex;
}
@Override
public Map<String, String> resolveIndexesFor(MapSession session) {
return Collections.singletonMap(this.supportedIndex, session.getAttribute(this.supportedIndex));
}
}
}

View File

@@ -29,20 +29,20 @@ import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MapSessionRepository}.
*/
public class MapSessionRepositoryTests {
class MapSessionRepositoryTests {
private MapSessionRepository repository;
private MapSession session;
@BeforeEach
public void setup() {
void setup() {
this.repository = new MapSessionRepository(new ConcurrentHashMap<>());
this.session = new MapSession();
}
@Test
public void getSessionExpired() {
void getSessionExpired() {
this.session.setMaxInactiveInterval(Duration.ofSeconds(1));
this.session.setLastAccessedTime(Instant.now().minus(5, ChronoUnit.MINUTES));
this.repository.save(this.session);
@@ -51,29 +51,25 @@ public class MapSessionRepositoryTests {
}
@Test
public void createSessionDefaultExpiration() {
void createSessionDefaultExpiration() {
Session session = this.repository.createSession();
assertThat(session).isInstanceOf(MapSession.class);
assertThat(session.getMaxInactiveInterval())
.isEqualTo(new MapSession().getMaxInactiveInterval());
assertThat(session.getMaxInactiveInterval()).isEqualTo(new MapSession().getMaxInactiveInterval());
}
@Test
public void createSessionCustomDefaultExpiration() {
final Duration expectedMaxInterval = new MapSession().getMaxInactiveInterval()
.plusSeconds(10);
this.repository.setDefaultMaxInactiveInterval(
(int) expectedMaxInterval.getSeconds());
void createSessionCustomDefaultExpiration() {
final Duration expectedMaxInterval = new MapSession().getMaxInactiveInterval().plusSeconds(10);
this.repository.setDefaultMaxInactiveInterval((int) expectedMaxInterval.getSeconds());
Session session = this.repository.createSession();
assertThat(session.getMaxInactiveInterval())
.isEqualTo(expectedMaxInterval);
assertThat(session.getMaxInactiveInterval()).isEqualTo(expectedMaxInterval);
}
@Test
public void changeSessionIdWhenNotYetSaved() {
void changeSessionIdWhenNotYetSaved() {
MapSession createSession = this.repository.createSession();
String originalId = createSession.getId();
@@ -86,7 +82,7 @@ public class MapSessionRepositoryTests {
}
@Test
public void changeSessionIdWhenSaved() {
void changeSessionIdWhenSaved() {
MapSession createSession = this.repository.createSession();
this.repository.save(createSession);
@@ -101,7 +97,7 @@ public class MapSessionRepositoryTests {
}
@Test // gh-1120
public void getAttributeNamesAndRemove() {
void getAttributeNamesAndRemove() {
MapSession session = this.repository.createSession();
session.setAttribute("attribute1", "value1");
session.setAttribute("attribute2", "value2");

View File

@@ -26,38 +26,37 @@ import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
public class MapSessionTests {
class MapSessionTests {
private MapSession session;
@BeforeEach
public void setup() {
void setup() {
this.session = new MapSession();
this.session.setLastAccessedTime(Instant.ofEpochMilli(1413258262962L));
}
@Test
public void constructorNullSession() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new MapSession((Session) null))
void constructorNullSession() {
assertThatIllegalArgumentException().isThrownBy(() -> new MapSession((Session) null))
.withMessage("session cannot be null");
}
@Test
public void getAttributeWhenNullThenNull() {
void getAttributeWhenNullThenNull() {
String result = this.session.getAttribute("attrName");
assertThat(result).isNull();
}
@Test
public void getAttributeOrDefaultWhenNullThenDefaultValue() {
void getAttributeOrDefaultWhenNullThenDefaultValue() {
String defaultValue = "default";
String result = this.session.getAttributeOrDefault("attrName", defaultValue);
assertThat(result).isEqualTo(defaultValue);
}
@Test
public void getAttributeOrDefaultWhenNotNullThenDefaultValue() {
void getAttributeOrDefaultWhenNotNullThenDefaultValue() {
String defaultValue = "default";
String attrValue = "value";
String attrName = "attrName";
@@ -69,14 +68,13 @@ public class MapSessionTests {
}
@Test
public void getRequiredAttributeWhenNullThenException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.session.getRequiredAttribute("attrName"))
void getRequiredAttributeWhenNullThenException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.session.getRequiredAttribute("attrName"))
.withMessage("Required attribute 'attrName' is missing.");
}
@Test
public void getRequiredAttributeWhenNotNullThenReturns() {
void getRequiredAttributeWhenNotNullThenReturns() {
String attrValue = "value";
String attrName = "attrName";
this.session.setAttribute(attrName, attrValue);
@@ -90,7 +88,7 @@ public class MapSessionTests {
* Ensure conforms to the javadoc of {@link Session}
*/
@Test
public void setAttributeNullObjectRemoves() {
void setAttributeNullObjectRemoves() {
String attr = "attr";
this.session.setAttribute(attr, new Object());
this.session.setAttribute(attr, null);
@@ -98,43 +96,43 @@ public class MapSessionTests {
}
@Test
public void equalsNonSessionFalse() {
void equalsNonSessionFalse() {
assertThat(this.session.equals(new Object())).isFalse();
}
@Test
public void equalsCustomSession() {
void equalsCustomSession() {
CustomSession other = new CustomSession();
this.session.setId(other.getId());
assertThat(this.session.equals(other)).isTrue();
}
@Test
public void hashCodeEqualsIdHashCode() {
void hashCodeEqualsIdHashCode() {
this.session.setId("constantId");
assertThat(this.session.hashCode()).isEqualTo(this.session.getId().hashCode());
}
@Test
public void isExpiredExact() {
void isExpiredExact() {
Instant now = Instant.ofEpochMilli(1413260062962L);
assertThat(this.session.isExpired(now)).isTrue();
}
@Test
public void isExpiredOneMsTooSoon() {
void isExpiredOneMsTooSoon() {
Instant now = Instant.ofEpochMilli(1413260062961L);
assertThat(this.session.isExpired(now)).isFalse();
}
@Test
public void isExpiredOneMsAfter() {
void isExpiredOneMsAfter() {
Instant now = Instant.ofEpochMilli(1413260062963L);
assertThat(this.session.isExpired(now)).isTrue();
}
@Test // gh-1120
public void getAttributeNamesAndRemove() {
void getAttributeNamesAndRemove() {
this.session.setAttribute("attribute1", "value1");
this.session.setAttribute("attribute2", "value2");
@@ -206,6 +204,7 @@ public class MapSessionTests {
public boolean isExpired() {
return false;
}
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2014-2019 the original author or authors.
*
* 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
*
* https://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 org.springframework.session;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextImpl;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link PrincipalNameIndexResolver}.
*
* @author Vedran Pavic
*/
class PrincipalNameIndexResolverTests {
private static final String PRINCIPAL_NAME = "principalName";
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
private PrincipalNameIndexResolver<Session> indexResolver;
@BeforeEach
void setUp() {
this.indexResolver = new PrincipalNameIndexResolver<>();
}
@Test
void resolveFromPrincipalName() {
MapSession session = new MapSession();
session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, PRINCIPAL_NAME);
assertThat(this.indexResolver.resolveIndexValueFor(session)).isEqualTo(PRINCIPAL_NAME);
}
@Test
void resolveFromSpringSecurityContext() {
Authentication authentication = new UsernamePasswordAuthenticationToken(PRINCIPAL_NAME, "notused",
AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContext context = new SecurityContextImpl();
context.setAuthentication(authentication);
MapSession session = new MapSession();
session.setAttribute(SPRING_SECURITY_CONTEXT, context);
assertThat(this.indexResolver.resolveIndexValueFor(session)).isEqualTo(PRINCIPAL_NAME);
}
}

View File

@@ -35,20 +35,20 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
* @author Rob Winch
* @since 2.0
*/
public class ReactiveMapSessionRepositoryTests {
class ReactiveMapSessionRepositoryTests {
private ReactiveMapSessionRepository repository;
private MapSession session;
@BeforeEach
public void setup() {
void setup() {
this.repository = new ReactiveMapSessionRepository(new HashMap<>());
this.session = new MapSession("session-id");
}
@Test
public void constructorMapThenFound() {
void constructorMapThenFound() {
Map<String, Session> sessions = new HashMap<>();
sessions.put(this.session.getId(), this.session);
this.repository = new ReactiveMapSessionRepository(sessions);
@@ -59,21 +59,20 @@ public class ReactiveMapSessionRepositoryTests {
}
@Test
public void constructorMapWhenNullThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new ReactiveMapSessionRepository(null))
void constructorMapWhenNullThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException().isThrownBy(() -> new ReactiveMapSessionRepository(null))
.withMessage("sessions cannot be null");
}
@Test
public void saveWhenNoSubscribersThenNotFound() {
void saveWhenNoSubscribersThenNotFound() {
this.repository.save(this.session);
assertThat(this.repository.findById(this.session.getId()).block()).isNull();
}
@Test
public void saveWhenSubscriberThenFound() {
void saveWhenSubscriberThenFound() {
this.repository.save(this.session).block();
Session findByIdSession = this.repository.findById(this.session.getId()).block();
@@ -82,7 +81,7 @@ public class ReactiveMapSessionRepositoryTests {
}
@Test
public void findByIdWhenExpiredRemovesFromSessionMap() {
void findByIdWhenExpiredRemovesFromSessionMap() {
this.session.setMaxInactiveInterval(Duration.ofMinutes(1));
this.session.setLastAccessedTime(Instant.now().minus(5, ChronoUnit.MINUTES));
@@ -95,20 +94,17 @@ public class ReactiveMapSessionRepositoryTests {
}
@Test
public void createSessionWhenDefaultMaxInactiveIntervalThenDefaultMaxInactiveInterval() {
void createSessionWhenDefaultMaxInactiveIntervalThenDefaultMaxInactiveInterval() {
Session session = this.repository.createSession().block();
assertThat(session).isInstanceOf(MapSession.class);
assertThat(session.getMaxInactiveInterval())
.isEqualTo(new MapSession().getMaxInactiveInterval());
assertThat(session.getMaxInactiveInterval()).isEqualTo(new MapSession().getMaxInactiveInterval());
}
@Test
public void createSessionWhenCustomMaxInactiveIntervalThenCustomMaxInactiveInterval() {
final Duration expectedMaxInterval = new MapSession().getMaxInactiveInterval()
.plusSeconds(10);
this.repository
.setDefaultMaxInactiveInterval((int) expectedMaxInterval.getSeconds());
void createSessionWhenCustomMaxInactiveIntervalThenCustomMaxInactiveInterval() {
final Duration expectedMaxInterval = new MapSession().getMaxInactiveInterval().plusSeconds(10);
this.repository.setDefaultMaxInactiveInterval((int) expectedMaxInterval.getSeconds());
Session session = this.repository.createSession().block();
@@ -116,7 +112,7 @@ public class ReactiveMapSessionRepositoryTests {
}
@Test
public void changeSessionIdWhenNotYetSaved() {
void changeSessionIdWhenNotYetSaved() {
MapSession createSession = this.repository.createSession().block();
String originalId = createSession.getId();
@@ -129,7 +125,7 @@ public class ReactiveMapSessionRepositoryTests {
}
@Test
public void changeSessionIdWhenSaved() {
void changeSessionIdWhenSaved() {
MapSession createSession = this.repository.createSession().block();
this.repository.save(createSession).block();
@@ -144,7 +140,7 @@ public class ReactiveMapSessionRepositoryTests {
}
@Test // gh-1120
public void getAttributeNamesAndRemove() {
void getAttributeNamesAndRemove() {
MapSession session = this.repository.createSession().block();
session.setAttribute("attribute1", "value1");
session.setAttribute("attribute2", "value2");

View File

@@ -61,7 +61,7 @@ import static org.mockito.Mockito.verify;
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class EnableSpringHttpSessionCustomCookieSerializerTests {
class EnableSpringHttpSessionCustomCookieSerializerTests {
@Autowired
private MockHttpServletRequest request;
@@ -81,7 +81,7 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
private CookieSerializer cookieSerializer;
@BeforeEach
public void setup() {
void setup() {
this.chain = new MockFilterChain();
reset(this.sessionRepository);
@@ -89,12 +89,11 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
}
@Test
public void usesReadSessionIds() throws Exception {
void usesReadSessionIds() throws Exception {
String sessionId = "sessionId";
given(this.cookieSerializer.readCookieValues(any(HttpServletRequest.class)))
.willReturn(Collections.singletonList(sessionId));
given(this.sessionRepository.findById(anyString()))
.willReturn(new MapSession(sessionId));
given(this.sessionRepository.findById(anyString())).willReturn(new MapSession(sessionId));
this.sessionRepositoryFilter.doFilter(this.request, this.response, this.chain);
@@ -102,19 +101,18 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
}
@Test
public void usesWrite() throws Exception {
void usesWrite() throws Exception {
given(this.sessionRepository.createSession()).willReturn(new MapSession());
this.sessionRepositoryFilter.doFilter(this.request, this.response,
new MockFilterChain() {
this.sessionRepositoryFilter.doFilter(this.request, this.response, new MockFilterChain() {
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
((HttpServletRequest) request).getSession();
super.doFilter(request, response);
}
});
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
((HttpServletRequest) request).getSession();
super.doFilter(request, response);
}
});
verify(this.cookieSerializer).writeCookieValue(any(CookieValue.class));
}
@@ -128,12 +126,12 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
static class Config {
@Bean
public SessionRepository sessionRepository() {
SessionRepository sessionRepository() {
return mock(SessionRepository.class);
}
@Bean
public CookieSerializer cookieSerializer() {
CookieSerializer cookieSerializer() {
return mock(CookieSerializer.class);
}

View File

@@ -45,12 +45,12 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
*
* @author Vedran Pavic
*/
public class SpringHttpSessionConfigurationTests {
class SpringHttpSessionConfigurationTests {
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@AfterEach
public void closeContext() {
void closeContext() {
if (this.context != null) {
this.context.close();
}
@@ -62,28 +62,26 @@ public class SpringHttpSessionConfigurationTests {
}
@Test
public void noSessionRepositoryConfiguration() {
void noSessionRepositoryConfiguration() {
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
.isThrownBy(() -> registerAndRefresh(EmptyConfiguration.class))
.withMessageContaining("org.springframework.session.SessionRepository");
}
@Test
public void defaultConfiguration() {
void defaultConfiguration() {
registerAndRefresh(DefaultConfiguration.class);
assertThat(this.context.getBean(SessionEventHttpSessionListenerAdapter.class))
.isNotNull();
assertThat(this.context.getBean(SessionEventHttpSessionListenerAdapter.class)).isNotNull();
assertThat(this.context.getBean(SessionRepositoryFilter.class)).isNotNull();
assertThat(this.context.getBean(SessionRepository.class)).isNotNull();
}
@Test
public void sessionCookieConfigConfiguration() {
void sessionCookieConfigConfiguration() {
registerAndRefresh(SessionCookieConfigConfiguration.class);
SessionRepositoryFilter sessionRepositoryFilter = this.context
.getBean(SessionRepositoryFilter.class);
SessionRepositoryFilter sessionRepositoryFilter = this.context.getBean(SessionRepositoryFilter.class);
assertThat(sessionRepositoryFilter).isNotNull();
CookieHttpSessionIdResolver httpSessionIdResolver = (CookieHttpSessionIdResolver) ReflectionTestUtils
.getField(sessionRepositoryFilter, "httpSessionIdResolver");
@@ -91,22 +89,17 @@ public class SpringHttpSessionConfigurationTests {
DefaultCookieSerializer cookieSerializer = (DefaultCookieSerializer) ReflectionTestUtils
.getField(httpSessionIdResolver, "cookieSerializer");
assertThat(cookieSerializer).isNotNull();
assertThat(ReflectionTestUtils.getField(cookieSerializer, "cookieName"))
.isEqualTo("test-name");
assertThat(ReflectionTestUtils.getField(cookieSerializer, "cookiePath"))
.isEqualTo("test-path");
assertThat(ReflectionTestUtils.getField(cookieSerializer, "cookieMaxAge"))
.isEqualTo(600);
assertThat(ReflectionTestUtils.getField(cookieSerializer, "domainName"))
.isEqualTo("test-domain");
assertThat(ReflectionTestUtils.getField(cookieSerializer, "cookieName")).isEqualTo("test-name");
assertThat(ReflectionTestUtils.getField(cookieSerializer, "cookiePath")).isEqualTo("test-path");
assertThat(ReflectionTestUtils.getField(cookieSerializer, "cookieMaxAge")).isEqualTo(600);
assertThat(ReflectionTestUtils.getField(cookieSerializer, "domainName")).isEqualTo("test-domain");
}
@Test
public void rememberMeServicesConfiguration() {
void rememberMeServicesConfiguration() {
registerAndRefresh(RememberMeServicesConfiguration.class);
SessionRepositoryFilter sessionRepositoryFilter = this.context
.getBean(SessionRepositoryFilter.class);
SessionRepositoryFilter sessionRepositoryFilter = this.context.getBean(SessionRepositoryFilter.class);
assertThat(sessionRepositoryFilter).isNotNull();
CookieHttpSessionIdResolver httpSessionIdResolver = (CookieHttpSessionIdResolver) ReflectionTestUtils
.getField(sessionRepositoryFilter, "httpSessionIdResolver");
@@ -114,20 +107,20 @@ public class SpringHttpSessionConfigurationTests {
DefaultCookieSerializer cookieSerializer = (DefaultCookieSerializer) ReflectionTestUtils
.getField(httpSessionIdResolver, "cookieSerializer");
assertThat(cookieSerializer).isNotNull();
assertThat(ReflectionTestUtils.getField(cookieSerializer,
"rememberMeRequestAttribute")).isEqualTo(
SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);
assertThat(ReflectionTestUtils.getField(cookieSerializer, "rememberMeRequestAttribute"))
.isEqualTo(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);
}
@Configuration
@EnableSpringHttpSession
static class EmptyConfiguration {
}
static class BaseConfiguration {
@Bean
public MapSessionRepository sessionRepository() {
MapSessionRepository sessionRepository() {
return new MapSessionRepository(new ConcurrentHashMap<>());
}
@@ -136,6 +129,7 @@ public class SpringHttpSessionConfigurationTests {
@Configuration
@EnableSpringHttpSession
static class DefaultConfiguration extends BaseConfiguration {
}
@Configuration
@@ -143,7 +137,7 @@ public class SpringHttpSessionConfigurationTests {
static class SessionCookieConfigConfiguration extends BaseConfiguration {
@Bean
public ServletContext servletContext() {
ServletContext servletContext() {
MockServletContext servletContext = new MockServletContext();
servletContext.getSessionCookieConfig().setName("test-name");
servletContext.getSessionCookieConfig().setDomain("test-domain");
@@ -159,7 +153,7 @@ public class SpringHttpSessionConfigurationTests {
static class RememberMeServicesConfiguration extends BaseConfiguration {
@Bean
public SpringSessionRememberMeServices rememberMeServices() {
SpringSessionRememberMeServices rememberMeServices() {
return new SpringSessionRememberMeServices();
}

View File

@@ -41,18 +41,19 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
*
* @author Greg Turnquist
*/
public class SpringWebSessionConfigurationTests {
class SpringWebSessionConfigurationTests {
private AnnotationConfigApplicationContext context;
@AfterEach
public void cleanup() {
void cleanup() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void enableSpringWebSessionConfiguresThings() {
void enableSpringWebSessionConfiguresThings() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(GoodConfig.class);
@@ -69,19 +70,18 @@ public class SpringWebSessionConfigurationTests {
}
@Test
public void missingReactiveSessionRepositoryBreaksAppContext() {
void missingReactiveSessionRepositoryBreaksAppContext() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(BadConfig.class);
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
.isThrownBy(this.context::refresh)
.withMessageContaining("Error creating bean with name 'webSessionManager'")
.withMessageContaining("No qualifying bean of type '" + ReactiveSessionRepository.class.getCanonicalName());
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(this.context::refresh)
.withMessageContaining("Error creating bean with name 'webSessionManager'").withMessageContaining(
"No qualifying bean of type '" + ReactiveSessionRepository.class.getCanonicalName());
}
@Test
public void defaultSessionIdResolverShouldBeCookieBased() {
void defaultSessionIdResolverShouldBeCookieBased() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(GoodConfig.class);
@@ -92,7 +92,7 @@ public class SpringWebSessionConfigurationTests {
}
@Test
public void providedSessionIdResolverShouldBePickedUpAutomatically() {
void providedSessionIdResolverShouldBePickedUpAutomatically() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(OverrideSessionIdResolver.class);
@@ -109,12 +109,14 @@ public class SpringWebSessionConfigurationTests {
static class GoodConfig {
/**
* Use Reactor-friendly, {@link java.util.Map}-backed {@link ReactiveSessionRepository} for test purposes.
* Use Reactor-friendly, {@link java.util.Map}-backed
* {@link ReactiveSessionRepository} for test purposes.
*/
@Bean
ReactiveSessionRepository<?> reactiveSessionRepository() {
return new ReactiveMapSessionRepository(new HashMap<>());
}
}
/**
@@ -137,6 +139,7 @@ public class SpringWebSessionConfigurationTests {
WebSessionIdResolver alternateWebSessionIdResolver() {
return new HeaderWebSessionIdResolver();
}
}
}

View File

@@ -16,6 +16,7 @@
package org.springframework.session.security;
import java.security.Principal;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
@@ -30,6 +31,7 @@ import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.security.core.AuthenticatedPrincipal;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.core.session.SessionInformation;
@@ -46,7 +48,7 @@ import static org.mockito.BDDMockito.when;
/**
* Tests for {@link SpringSessionBackedSessionRegistry}.
*/
public class SpringSessionBackedSessionRegistryTest {
class SpringSessionBackedSessionRegistryTest {
private static final String SESSION_ID = "sessionId";
@@ -54,8 +56,7 @@ public class SpringSessionBackedSessionRegistryTest {
private static final String USER_NAME = "userName";
private static final User PRINCIPAL = new User(USER_NAME, "password",
Collections.emptyList());
private static final User PRINCIPAL = new User(USER_NAME, "password", Collections.emptyList());
private static final Instant NOW = Instant.now();
@@ -71,74 +72,77 @@ public class SpringSessionBackedSessionRegistryTest {
}
@Test
public void sessionInformationForExistingSession() {
void sessionInformationForExistingSession() {
Session session = createSession(SESSION_ID, USER_NAME, NOW);
when(this.sessionRepository.findById(SESSION_ID)).thenReturn(session);
SessionInformation sessionInfo = this.sessionRegistry
.getSessionInformation(SESSION_ID);
SessionInformation sessionInfo = this.sessionRegistry.getSessionInformation(SESSION_ID);
assertThat(sessionInfo.getSessionId()).isEqualTo(SESSION_ID);
assertThat(
sessionInfo.getLastRequest().toInstant().truncatedTo(ChronoUnit.MILLIS))
.isEqualTo(NOW.truncatedTo(ChronoUnit.MILLIS));
assertThat(sessionInfo.getLastRequest().toInstant().truncatedTo(ChronoUnit.MILLIS))
.isEqualTo(NOW.truncatedTo(ChronoUnit.MILLIS));
assertThat(sessionInfo.getPrincipal()).isEqualTo(USER_NAME);
assertThat(sessionInfo.isExpired()).isFalse();
}
@Test
public void sessionInformationForExpiredSession() {
void sessionInformationForExpiredSession() {
Session session = createSession(SESSION_ID, USER_NAME, NOW);
session.setAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR,
Boolean.TRUE);
session.setAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR, Boolean.TRUE);
when(this.sessionRepository.findById(SESSION_ID)).thenReturn(session);
SessionInformation sessionInfo = this.sessionRegistry
.getSessionInformation(SESSION_ID);
SessionInformation sessionInfo = this.sessionRegistry.getSessionInformation(SESSION_ID);
assertThat(sessionInfo.getSessionId()).isEqualTo(SESSION_ID);
assertThat(
sessionInfo.getLastRequest().toInstant().truncatedTo(ChronoUnit.MILLIS))
assertThat(sessionInfo.getLastRequest().toInstant().truncatedTo(ChronoUnit.MILLIS))
.isEqualTo(NOW.truncatedTo(ChronoUnit.MILLIS));
assertThat(sessionInfo.getPrincipal()).isEqualTo(USER_NAME);
assertThat(sessionInfo.isExpired()).isTrue();
}
@Test
public void noSessionInformationForMissingSession() {
assertThat(this.sessionRegistry.getSessionInformation("nonExistingSessionId"))
.isNull();
void noSessionInformationForMissingSession() {
assertThat(this.sessionRegistry.getSessionInformation("nonExistingSessionId")).isNull();
}
@Test
public void getAllSessions() {
void getAllSessionsForUserDetails() {
setUpSessions();
List<SessionInformation> allSessionInfos = this.sessionRegistry.getAllSessions(PRINCIPAL, true);
assertThat(allSessionInfos).extracting("sessionId").containsExactly(SESSION_ID, SESSION_ID2);
}
@Test
void getAllSessionsForAuthenticatedPrincipal() {
setUpSessions();
List<SessionInformation> allSessionInfos = this.sessionRegistry
.getAllSessions(PRINCIPAL, true);
assertThat(allSessionInfos).extracting("sessionId").containsExactly(SESSION_ID,
SESSION_ID2);
.getAllSessions((AuthenticatedPrincipal) () -> USER_NAME, true);
assertThat(allSessionInfos).extracting("sessionId").containsExactly(SESSION_ID, SESSION_ID2);
}
@Test
public void getNonExpiredSessions() {
void getAllSessionsForPrincipal() {
setUpSessions();
List<SessionInformation> allSessionInfos = this.sessionRegistry.getAllSessions(new TestPrincipal(USER_NAME),
true);
assertThat(allSessionInfos).extracting("sessionId").containsExactly(SESSION_ID, SESSION_ID2);
}
@Test
void getNonExpiredSessions() {
setUpSessions();
List<SessionInformation> nonExpiredSessionInfos = this.sessionRegistry
.getAllSessions(PRINCIPAL, false);
List<SessionInformation> nonExpiredSessionInfos = this.sessionRegistry.getAllSessions(PRINCIPAL, false);
assertThat(nonExpiredSessionInfos).extracting("sessionId")
.containsExactly(SESSION_ID2);
assertThat(nonExpiredSessionInfos).extracting("sessionId").containsExactly(SESSION_ID2);
}
@Test
public void expireNow() {
void expireNow() {
Session session = createSession(SESSION_ID, USER_NAME, NOW);
when(this.sessionRepository.findById(SESSION_ID)).thenReturn(session);
SessionInformation sessionInfo = this.sessionRegistry
.getSessionInformation(SESSION_ID);
SessionInformation sessionInfo = this.sessionRegistry.getSessionInformation(SESSION_ID);
assertThat(sessionInfo.isExpired()).isFalse();
sessionInfo.expireNow();
@@ -146,13 +150,11 @@ public class SpringSessionBackedSessionRegistryTest {
assertThat(sessionInfo.isExpired()).isTrue();
ArgumentCaptor<Session> captor = ArgumentCaptor.forClass(Session.class);
verify(this.sessionRepository).save(captor.capture());
assertThat(captor.getValue().<Boolean>getAttribute(
SpringSessionBackedSessionInformation.EXPIRED_ATTR))
.isEqualTo(Boolean.TRUE);
assertThat(captor.getValue().<Boolean>getAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR))
.isEqualTo(Boolean.TRUE);
}
private Session createSession(String sessionId, String userName,
Instant lastAccessed) {
private Session createSession(String sessionId, String userName, Instant lastAccessed) {
MapSession session = new MapSession(sessionId);
session.setLastAccessedTime(lastAccessed);
Authentication authentication = mock(Authentication.class);
@@ -165,14 +167,48 @@ public class SpringSessionBackedSessionRegistryTest {
private void setUpSessions() {
Session session1 = createSession(SESSION_ID, USER_NAME, NOW);
session1.setAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR,
Boolean.TRUE);
session1.setAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR, Boolean.TRUE);
Session session2 = createSession(SESSION_ID2, USER_NAME, NOW);
Map<String, Session> sessions = new LinkedHashMap<>();
sessions.put(session1.getId(), session1);
sessions.put(session2.getId(), session2);
when(this.sessionRepository.findByPrincipalName(USER_NAME))
.thenReturn(sessions);
when(this.sessionRepository.findByPrincipalName(USER_NAME)).thenReturn(sessions);
}
private static final class TestPrincipal implements Principal {
private final String name;
private TestPrincipal(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
@Override
public boolean equals(Object another) {
if (this == another) {
return true;
}
if (another instanceof TestPrincipal) {
return this.name.equals(((TestPrincipal) another).name);
}
return false;
}
@Override
public int hashCode() {
return this.name.hashCode();
}
@Override
public String toString() {
return this.name;
}
}
}

View File

@@ -33,77 +33,67 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
/**
* Tests for {@link SpringSessionRememberMeServices}.
*
* @author Vedran Pavic
*/
public class SpringSessionRememberMeServicesTests {
class SpringSessionRememberMeServicesTests {
private SpringSessionRememberMeServices rememberMeServices;
@Test
public void create() {
void create() {
this.rememberMeServices = new SpringSessionRememberMeServices();
assertThat(ReflectionTestUtils.getField(this.rememberMeServices,
"rememberMeParameterName")).isEqualTo("remember-me");
assertThat(
ReflectionTestUtils.getField(this.rememberMeServices, "alwaysRemember"))
.isEqualTo(false);
assertThat(
ReflectionTestUtils.getField(this.rememberMeServices, "validitySeconds"))
.isEqualTo(2592000);
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "rememberMeParameterName"))
.isEqualTo("remember-me");
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "alwaysRemember")).isEqualTo(false);
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "validitySeconds")).isEqualTo(2592000);
}
@Test
public void createWithCustomParameter() {
void createWithCustomParameter() {
this.rememberMeServices = new SpringSessionRememberMeServices();
this.rememberMeServices.setRememberMeParameterName("test-param");
assertThat(ReflectionTestUtils.getField(this.rememberMeServices,
"rememberMeParameterName")).isEqualTo("test-param");
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "rememberMeParameterName"))
.isEqualTo("test-param");
}
@Test
public void createWithNullParameter() {
void createWithNullParameter() {
this.rememberMeServices = new SpringSessionRememberMeServices();
assertThatIllegalArgumentException()
.isThrownBy(
() -> this.rememberMeServices.setRememberMeParameterName(null))
assertThatIllegalArgumentException().isThrownBy(() -> this.rememberMeServices.setRememberMeParameterName(null))
.withMessage("rememberMeParameterName cannot be empty or null");
}
@Test
public void createWithAlwaysRemember() {
void createWithAlwaysRemember() {
this.rememberMeServices = new SpringSessionRememberMeServices();
this.rememberMeServices.setAlwaysRemember(true);
assertThat(
ReflectionTestUtils.getField(this.rememberMeServices, "alwaysRemember"))
.isEqualTo(true);
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "alwaysRemember")).isEqualTo(true);
}
@Test
public void createWithCustomValidity() {
void createWithCustomValidity() {
this.rememberMeServices = new SpringSessionRememberMeServices();
this.rememberMeServices.setValiditySeconds(100000);
assertThat(
ReflectionTestUtils.getField(this.rememberMeServices, "validitySeconds"))
.isEqualTo(100000);
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "validitySeconds")).isEqualTo(100000);
}
@Test
public void autoLogin() {
void autoLogin() {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
this.rememberMeServices = new SpringSessionRememberMeServices();
this.rememberMeServices.autoLogin(request, response);
verifyZeroInteractions(request, response);
verifyNoMoreInteractions(request, response);
}
// gh-752
@Test
public void loginFailRemoveSecurityContext() {
void loginFailRemoveSecurityContext() {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
HttpSession session = mock(HttpSession.class);
@@ -111,13 +101,12 @@ public class SpringSessionRememberMeServicesTests {
this.rememberMeServices = new SpringSessionRememberMeServices();
this.rememberMeServices.loginFail(request, response);
verify(request, times(1)).getSession(eq(false));
verify(session, times(1)).removeAttribute(
HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
verifyZeroInteractions(request, response, session);
verify(session, times(1)).removeAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
verifyNoMoreInteractions(request, response, session);
}
@Test
public void loginSuccess() {
void loginSuccess() {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
Authentication authentication = mock(Authentication.class);
@@ -128,14 +117,13 @@ public class SpringSessionRememberMeServicesTests {
this.rememberMeServices.loginSuccess(request, response, authentication);
verify(request, times(1)).getParameter(eq("remember-me"));
verify(request, times(1)).getSession();
verify(request, times(1)).setAttribute(
eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(request, times(1)).setAttribute(eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(session, times(1)).setMaxInactiveInterval(eq(2592000));
verifyZeroInteractions(request, response, session, authentication);
verifyNoMoreInteractions(request, response, session, authentication);
}
@Test
public void loginSuccessWithCustomParameter() {
void loginSuccessWithCustomParameter() {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
Authentication authentication = mock(Authentication.class);
@@ -147,14 +135,13 @@ public class SpringSessionRememberMeServicesTests {
this.rememberMeServices.loginSuccess(request, response, authentication);
verify(request, times(1)).getParameter(eq("test-param"));
verify(request, times(1)).getSession();
verify(request, times(1)).setAttribute(
eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(request, times(1)).setAttribute(eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(session, times(1)).setMaxInactiveInterval(eq(2592000));
verifyZeroInteractions(request, response, session, authentication);
verifyNoMoreInteractions(request, response, session, authentication);
}
@Test
public void loginSuccessWithAlwaysRemember() {
void loginSuccessWithAlwaysRemember() {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
Authentication authentication = mock(Authentication.class);
@@ -164,14 +151,13 @@ public class SpringSessionRememberMeServicesTests {
this.rememberMeServices.setAlwaysRemember(true);
this.rememberMeServices.loginSuccess(request, response, authentication);
verify(request, times(1)).getSession();
verify(request, times(1)).setAttribute(
eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(request, times(1)).setAttribute(eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(session, times(1)).setMaxInactiveInterval(eq(2592000));
verifyZeroInteractions(request, response, session, authentication);
verifyNoMoreInteractions(request, response, session, authentication);
}
@Test
public void loginSuccessWithCustomValidity() {
void loginSuccessWithCustomValidity() {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
Authentication authentication = mock(Authentication.class);
@@ -183,10 +169,9 @@ public class SpringSessionRememberMeServicesTests {
this.rememberMeServices.loginSuccess(request, response, authentication);
verify(request, times(1)).getParameter(eq("remember-me"));
verify(request, times(1)).getSession();
verify(request, times(1)).setAttribute(
eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(request, times(1)).setAttribute(eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(session, times(1)).setMaxInactiveInterval(eq(100000));
verifyZeroInteractions(request, response, session, authentication);
verifyNoMoreInteractions(request, response, session, authentication);
}
}

View File

@@ -34,17 +34,20 @@ import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link CookieHttpSessionIdResolver}.
*/
public class CookieHttpSessionIdResolverTests {
class CookieHttpSessionIdResolverTests {
private MockHttpServletRequest request;
private MockHttpServletResponse response;
private CookieHttpSessionIdResolver strategy;
private String cookieName;
private Session session;
@BeforeEach
public void setup() throws Exception {
void setup() {
this.cookieName = "SESSION";
this.session = new MapSession();
this.request = new MockHttpServletRequest();
@@ -53,19 +56,19 @@ public class CookieHttpSessionIdResolverTests {
}
@Test
public void getRequestedSessionIdNull() throws Exception {
void getRequestedSessionIdNull() {
assertThat(this.strategy.resolveSessionIds(this.request)).isEmpty();
}
@Test
public void getRequestedSessionIdNotNull() throws Exception {
void getRequestedSessionIdNotNull() {
setSessionCookie(this.session.getId());
assertThat(this.strategy.resolveSessionIds(this.request))
.isEqualTo(Collections.singletonList(this.session.getId()));
}
@Test
public void getRequestedSessionIdNotNullCustomCookieName() throws Exception {
void getRequestedSessionIdNotNullCustomCookieName() {
setCookieName("CUSTOM");
setSessionCookie(this.session.getId());
assertThat(this.strategy.resolveSessionIds(this.request))
@@ -73,13 +76,13 @@ public class CookieHttpSessionIdResolverTests {
}
@Test
public void onNewSession() throws Exception {
void onNewSession() {
this.strategy.setSessionId(this.request, this.response, this.session.getId());
assertThat(getSessionId()).isEqualTo(this.session.getId());
}
@Test
public void onNewSessionTwiceSameId() throws Exception {
void onNewSessionTwiceSameId() {
this.strategy.setSessionId(this.request, this.response, this.session.getId());
this.strategy.setSessionId(this.request, this.response, this.session.getId());
@@ -87,7 +90,7 @@ public class CookieHttpSessionIdResolverTests {
}
@Test
public void onNewSessionTwiceNewId() throws Exception {
void onNewSessionTwiceNewId() {
Session newSession = new MapSession();
this.strategy.setSessionId(this.request, this.response, this.session.getId());
@@ -101,49 +104,47 @@ public class CookieHttpSessionIdResolverTests {
}
@Test
public void onNewSessionCookiePath() throws Exception {
void onNewSessionCookiePath() {
this.request.setContextPath("/somethingunique");
this.strategy.setSessionId(this.request, this.response, this.session.getId());
Cookie sessionCookie = this.response.getCookie(this.cookieName);
assertThat(sessionCookie.getPath())
.isEqualTo(this.request.getContextPath() + "/");
assertThat(sessionCookie.getPath()).isEqualTo(this.request.getContextPath() + "/");
}
@Test
public void onNewSessionCustomCookieName() throws Exception {
void onNewSessionCustomCookieName() {
setCookieName("CUSTOM");
this.strategy.setSessionId(this.request, this.response, this.session.getId());
assertThat(getSessionId()).isEqualTo(this.session.getId());
}
@Test
public void onDeleteSession() throws Exception {
void onDeleteSession() {
this.strategy.expireSession(this.request, this.response);
assertThat(getSessionId()).isEmpty();
}
@Test
public void onDeleteSessionCookiePath() throws Exception {
void onDeleteSessionCookiePath() {
this.request.setContextPath("/somethingunique");
this.strategy.expireSession(this.request, this.response);
Cookie sessionCookie = this.response.getCookie(this.cookieName);
assertThat(sessionCookie.getPath())
.isEqualTo(this.request.getContextPath() + "/");
assertThat(sessionCookie.getPath()).isEqualTo(this.request.getContextPath() + "/");
}
@Test
public void onDeleteSessionCustomCookieName() throws Exception {
void onDeleteSessionCustomCookieName() {
setCookieName("CUSTOM");
this.strategy.expireSession(this.request, this.response);
assertThat(getSessionId()).isEmpty();
}
@Test
public void createSessionCookieValue() {
assertThat(createSessionCookieValue(17)).isEqualToIgnoringCase(
"0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 a 10 b 11 c 12 d 13 e 14 f 15 10 16");
void createSessionCookieValue() {
assertThat(createSessionCookieValue(17))
.isEqualToIgnoringCase("0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 a 10 b 11 c 12 d 13 e 14 f 15 10 16");
}
private String createSessionCookieValue(long size) {

View File

@@ -16,6 +16,11 @@
package org.springframework.session.web.http;
import java.time.Clock;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import javax.servlet.http.Cookie;
@@ -42,7 +47,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
* @author Vedran Pavic
* @author Eddú Meléndez
*/
public class DefaultCookieSerializerTests {
class DefaultCookieSerializerTests {
private String cookieName;
@@ -55,7 +60,7 @@ public class DefaultCookieSerializerTests {
private String sessionId;
@BeforeEach
public void setup() {
void setup() {
this.cookieName = "SESSION";
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
@@ -66,459 +71,397 @@ public class DefaultCookieSerializerTests {
// --- readCookieValues ---
@Test
public void readCookieValuesNull() {
void readCookieValuesNull() {
assertThat(this.serializer.readCookieValues(this.request)).isEmpty();
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieValuesSingle(boolean useBase64Encoding) {
@ValueSource(booleans = { true, false })
void readCookieValuesSingle(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
this.request.setCookies(
createCookie(this.cookieName, this.sessionId, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request))
.containsOnly(this.sessionId);
this.request.setCookies(createCookie(this.cookieName, this.sessionId, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request)).containsOnly(this.sessionId);
}
@Test
public void readCookieSerializerUseBase64EncodingTrueValuesNotBase64() {
void readCookieSerializerUseBase64EncodingTrueValuesNotBase64() {
this.sessionId = "&^%$*";
this.serializer.setUseBase64Encoding(true);
this.request.setCookies(new Cookie(this.cookieName, this.sessionId));
assertThat(this.serializer.readCookieValues(this.request)).isEmpty();
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieValuesSingleAndInvalidName(boolean useBase64Encoding) {
@ValueSource(booleans = { true, false })
void readCookieValuesSingleAndInvalidName(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
this.request.setCookies(
createCookie(this.cookieName, this.sessionId, useBase64Encoding),
createCookie(this.cookieName + "INVALID", this.sessionId + "INVALID",
useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request))
.containsOnly(this.sessionId);
this.request.setCookies(createCookie(this.cookieName, this.sessionId, useBase64Encoding),
createCookie(this.cookieName + "INVALID", this.sessionId + "INVALID", useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request)).containsOnly(this.sessionId);
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieValuesMulti(boolean useBase64Encoding) {
@ValueSource(booleans = { true, false })
void readCookieValuesMulti(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
String secondSession = "secondSessionId";
this.request.setCookies(
createCookie(this.cookieName, this.sessionId, useBase64Encoding),
this.request.setCookies(createCookie(this.cookieName, this.sessionId, useBase64Encoding),
createCookie(this.cookieName, secondSession, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request))
.containsExactly(this.sessionId, secondSession);
assertThat(this.serializer.readCookieValues(this.request)).containsExactly(this.sessionId, secondSession);
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieValuesMultiCustomSessionCookieName(boolean useBase64Encoding) {
@ValueSource(booleans = { true, false })
void readCookieValuesMultiCustomSessionCookieName(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
setCookieName("JSESSIONID");
String secondSession = "secondSessionId";
this.request.setCookies(
createCookie(this.cookieName, this.sessionId, useBase64Encoding),
this.request.setCookies(createCookie(this.cookieName, this.sessionId, useBase64Encoding),
createCookie(this.cookieName, secondSession, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request))
.containsExactly(this.sessionId, secondSession);
assertThat(this.serializer.readCookieValues(this.request)).containsExactly(this.sessionId, secondSession);
}
// gh-392
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieValuesNullCookieValue(boolean useBase64Encoding) {
@ValueSource(booleans = { true, false })
void readCookieValuesNullCookieValue(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
this.request.setCookies(createCookie(this.cookieName, null, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request)).isEmpty();
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieValuesNullCookieValueAndJvmRoute(boolean useBase64Encoding) {
@ValueSource(booleans = { true, false })
void readCookieValuesNullCookieValueAndJvmRoute(boolean useBase64Encoding) {
this.serializer.setJvmRoute("123");
this.request.setCookies(createCookie(this.cookieName, null, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request)).isEmpty();
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieValuesNullCookieValueAndNotNullCookie(boolean useBase64Encoding) {
@ValueSource(booleans = { true, false })
void readCookieValuesNullCookieValueAndNotNullCookie(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
this.serializer.setJvmRoute("123");
this.request.setCookies(createCookie(this.cookieName, null, useBase64Encoding),
createCookie(this.cookieName, this.sessionId, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request))
.containsOnly(this.sessionId);
assertThat(this.serializer.readCookieValues(this.request)).containsOnly(this.sessionId);
}
// --- writeCookie ---
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void writeCookie(boolean useBase64Encoding) {
@ValueSource(booleans = { true, false })
void writeCookie(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookieValue(useBase64Encoding)).isEqualTo(this.sessionId);
}
// --- httpOnly ---
@Test
public void writeCookieHttpOnlyDefault() {
void writeCookieHttpOnlyDefault() {
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().isHttpOnly()).isTrue();
}
@Test
public void writeCookieHttpOnlySetTrue() {
void writeCookieHttpOnlySetTrue() {
this.serializer.setUseHttpOnlyCookie(true);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().isHttpOnly()).isTrue();
}
@Test
public void writeCookieHttpOnlySetFalse() {
void writeCookieHttpOnlySetFalse() {
this.serializer.setUseHttpOnlyCookie(false);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().isHttpOnly()).isFalse();
}
// --- domainName ---
@Test
public void writeCookieDomainNameDefault() {
void writeCookieDomainNameDefault() {
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getDomain()).isNull();
}
@Test
public void writeCookieDomainNameCustom() {
void writeCookieDomainNameCustom() {
String domainName = "example.com";
this.serializer.setDomainName(domainName);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getDomain()).isEqualTo(domainName);
}
@Test
public void setDomainNameAndDomainNamePatternThrows() {
void setDomainNameAndDomainNamePatternThrows() {
this.serializer.setDomainName("example.com");
assertThatIllegalStateException()
.isThrownBy(() -> this.serializer.setDomainNamePattern(".*"))
assertThatIllegalStateException().isThrownBy(() -> this.serializer.setDomainNamePattern(".*"))
.withMessage("Cannot set both domainName and domainNamePattern");
}
// --- domainNamePattern ---
@Test
public void writeCookieDomainNamePattern() {
void writeCookieDomainNamePattern() {
String domainNamePattern = "^.+?\\.(\\w+\\.[a-z]+)$";
this.serializer.setDomainNamePattern(domainNamePattern);
String[] matchingDomains = { "child.sub.example.com", "www.example.com" };
for (String domain : matchingDomains) {
this.request.setServerName(domain);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getDomain()).isEqualTo("example.com");
this.response = new MockHttpServletResponse();
}
String[] notMatchingDomains = { "example.com", "localhost", "127.0.0.1" };
for (String domain : notMatchingDomains) {
this.request.setServerName(domain);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getDomain()).isNull();
this.response = new MockHttpServletResponse();
}
}
@Test
public void setDomainNamePatternAndDomainNameThrows() {
void setDomainNamePatternAndDomainNameThrows() {
this.serializer.setDomainNamePattern(".*");
assertThatIllegalStateException()
.isThrownBy(() -> this.serializer.setDomainName("example.com"))
assertThatIllegalStateException().isThrownBy(() -> this.serializer.setDomainName("example.com"))
.withMessage("Cannot set both domainName and domainNamePattern");
}
// --- cookieName ---
@Test
public void writeCookieCookieNameDefault() {
void writeCookieCookieNameDefault() {
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getName()).isEqualTo("SESSION");
}
@Test
public void writeCookieCookieNameCustom() {
void writeCookieCookieNameCustom() {
String cookieName = "JSESSIONID";
setCookieName(cookieName);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getName()).isEqualTo(cookieName);
}
@Test
public void setCookieNameNullThrows() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.serializer.setCookieName(null))
void setCookieNameNullThrows() {
assertThatIllegalArgumentException().isThrownBy(() -> this.serializer.setCookieName(null))
.withMessage("cookieName cannot be null");
}
// --- cookiePath ---
@Test
public void writeCookieCookiePathDefaultEmptyContextPathUsed() {
void writeCookieCookiePathDefaultEmptyContextPathUsed() {
this.request.setContextPath("");
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getPath()).isEqualTo("/");
}
@Test
public void writeCookieCookiePathDefaultContextPathUsed() {
void writeCookieCookiePathDefaultContextPathUsed() {
this.request.setContextPath("/context");
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getPath()).isEqualTo("/context/");
}
@Test
public void writeCookieCookiePathExplicitNullCookiePathContextPathUsed() {
void writeCookieCookiePathExplicitNullCookiePathContextPathUsed() {
this.request.setContextPath("/context");
this.serializer.setCookiePath(null);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getPath()).isEqualTo("/context/");
}
@Test
public void writeCookieCookiePathExplicitCookiePath() {
void writeCookieCookiePathExplicitCookiePath() {
this.request.setContextPath("/context");
this.serializer.setCookiePath("/");
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getPath()).isEqualTo("/");
}
// --- cookieMaxAge ---
@Test
public void writeCookieCookieMaxAgeDefault() {
void writeCookieCookieMaxAgeDefault() {
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getMaxAge()).isEqualTo(-1);
assertThat(getCookie().getExpires()).isNull();
}
@Test
public void writeCookieCookieMaxAgeExplicit() {
void writeCookieCookieMaxAgeExplicit() {
this.serializer.setClock(Clock.fixed(Instant.parse("2019-10-07T20:10:00Z"), ZoneOffset.UTC));
this.serializer.setCookieMaxAge(100);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getMaxAge()).isEqualTo(100);
MockCookie cookie = getCookie();
assertThat(cookie.getMaxAge()).isEqualTo(100);
ZonedDateTime expires = cookie.getExpires();
assertThat(expires).isNotNull();
assertThat(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME)).isEqualTo("Mon, 7 Oct 2019 20:11:40 GMT");
}
@Test
public void writeCookieCookieMaxAgeExplicitEmptyCookie() {
void writeCookieCookieMaxAgeExplicitEmptyCookie() {
this.serializer.setClock(Clock.fixed(Instant.parse("2019-10-07T20:10:00Z"), ZoneOffset.UTC));
this.serializer.setCookieMaxAge(100);
this.serializer.writeCookieValue(cookieValue(""));
assertThat(getCookie().getMaxAge()).isEqualTo(0);
MockCookie cookie = getCookie();
assertThat(cookie.getMaxAge()).isEqualTo(0);
ZonedDateTime expires = cookie.getExpires();
assertThat(expires).isNotNull();
assertThat(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME)).isEqualTo("Thu, 1 Jan 1970 00:00:00 GMT");
}
@Test
public void writeCookieCookieMaxAgeExplicitCookieValue() {
void writeCookieCookieMaxAgeExplicitCookieValue() {
this.serializer.setClock(Clock.fixed(Instant.parse("2019-10-07T20:10:00Z"), ZoneOffset.UTC));
CookieValue cookieValue = cookieValue(this.sessionId);
cookieValue.setCookieMaxAge(100);
this.serializer.writeCookieValue(cookieValue);
assertThat(getCookie().getMaxAge()).isEqualTo(100);
MockCookie cookie = getCookie();
assertThat(cookie.getMaxAge()).isEqualTo(100);
ZonedDateTime expires = cookie.getExpires();
assertThat(expires).isNotNull();
assertThat(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME)).isEqualTo("Mon, 7 Oct 2019 20:11:40 GMT");
}
// --- secure ---
@Test
public void writeCookieDefaultInsecureRequest() {
void writeCookieDefaultInsecureRequest() {
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getSecure()).isFalse();
}
@Test
public void writeCookieSecureSecureRequest() {
void writeCookieSecureSecureRequest() {
this.request.setSecure(true);
this.serializer.setUseSecureCookie(true);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getSecure()).isTrue();
}
@Test
public void writeCookieSecureInsecureRequest() {
void writeCookieSecureInsecureRequest() {
this.serializer.setUseSecureCookie(true);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getSecure()).isTrue();
}
@Test
public void writeCookieInsecureSecureRequest() {
void writeCookieInsecureSecureRequest() {
this.request.setSecure(true);
this.serializer.setUseSecureCookie(false);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getSecure()).isFalse();
}
@Test
public void writeCookieInecureInsecureRequest() {
void writeCookieInecureInsecureRequest() {
this.serializer.setUseSecureCookie(false);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getSecure()).isFalse();
}
// --- jvmRoute ---
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void writeCookieJvmRoute(boolean useBase64Encoding) {
@ValueSource(booleans = { true, false })
void writeCookieJvmRoute(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
String jvmRoute = "route";
this.serializer.setJvmRoute(jvmRoute);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookieValue(useBase64Encoding))
.isEqualTo(this.sessionId + "." + jvmRoute);
assertThat(getCookieValue(useBase64Encoding)).isEqualTo(this.sessionId + "." + jvmRoute);
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieJvmRoute(boolean useBase64Encoding) {
@ValueSource(booleans = { true, false })
void readCookieJvmRoute(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
String jvmRoute = "route";
this.serializer.setJvmRoute(jvmRoute);
this.request.setCookies(createCookie(this.cookieName,
this.sessionId + "." + jvmRoute, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request))
.containsOnly(this.sessionId);
this.request.setCookies(createCookie(this.cookieName, this.sessionId + "." + jvmRoute, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request)).containsOnly(this.sessionId);
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieJvmRouteRouteMissing(boolean useBase64Encoding) {
@ValueSource(booleans = { true, false })
void readCookieJvmRouteRouteMissing(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
String jvmRoute = "route";
this.serializer.setJvmRoute(jvmRoute);
this.request.setCookies(
createCookie(this.cookieName, this.sessionId, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request))
.containsOnly(this.sessionId);
this.request.setCookies(createCookie(this.cookieName, this.sessionId, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request)).containsOnly(this.sessionId);
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieJvmRouteOnlyRoute(boolean useBase64Encoding) {
@ValueSource(booleans = { true, false })
void readCookieJvmRouteOnlyRoute(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
String jvmRoute = "route";
this.serializer.setJvmRoute(jvmRoute);
this.request.setCookies(
createCookie(this.cookieName, "." + jvmRoute, useBase64Encoding));
this.request.setCookies(createCookie(this.cookieName, "." + jvmRoute, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request)).containsOnly("");
}
// --- rememberMe ---
@Test
public void writeCookieRememberMeCookieMaxAgeDefault() {
void writeCookieRememberMeCookieMaxAgeDefault() {
this.request.setAttribute("rememberMe", true);
this.serializer.setRememberMeRequestAttribute("rememberMe");
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getMaxAge()).isEqualTo(Integer.MAX_VALUE);
}
@Test
public void writeCookieRememberMeCookieMaxAgeOverride() {
void writeCookieRememberMeCookieMaxAgeOverride() {
this.request.setAttribute("rememberMe", true);
this.serializer.setRememberMeRequestAttribute("rememberMe");
CookieValue cookieValue = cookieValue(this.sessionId);
cookieValue.setCookieMaxAge(100);
this.serializer.writeCookieValue(cookieValue);
assertThat(getCookie().getMaxAge()).isEqualTo(100);
}
// --- sameSite ---
@Test
public void writeCookieDefaultSameSiteLax() {
void writeCookieDefaultSameSiteLax() {
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getSameSite()).isEqualTo("Lax");
}
@Test
public void writeCookieSetSameSiteLax() {
void writeCookieSetSameSiteLax() {
this.serializer.setSameSite("Lax");
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getSameSite()).isEqualTo("Lax");
}
@Test
public void writeCookieSetSameSiteStrict() {
void writeCookieSetSameSiteStrict() {
this.serializer.setSameSite("Strict");
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getSameSite()).isEqualTo("Strict");
}
@Test
public void writeCookieSetSameSiteNull() {
void writeCookieSetSameSiteNull() {
this.serializer.setSameSite(null);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getSameSite()).isNull();
}
public void setCookieName(String cookieName) {
void setCookieName(String cookieName) {
this.cookieName = cookieName;
this.serializer.setCookieName(cookieName);
}

View File

@@ -32,7 +32,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
/**
* Tests for {@link HeaderHttpSessionIdResolver}.
*/
public class HeaderHttpSessionIdResolverTests {
class HeaderHttpSessionIdResolverTests {
private static final String HEADER_X_AUTH_TOKEN = "X-Auth-Token";
@@ -43,71 +43,64 @@ public class HeaderHttpSessionIdResolverTests {
private HeaderHttpSessionIdResolver resolver;
@BeforeEach
public void setup() {
void setup() {
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
this.resolver = HeaderHttpSessionIdResolver.xAuthToken();
}
@Test
public void createResolverWithXAuthTokenHeader() {
void createResolverWithXAuthTokenHeader() {
HeaderHttpSessionIdResolver resolver = HeaderHttpSessionIdResolver.xAuthToken();
assertThat(ReflectionTestUtils.getField(resolver, "headerName"))
.isEqualTo("X-Auth-Token");
assertThat(ReflectionTestUtils.getField(resolver, "headerName")).isEqualTo("X-Auth-Token");
}
@Test
public void createResolverWithAuthenticationInfoHeader() {
HeaderHttpSessionIdResolver resolver = HeaderHttpSessionIdResolver
.authenticationInfo();
assertThat(ReflectionTestUtils.getField(resolver, "headerName"))
.isEqualTo("Authentication-Info");
void createResolverWithAuthenticationInfoHeader() {
HeaderHttpSessionIdResolver resolver = HeaderHttpSessionIdResolver.authenticationInfo();
assertThat(ReflectionTestUtils.getField(resolver, "headerName")).isEqualTo("Authentication-Info");
}
@Test
public void createResolverWithCustomHeaderName() {
HeaderHttpSessionIdResolver resolver = new HeaderHttpSessionIdResolver(
"Custom-Header");
assertThat(ReflectionTestUtils.getField(resolver, "headerName"))
.isEqualTo("Custom-Header");
void createResolverWithCustomHeaderName() {
HeaderHttpSessionIdResolver resolver = new HeaderHttpSessionIdResolver("Custom-Header");
assertThat(ReflectionTestUtils.getField(resolver, "headerName")).isEqualTo("Custom-Header");
}
@Test
public void createResolverWithNullHeaderName() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new HeaderHttpSessionIdResolver(null))
void createResolverWithNullHeaderName() {
assertThatIllegalArgumentException().isThrownBy(() -> new HeaderHttpSessionIdResolver(null))
.withMessage("headerName cannot be null");
}
@Test
public void getRequestedSessionIdNull() {
void getRequestedSessionIdNull() {
assertThat(this.resolver.resolveSessionIds(this.request)).isEmpty();
}
@Test
public void getRequestedSessionIdNotNull() {
void getRequestedSessionIdNotNull() {
String sessionId = UUID.randomUUID().toString();
setSessionId(sessionId);
assertThat(this.resolver.resolveSessionIds(this.request))
.isEqualTo(Collections.singletonList(sessionId));
assertThat(this.resolver.resolveSessionIds(this.request)).isEqualTo(Collections.singletonList(sessionId));
}
@Test
public void onNewSession() {
void onNewSession() {
String sessionId = UUID.randomUUID().toString();
this.resolver.setSessionId(this.request, this.response, sessionId);
assertThat(getSessionId()).isEqualTo(sessionId);
}
@Test
public void onDeleteSession() {
void onDeleteSession() {
this.resolver.expireSession(this.request, this.response);
assertThat(getSessionId()).isEmpty();
}
// the header is set as apposed to added
@Test
public void onNewSessionMulti() {
void onNewSessionMulti() {
String sessionId = UUID.randomUUID().toString();
this.resolver.setSessionId(this.request, this.response, sessionId);
this.resolver.setSessionId(this.request, this.response, sessionId);
@@ -117,7 +110,7 @@ public class HeaderHttpSessionIdResolverTests {
// the header is set as apposed to added
@Test
public void onDeleteSessionMulti() {
void onDeleteSessionMulti() {
this.resolver.expireSession(this.request, this.response);
this.resolver.expireSession(this.request, this.response);
assertThat(this.response.getHeaders(HEADER_X_AUTH_TOKEN).size()).isEqualTo(1);

View File

@@ -18,6 +18,7 @@ package org.springframework.session.web.http;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import javax.servlet.ServletOutputStream;
@@ -32,22 +33,25 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify;
public class OnCommittedResponseWrapperTests {
class OnCommittedResponseWrapperTests {
private static final String NL = "\r\n";
@Mock
HttpServletResponse delegate;
@Mock
PrintWriter writer;
@Mock
ServletOutputStream out;
OnCommittedResponseWrapper response;
private OnCommittedResponseWrapper response;
boolean committed;
private boolean committed;
@BeforeEach
public void setup() throws Exception {
void setup() throws Exception {
MockitoAnnotations.initMocks(this);
this.response = new OnCommittedResponseWrapper(this.delegate) {
@Override
@@ -62,14 +66,14 @@ public class OnCommittedResponseWrapperTests {
// --- printwriter
@Test
public void printWriterHashCode() throws Exception {
void printWriterHashCode() throws Exception {
int expected = this.writer.hashCode();
assertThat(this.response.getWriter().hashCode()).isEqualTo(expected);
}
@Test
public void printWriterCheckError() throws Exception {
void printWriterCheckError() throws Exception {
boolean expected = true;
given(this.writer.checkError()).willReturn(expected);
@@ -77,7 +81,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterWriteInt() throws Exception {
void printWriterWriteInt() throws Exception {
int expected = 1;
this.response.getWriter().write(expected);
@@ -86,7 +90,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterWriteCharIntInt() throws Exception {
void printWriterWriteCharIntInt() throws Exception {
char[] buff = new char[0];
int off = 2;
int len = 3;
@@ -97,7 +101,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterWriteChar() throws Exception {
void printWriterWriteChar() throws Exception {
char[] buff = new char[0];
this.response.getWriter().write(buff);
@@ -106,7 +110,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterWriteStringIntInt() throws Exception {
void printWriterWriteStringIntInt() throws Exception {
String s = "";
int off = 2;
int len = 3;
@@ -117,7 +121,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterWriteString() throws Exception {
void printWriterWriteString() throws Exception {
String s = "";
this.response.getWriter().write(s);
@@ -126,7 +130,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintBoolean() throws Exception {
void printWriterPrintBoolean() throws Exception {
boolean b = true;
this.response.getWriter().print(b);
@@ -135,7 +139,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintChar() throws Exception {
void printWriterPrintChar() throws Exception {
char c = 1;
this.response.getWriter().print(c);
@@ -144,7 +148,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintInt() throws Exception {
void printWriterPrintInt() throws Exception {
int i = 1;
this.response.getWriter().print(i);
@@ -153,7 +157,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintLong() throws Exception {
void printWriterPrintLong() throws Exception {
long l = 1;
this.response.getWriter().print(l);
@@ -162,7 +166,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintFloat() throws Exception {
void printWriterPrintFloat() throws Exception {
float f = 1;
this.response.getWriter().print(f);
@@ -171,7 +175,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintDouble() throws Exception {
void printWriterPrintDouble() throws Exception {
double x = 1;
this.response.getWriter().print(x);
@@ -180,7 +184,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintCharArray() throws Exception {
void printWriterPrintCharArray() throws Exception {
char[] x = new char[0];
this.response.getWriter().print(x);
@@ -189,7 +193,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintString() throws Exception {
void printWriterPrintString() throws Exception {
String x = "1";
this.response.getWriter().print(x);
@@ -198,7 +202,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintObject() throws Exception {
void printWriterPrintObject() throws Exception {
Object x = "1";
this.response.getWriter().print(x);
@@ -207,14 +211,14 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintln() throws Exception {
void printWriterPrintln() throws Exception {
this.response.getWriter().println();
verify(this.writer).println();
}
@Test
public void printWriterPrintlnBoolean() throws Exception {
void printWriterPrintlnBoolean() throws Exception {
boolean b = true;
this.response.getWriter().println(b);
@@ -223,7 +227,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnChar() throws Exception {
void printWriterPrintlnChar() throws Exception {
char c = 1;
this.response.getWriter().println(c);
@@ -232,7 +236,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnInt() throws Exception {
void printWriterPrintlnInt() throws Exception {
int i = 1;
this.response.getWriter().println(i);
@@ -241,7 +245,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnLong() throws Exception {
void printWriterPrintlnLong() throws Exception {
long l = 1;
this.response.getWriter().println(l);
@@ -250,7 +254,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnFloat() throws Exception {
void printWriterPrintlnFloat() throws Exception {
float f = 1;
this.response.getWriter().println(f);
@@ -259,7 +263,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnDouble() throws Exception {
void printWriterPrintlnDouble() throws Exception {
double x = 1;
this.response.getWriter().println(x);
@@ -268,7 +272,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnCharArray() throws Exception {
void printWriterPrintlnCharArray() throws Exception {
char[] x = new char[0];
this.response.getWriter().println(x);
@@ -277,7 +281,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnString() throws Exception {
void printWriterPrintlnString() throws Exception {
String x = "1";
this.response.getWriter().println(x);
@@ -286,7 +290,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnObject() throws Exception {
void printWriterPrintlnObject() throws Exception {
Object x = "1";
this.response.getWriter().println(x);
@@ -295,7 +299,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintfStringObjectVargs() throws Exception {
void printWriterPrintfStringObjectVargs() throws Exception {
String format = "format";
Object[] args = new Object[] { "1" };
@@ -305,7 +309,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintfLocaleStringObjectVargs() throws Exception {
void printWriterPrintfLocaleStringObjectVargs() throws Exception {
Locale l = Locale.US;
String format = "format";
Object[] args = new Object[] { "1" };
@@ -316,7 +320,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterFormatStringObjectVargs() throws Exception {
void printWriterFormatStringObjectVargs() throws Exception {
String format = "format";
Object[] args = new Object[] { "1" };
@@ -326,7 +330,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterFormatLocaleStringObjectVargs() throws Exception {
void printWriterFormatLocaleStringObjectVargs() throws Exception {
Locale l = Locale.US;
String format = "format";
Object[] args = new Object[] { "1" };
@@ -337,7 +341,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterAppendCharSequence() throws Exception {
void printWriterAppendCharSequence() throws Exception {
String x = "a";
this.response.getWriter().append(x);
@@ -346,7 +350,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterAppendCharSequenceIntInt() throws Exception {
void printWriterAppendCharSequenceIntInt() throws Exception {
String x = "abcdef";
int start = 1;
int end = 3;
@@ -357,7 +361,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterAppendChar() throws Exception {
void printWriterAppendChar() throws Exception {
char x = 1;
this.response.getWriter().append(x);
@@ -368,14 +372,14 @@ public class OnCommittedResponseWrapperTests {
// servletoutputstream
@Test
public void outputStreamHashCode() throws Exception {
void outputStreamHashCode() throws Exception {
int expected = this.out.hashCode();
assertThat(this.response.getOutputStream().hashCode()).isEqualTo(expected);
}
@Test
public void outputStreamWriteInt() throws Exception {
void outputStreamWriteInt() throws Exception {
int expected = 1;
this.response.getOutputStream().write(expected);
@@ -384,7 +388,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamWriteByte() throws Exception {
void outputStreamWriteByte() throws Exception {
byte[] expected = new byte[0];
this.response.getOutputStream().write(expected);
@@ -393,7 +397,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamWriteByteIntInt() throws Exception {
void outputStreamWriteByteIntInt() throws Exception {
int start = 1;
int end = 2;
byte[] expected = new byte[0];
@@ -404,7 +408,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintBoolean() throws Exception {
void outputStreamPrintBoolean() throws Exception {
boolean b = true;
this.response.getOutputStream().print(b);
@@ -413,7 +417,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintChar() throws Exception {
void outputStreamPrintChar() throws Exception {
char c = 1;
this.response.getOutputStream().print(c);
@@ -422,7 +426,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintInt() throws Exception {
void outputStreamPrintInt() throws Exception {
int i = 1;
this.response.getOutputStream().print(i);
@@ -431,7 +435,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintLong() throws Exception {
void outputStreamPrintLong() throws Exception {
long l = 1;
this.response.getOutputStream().print(l);
@@ -440,7 +444,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintFloat() throws Exception {
void outputStreamPrintFloat() throws Exception {
float f = 1;
this.response.getOutputStream().print(f);
@@ -449,7 +453,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintDouble() throws Exception {
void outputStreamPrintDouble() throws Exception {
double x = 1;
this.response.getOutputStream().print(x);
@@ -458,7 +462,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintString() throws Exception {
void outputStreamPrintString() throws Exception {
String x = "1";
this.response.getOutputStream().print(x);
@@ -467,14 +471,14 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintln() throws Exception {
void outputStreamPrintln() throws Exception {
this.response.getOutputStream().println();
verify(this.out).println();
}
@Test
public void outputStreamPrintlnBoolean() throws Exception {
void outputStreamPrintlnBoolean() throws Exception {
boolean b = true;
this.response.getOutputStream().println(b);
@@ -483,7 +487,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintlnChar() throws Exception {
void outputStreamPrintlnChar() throws Exception {
char c = 1;
this.response.getOutputStream().println(c);
@@ -492,7 +496,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintlnInt() throws Exception {
void outputStreamPrintlnInt() throws Exception {
int i = 1;
this.response.getOutputStream().println(i);
@@ -501,7 +505,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintlnLong() throws Exception {
void outputStreamPrintlnLong() throws Exception {
long l = 1;
this.response.getOutputStream().println(l);
@@ -510,7 +514,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintlnFloat() throws Exception {
void outputStreamPrintlnFloat() throws Exception {
float f = 1;
this.response.getOutputStream().println(f);
@@ -519,7 +523,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintlnDouble() throws Exception {
void outputStreamPrintlnDouble() throws Exception {
double x = 1;
this.response.getOutputStream().println(x);
@@ -528,7 +532,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintlnString() throws Exception {
void outputStreamPrintlnString() throws Exception {
String x = "1";
this.response.getOutputStream().println(x);
@@ -540,7 +544,7 @@ public class OnCommittedResponseWrapperTests {
// has been greater than zero and has been written to the response.
@Test
public void contentLengthPrintWriterWriteIntCommits() throws Exception {
void contentLengthPrintWriterWriteIntCommits() throws Exception {
int expected = 1;
this.response.setContentLength(String.valueOf(expected).length());
@@ -550,7 +554,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterWriteIntMultiDigitCommits() throws Exception {
void contentLengthPrintWriterWriteIntMultiDigitCommits() throws Exception {
int expected = 10000;
this.response.setContentLength(String.valueOf(expected).length());
@@ -560,8 +564,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPlus1PrintWriterWriteIntMultiDigitCommits()
throws Exception {
void contentLengthPlus1PrintWriterWriteIntMultiDigitCommits() throws Exception {
int expected = 10000;
this.response.setContentLength(String.valueOf(expected).length() + 1);
@@ -575,7 +578,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterWriteCharIntIntCommits() throws Exception {
void contentLengthPrintWriterWriteCharIntIntCommits() throws Exception {
char[] buff = new char[0];
int off = 2;
int len = 3;
@@ -587,7 +590,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterWriteCharCommits() throws Exception {
void contentLengthPrintWriterWriteCharCommits() throws Exception {
char[] buff = new char[4];
this.response.setContentLength(buff.length);
@@ -597,7 +600,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterWriteStringIntIntCommits() throws Exception {
void contentLengthPrintWriterWriteStringIntIntCommits() throws Exception {
String s = "";
int off = 2;
int len = 3;
@@ -609,7 +612,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterWriteStringCommits() throws IOException {
void contentLengthPrintWriterWriteStringCommits() throws IOException {
String body = "something";
this.response.setContentLength(body.length());
@@ -619,7 +622,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterWriteStringContentLengthCommits() throws IOException {
void printWriterWriteStringContentLengthCommits() throws IOException {
String body = "something";
this.response.getWriter().write(body);
@@ -629,7 +632,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterWriteStringDoesNotCommit() throws IOException {
void printWriterWriteStringDoesNotCommit() throws IOException {
String body = "something";
this.response.getWriter().write(body);
@@ -638,7 +641,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintBooleanCommits() throws Exception {
void contentLengthPrintWriterPrintBooleanCommits() throws Exception {
boolean b = true;
this.response.setContentLength(1);
@@ -648,7 +651,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintCharCommits() throws Exception {
void contentLengthPrintWriterPrintCharCommits() throws Exception {
char c = 1;
this.response.setContentLength(1);
@@ -658,7 +661,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintIntCommits() throws Exception {
void contentLengthPrintWriterPrintIntCommits() throws Exception {
int i = 1234;
this.response.setContentLength(String.valueOf(i).length());
@@ -668,7 +671,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintLongCommits() throws Exception {
void contentLengthPrintWriterPrintLongCommits() throws Exception {
long l = 12345;
this.response.setContentLength(String.valueOf(l).length());
@@ -678,7 +681,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintFloatCommits() throws Exception {
void contentLengthPrintWriterPrintFloatCommits() throws Exception {
float f = 12345;
this.response.setContentLength(String.valueOf(f).length());
@@ -688,7 +691,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintDoubleCommits() throws Exception {
void contentLengthPrintWriterPrintDoubleCommits() throws Exception {
double x = 1.2345;
this.response.setContentLength(String.valueOf(x).length());
@@ -698,7 +701,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintCharArrayCommits() throws Exception {
void contentLengthPrintWriterPrintCharArrayCommits() throws Exception {
char[] x = new char[10];
this.response.setContentLength(x.length);
@@ -708,7 +711,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintStringCommits() throws Exception {
void contentLengthPrintWriterPrintStringCommits() throws Exception {
String x = "12345";
this.response.setContentLength(x.length());
@@ -718,7 +721,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintObjectCommits() throws Exception {
void contentLengthPrintWriterPrintObjectCommits() throws Exception {
Object x = "12345";
this.response.setContentLength(String.valueOf(x).length());
@@ -728,7 +731,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnCommits() throws Exception {
void contentLengthPrintWriterPrintlnCommits() throws Exception {
this.response.setContentLength(NL.length());
this.response.getWriter().println();
@@ -737,7 +740,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnBooleanCommits() throws Exception {
void contentLengthPrintWriterPrintlnBooleanCommits() throws Exception {
boolean b = true;
this.response.setContentLength(1);
@@ -747,7 +750,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnCharCommits() throws Exception {
void contentLengthPrintWriterPrintlnCharCommits() throws Exception {
char c = 1;
this.response.setContentLength(1);
@@ -757,7 +760,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnIntCommits() throws Exception {
void contentLengthPrintWriterPrintlnIntCommits() throws Exception {
int i = 12345;
this.response.setContentLength(String.valueOf(i).length());
@@ -767,7 +770,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnLongCommits() throws Exception {
void contentLengthPrintWriterPrintlnLongCommits() throws Exception {
long l = 12345678;
this.response.setContentLength(String.valueOf(l).length());
@@ -777,7 +780,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnFloatCommits() throws Exception {
void contentLengthPrintWriterPrintlnFloatCommits() throws Exception {
float f = 1234;
this.response.setContentLength(String.valueOf(f).length());
@@ -787,7 +790,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnDoubleCommits() throws Exception {
void contentLengthPrintWriterPrintlnDoubleCommits() throws Exception {
double x = 1;
this.response.setContentLength(String.valueOf(x).length());
@@ -797,7 +800,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnCharArrayCommits() throws Exception {
void contentLengthPrintWriterPrintlnCharArrayCommits() throws Exception {
char[] x = new char[20];
this.response.setContentLength(x.length);
@@ -807,9 +810,9 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnStringCommits() throws Exception {
void contentLengthPrintWriterPrintlnStringCommits() throws Exception {
String x = "1";
this.response.setContentLength(String.valueOf(x).length());
this.response.setContentLength(x.length());
this.response.getWriter().println(x);
@@ -817,7 +820,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnObjectCommits() throws Exception {
void contentLengthPrintWriterPrintlnObjectCommits() throws Exception {
Object x = "1";
this.response.setContentLength(String.valueOf(x).length());
@@ -827,9 +830,9 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterAppendCharSequenceCommits() throws Exception {
void contentLengthPrintWriterAppendCharSequenceCommits() throws Exception {
String x = "a";
this.response.setContentLength(String.valueOf(x).length());
this.response.setContentLength(x.length());
this.response.getWriter().append(x);
@@ -837,8 +840,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterAppendCharSequenceIntIntCommits()
throws Exception {
void contentLengthPrintWriterAppendCharSequenceIntIntCommits() throws Exception {
String x = "abcdef";
int start = 1;
int end = 3;
@@ -850,7 +852,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterAppendCharCommits() throws Exception {
void contentLengthPrintWriterAppendCharCommits() throws Exception {
char x = 1;
this.response.setContentLength(1);
@@ -860,7 +862,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamWriteIntCommits() throws Exception {
void contentLengthOutputStreamWriteIntCommits() throws Exception {
int expected = 1;
this.response.setContentLength(String.valueOf(expected).length());
@@ -870,7 +872,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamWriteIntMultiDigitCommits() throws Exception {
void contentLengthOutputStreamWriteIntMultiDigitCommits() throws Exception {
int expected = 10000;
this.response.setContentLength(String.valueOf(expected).length());
@@ -880,8 +882,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPlus1OutputStreamWriteIntMultiDigitCommits()
throws Exception {
void contentLengthPlus1OutputStreamWriteIntMultiDigitCommits() throws Exception {
int expected = 10000;
this.response.setContentLength(String.valueOf(expected).length() + 1);
@@ -896,24 +897,23 @@ public class OnCommittedResponseWrapperTests {
// gh-171
@Test
public void contentLengthPlus1OutputStreamWriteByteArrayMultiDigitCommits()
throws Exception {
void contentLengthPlus1OutputStreamWriteByteArrayMultiDigitCommits() throws Exception {
String expected = "{\n" + " \"parameterName\" : \"_csrf\",\n"
+ " \"token\" : \"06300b65-c4aa-4c8f-8cda-39ee17f545a0\",\n"
+ " \"headerName\" : \"X-CSRF-TOKEN\"\n" + "}";
+ " \"token\" : \"06300b65-c4aa-4c8f-8cda-39ee17f545a0\",\n" + " \"headerName\" : \"X-CSRF-TOKEN\"\n"
+ "}";
this.response.setContentLength(expected.length() + 1);
this.response.getOutputStream().write(expected.getBytes());
assertThat(this.committed).isFalse();
this.response.getOutputStream().write("1".getBytes("UTF-8"));
this.response.getOutputStream().write("1".getBytes(StandardCharsets.UTF_8));
assertThat(this.committed).isTrue();
}
@Test
public void contentLengthOutputStreamPrintBooleanCommits() throws Exception {
void contentLengthOutputStreamPrintBooleanCommits() throws Exception {
boolean b = true;
this.response.setContentLength(1);
@@ -923,7 +923,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintCharCommits() throws Exception {
void contentLengthOutputStreamPrintCharCommits() throws Exception {
char c = 1;
this.response.setContentLength(1);
@@ -933,7 +933,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintIntCommits() throws Exception {
void contentLengthOutputStreamPrintIntCommits() throws Exception {
int i = 1234;
this.response.setContentLength(String.valueOf(i).length());
@@ -943,7 +943,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintLongCommits() throws Exception {
void contentLengthOutputStreamPrintLongCommits() throws Exception {
long l = 12345;
this.response.setContentLength(String.valueOf(l).length());
@@ -953,7 +953,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintFloatCommits() throws Exception {
void contentLengthOutputStreamPrintFloatCommits() throws Exception {
float f = 12345;
this.response.setContentLength(String.valueOf(f).length());
@@ -963,7 +963,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintDoubleCommits() throws Exception {
void contentLengthOutputStreamPrintDoubleCommits() throws Exception {
double x = 1.2345;
this.response.setContentLength(String.valueOf(x).length());
@@ -973,7 +973,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintStringCommits() throws Exception {
void contentLengthOutputStreamPrintStringCommits() throws Exception {
String x = "12345";
this.response.setContentLength(x.length());
@@ -983,7 +983,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnCommits() throws Exception {
void contentLengthOutputStreamPrintlnCommits() throws Exception {
this.response.setContentLength(NL.length());
this.response.getOutputStream().println();
@@ -992,7 +992,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnBooleanCommits() throws Exception {
void contentLengthOutputStreamPrintlnBooleanCommits() throws Exception {
boolean b = true;
this.response.setContentLength(1);
@@ -1002,7 +1002,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnCharCommits() throws Exception {
void contentLengthOutputStreamPrintlnCharCommits() throws Exception {
char c = 1;
this.response.setContentLength(1);
@@ -1012,7 +1012,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnIntCommits() throws Exception {
void contentLengthOutputStreamPrintlnIntCommits() throws Exception {
int i = 12345;
this.response.setContentLength(String.valueOf(i).length());
@@ -1022,7 +1022,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnLongCommits() throws Exception {
void contentLengthOutputStreamPrintlnLongCommits() throws Exception {
long l = 12345678;
this.response.setContentLength(String.valueOf(l).length());
@@ -1032,7 +1032,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnFloatCommits() throws Exception {
void contentLengthOutputStreamPrintlnFloatCommits() throws Exception {
float f = 1234;
this.response.setContentLength(String.valueOf(f).length());
@@ -1042,7 +1042,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnDoubleCommits() throws Exception {
void contentLengthOutputStreamPrintlnDoubleCommits() throws Exception {
double x = 1;
this.response.setContentLength(String.valueOf(x).length());
@@ -1052,9 +1052,9 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnStringCommits() throws Exception {
void contentLengthOutputStreamPrintlnStringCommits() throws Exception {
String x = "1";
this.response.setContentLength(String.valueOf(x).length());
this.response.setContentLength(x.length());
this.response.getOutputStream().println(x);
@@ -1062,7 +1062,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthDoesNotCommit() throws IOException {
void contentLengthDoesNotCommit() {
String body = "something";
this.response.setContentLength(body.length());
@@ -1071,7 +1071,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamWriteStringCommits() throws IOException {
void contentLengthOutputStreamWriteStringCommits() throws IOException {
String body = "something";
this.response.setContentLength(body.length());
@@ -1081,10 +1081,9 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void addHeaderContentLengthPrintWriterWriteStringCommits() throws Exception {
void addHeaderContentLengthPrintWriterWriteStringCommits() throws Exception {
int expected = 1234;
this.response.addHeader("Content-Length",
String.valueOf(String.valueOf(expected).length()));
this.response.addHeader("Content-Length", String.valueOf(String.valueOf(expected).length()));
this.response.getWriter().write(expected);
@@ -1092,7 +1091,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void bufferSizePrintWriterWriteCommits() throws Exception {
void bufferSizePrintWriterWriteCommits() throws Exception {
String expected = "1234567890";
given(this.response.getBufferSize()).willReturn(expected.length());
@@ -1101,8 +1100,19 @@ public class OnCommittedResponseWrapperTests {
assertThat(this.committed).isTrue();
}
// gh-7261
@Test
public void bufferSizeCommitsOnce() throws Exception {
void contentLengthLongOutputStreamWriteStringCommits() throws IOException {
String body = "something";
this.response.setContentLengthLong(body.length());
this.response.getOutputStream().print(body);
assertThat(this.committed).isTrue();
}
@Test
void bufferSizeCommitsOnce() throws Exception {
String expected = "1234567890";
given(this.response.getBufferSize()).willReturn(expected.length());
@@ -1116,4 +1126,5 @@ public class OnCommittedResponseWrapperTests {
assertThat(this.committed).isFalse();
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2014-2020 the original author or authors.
*
* 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
*
* https://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 org.springframework.session.web.http;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.session.SessionRepository;
import org.springframework.session.web.http.OncePerRequestFilterAopTests.Config;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThatCode;
@SpringJUnitConfig(classes = Config.class)
class OncePerRequestFilterAopTests {
@Test
void doFilterOnce(@Autowired final OncePerRequestFilter filter) {
assertThatCode(() -> filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(),
new MockFilterChain())).as("`doFilter` does not throw NPE with the bean is being proxied by Spring AOP")
.doesNotThrowAnyException();
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Aspect
public static class Config {
@Bean
public SessionRepository sessionRepository() {
return Mockito.mock(SessionRepository.class);
}
@Bean
public SessionRepositoryFilter filter() {
return new SessionRepositoryFilter(sessionRepository());
}
@AfterReturning("execution(* SessionRepositoryFilter.doFilterInternal(..))")
public void doInternalFilterPointcut() {
// no op
}
}
}

View File

@@ -20,6 +20,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.DispatcherType;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
@@ -32,21 +33,27 @@ import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.util.WebUtils;
import static org.assertj.core.api.Assertions.assertThat;
public class OncePerRequestFilterTests {
class OncePerRequestFilterTests {
private MockHttpServletRequest request;
private MockHttpServletResponse response;
private MockFilterChain chain;
private OncePerRequestFilter filter;
private HttpServlet servlet;
private List<OncePerRequestFilter> invocations;
@BeforeEach
@SuppressWarnings("serial")
public void setup() {
void setup() {
this.servlet = new HttpServlet() {
};
this.request = new MockHttpServletRequest();
@@ -55,9 +62,8 @@ public class OncePerRequestFilterTests {
this.invocations = new ArrayList<>();
this.filter = new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
OncePerRequestFilterTests.this.invocations.add(this);
filterChain.doFilter(request, response);
}
@@ -65,34 +71,63 @@ public class OncePerRequestFilterTests {
}
@Test
public void doFilterOnce() throws ServletException, IOException {
void doFilterOnce() throws ServletException, IOException {
this.filter.doFilter(this.request, this.response, this.chain);
assertThat(this.invocations).containsOnly(this.filter);
}
@Test
public void doFilterMultiOnlyIvokesOnce() throws ServletException, IOException {
this.filter.doFilter(this.request, this.response,
new MockFilterChain(this.servlet, this.filter));
void doFilterMultiOnlyIvokesOnce() throws ServletException, IOException {
this.filter.doFilter(this.request, this.response, new MockFilterChain(this.servlet, this.filter));
assertThat(this.invocations).containsOnly(this.filter);
}
@Test
public void doFilterOtherSubclassInvoked() throws ServletException, IOException {
void doFilterOtherSubclassInvoked() throws ServletException, IOException {
OncePerRequestFilter filter2 = new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
OncePerRequestFilterTests.this.invocations.add(this);
filterChain.doFilter(request, response);
}
};
this.filter.doFilter(this.request, this.response,
new MockFilterChain(this.servlet, filter2));
this.filter.doFilter(this.request, this.response, new MockFilterChain(this.servlet, filter2));
assertThat(this.invocations).containsOnly(this.filter, filter2);
}
@Test // gh-1470
void filterNestedErrorDispatch() throws ServletException, IOException {
TestOncePerRequestFilter filter = new TestOncePerRequestFilter();
this.request.setAttribute(filter.getAlreadyFilteredAttributeName(), Boolean.TRUE);
this.request.setDispatcherType(DispatcherType.ERROR);
this.request.setAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE, "/error");
filter.doFilter(this.request, new MockHttpServletResponse(), this.chain);
assertThat(filter.didFilter).isFalse();
assertThat(filter.didFilterNestedErrorDispatch).isTrue();
}
private static class TestOncePerRequestFilter extends OncePerRequestFilter {
private boolean didFilter;
private boolean didFilterNestedErrorDispatch;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) {
this.didFilter = true;
}
@Override
protected void doFilterNestedErrorDispatch(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) {
this.didFilterNestedErrorDispatch = true;
}
}
}

View File

@@ -39,7 +39,7 @@ import org.springframework.session.events.SessionDestroyedEvent;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
/**
* Tests for {@link SessionEventHttpSessionListenerAdapter}.
@@ -47,7 +47,7 @@ import static org.mockito.Mockito.verifyZeroInteractions;
* @author Rob Winch
* @since 1.1
*/
public class SessionEventHttpSessionListenerAdapterTests {
class SessionEventHttpSessionListenerAdapterTests {
@Mock
private HttpSessionListener listener1;
@@ -68,10 +68,9 @@ public class SessionEventHttpSessionListenerAdapterTests {
private SessionEventHttpSessionListenerAdapter listener;
@BeforeEach
public void setup() {
void setup() {
MockitoAnnotations.initMocks(this);
this.listener = new SessionEventHttpSessionListenerAdapter(
Arrays.asList(this.listener1, this.listener2));
this.listener = new SessionEventHttpSessionListenerAdapter(Arrays.asList(this.listener1, this.listener2));
this.listener.setServletContext(new MockServletContext());
Session session = new MapSession();
@@ -83,7 +82,7 @@ public class SessionEventHttpSessionListenerAdapterTests {
// make configuration easier (i.e. autowire all HttpSessionListeners and might get
// none)
@Test
public void constructorEmptyWorks() {
void constructorEmptyWorks() {
new SessionEventHttpSessionListenerAdapter(Collections.emptyList());
}
@@ -92,36 +91,33 @@ public class SessionEventHttpSessionListenerAdapterTests {
* listeners
*/
@Test
public void onApplicationEventEmptyListenersDoesNotUseEvent() {
this.listener = new SessionEventHttpSessionListenerAdapter(
Collections.emptyList());
void onApplicationEventEmptyListenersDoesNotUseEvent() {
this.listener = new SessionEventHttpSessionListenerAdapter(Collections.emptyList());
this.destroyed = mock(SessionDestroyedEvent.class);
this.listener.onApplicationEvent(this.destroyed);
verifyZeroInteractions(this.destroyed, this.listener1, this.listener2);
verifyNoMoreInteractions(this.destroyed, this.listener1, this.listener2);
}
@Test
public void onApplicationEventDestroyed() {
void onApplicationEventDestroyed() {
this.listener.onApplicationEvent(this.destroyed);
verify(this.listener1).sessionDestroyed(this.sessionEvent.capture());
verify(this.listener2).sessionDestroyed(this.sessionEvent.capture());
assertThat(this.sessionEvent.getValue().getSession().getId())
.isEqualTo(this.destroyed.getSessionId());
assertThat(this.sessionEvent.getValue().getSession().getId()).isEqualTo(this.destroyed.getSessionId());
}
@Test
public void onApplicationEventCreated() {
void onApplicationEventCreated() {
this.listener.onApplicationEvent(this.created);
verify(this.listener1).sessionCreated(this.sessionEvent.capture());
verify(this.listener2).sessionCreated(this.sessionEvent.capture());
assertThat(this.sessionEvent.getValue().getSession().getId())
.isEqualTo(this.created.getSessionId());
assertThat(this.sessionEvent.getValue().getSession().getId()).isEqualTo(this.created.getSessionId());
}
}

View File

@@ -43,7 +43,7 @@ import static org.mockito.Mockito.verify;
* @author Rob Winch
* @author Vedran Pavic
*/
public class SpringSessionWebSessionStoreTests<S extends Session> {
class SpringSessionWebSessionStoreTests<S extends Session> {
@Mock
private ReactiveSessionRepository<S> sessionRepository;
@@ -57,68 +57,62 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
private SpringSessionWebSessionStore<S> webSessionStore;
@BeforeEach
public void setup() {
void setup() {
MockitoAnnotations.initMocks(this);
this.webSessionStore = new SpringSessionWebSessionStore<>(this.sessionRepository);
given(this.sessionRepository.findById(any()))
.willReturn(Mono.just(this.findByIdSession));
given(this.sessionRepository.createSession())
.willReturn(Mono.just(this.createSession));
given(this.sessionRepository.findById(any())).willReturn(Mono.just(this.findByIdSession));
given(this.sessionRepository.createSession()).willReturn(Mono.just(this.createSession));
}
@Test
public void constructorWhenNullRepositoryThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new SpringSessionWebSessionStore<S>(null))
void constructorWhenNullRepositoryThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException().isThrownBy(() -> new SpringSessionWebSessionStore<S>(null))
.withMessage("reactiveSessionRepository cannot be null");
}
@Test
public void createSessionWhenNoAttributesThenNotStarted() {
void createSessionWhenNoAttributesThenNotStarted() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
assertThat(createdWebSession.isStarted()).isFalse();
}
@Test
public void createSessionWhenAddAttributeThenStarted() {
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton("a"));
void createSessionWhenAddAttributeThenStarted() {
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton("a"));
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
assertThat(createdWebSession.isStarted()).isTrue();
}
@Test
public void createSessionWhenGetAttributesAndSizeThenDelegatesToCreateSession() {
void createSessionWhenGetAttributesAndSizeThenDelegatesToCreateSession() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
assertThat(attributes.size()).isEqualTo(0);
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton("a"));
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton("a"));
assertThat(attributes.size()).isEqualTo(1);
}
@Test
public void createSessionWhenGetAttributesAndIsEmptyThenDelegatesToCreateSession() {
void createSessionWhenGetAttributesAndIsEmptyThenDelegatesToCreateSession() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
assertThat(attributes.isEmpty()).isTrue();
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton("a"));
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton("a"));
assertThat(attributes.isEmpty()).isFalse();
}
@Test
public void createSessionWhenGetAttributesAndContainsKeyAndNotStringThenFalse() {
void createSessionWhenGetAttributesAndContainsKeyAndNotStringThenFalse() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -127,7 +121,7 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndContainsKeyAndNotFoundThenFalse() {
void createSessionWhenGetAttributesAndContainsKeyAndNotFoundThenFalse() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -136,9 +130,8 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndContainsKeyAndFoundThenTrue() {
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton("a"));
void createSessionWhenGetAttributesAndContainsKeyAndFoundThenTrue() {
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton("a"));
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -147,7 +140,7 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndPutThenDelegatesToCreateSession() {
void createSessionWhenGetAttributesAndPutThenDelegatesToCreateSession() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -157,7 +150,7 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndPutNullThenDelegatesToCreateSession() {
void createSessionWhenGetAttributesAndPutNullThenDelegatesToCreateSession() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -167,7 +160,7 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndRemoveThenDelegatesToCreateSession() {
void createSessionWhenGetAttributesAndRemoveThenDelegatesToCreateSession() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -177,7 +170,7 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndPutAllThenDelegatesToCreateSession() {
void createSessionWhenGetAttributesAndPutAllThenDelegatesToCreateSession() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -187,9 +180,8 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndClearThenDelegatesToCreateSession() {
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton("a"));
void createSessionWhenGetAttributesAndClearThenDelegatesToCreateSession() {
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton("a"));
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -199,9 +191,8 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndKeySetThenDelegatesToCreateSession() {
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton("a"));
void createSessionWhenGetAttributesAndKeySetThenDelegatesToCreateSession() {
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton("a"));
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -210,9 +201,8 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndValuesThenDelegatesToCreateSession() {
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton("a"));
void createSessionWhenGetAttributesAndValuesThenDelegatesToCreateSession() {
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton("a"));
given(this.createSession.getAttribute("a")).willReturn("b");
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
@@ -222,10 +212,9 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndEntrySetThenDelegatesToCreateSession() {
void createSessionWhenGetAttributesAndEntrySetThenDelegatesToCreateSession() {
String attrName = "attrName";
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton(attrName));
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton(attrName));
String attrValue = "attrValue";
given(this.createSession.getAttribute(attrName)).willReturn(attrValue);
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
@@ -233,12 +222,11 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
Map<String, Object> attributes = createdWebSession.getAttributes();
Set<Map.Entry<String, Object>> entries = attributes.entrySet();
assertThat(entries)
.containsExactly(new AbstractMap.SimpleEntry<>(attrName, attrValue));
assertThat(entries).containsExactly(new AbstractMap.SimpleEntry<>(attrName, attrValue));
}
@Test
public void retrieveSessionThenStarted() {
void retrieveSessionThenStarted() {
String id = "id";
WebSession retrievedWebSession = this.webSessionStore.retrieveSession(id).block();
@@ -247,7 +235,7 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void removeSessionWhenInvokedThenSessionSaved() {
void removeSessionWhenInvokedThenSessionSaved() {
String sessionId = "session-id";
given(this.sessionRepository.deleteById(sessionId)).willReturn(Mono.empty());
@@ -257,21 +245,20 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void setClockWhenNullThenException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.webSessionStore.setClock(null))
void setClockWhenNullThenException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.webSessionStore.setClock(null))
.withMessage("clock cannot be null");
}
@Test // gh-1114
public void createSessionThenSessionIsNotExpired() {
void createSessionThenSessionIsNotExpired() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
assertThat(createdWebSession.isExpired()).isFalse();
}
@Test // gh-1114
public void invalidateSessionThenSessionIsExpired() {
void invalidateSessionThenSessionIsExpired() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
given(createdWebSession.invalidate()).willReturn(Mono.empty());

View File

@@ -35,33 +35,36 @@ import static org.mockito.BDDMockito.willThrow;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.verify;
public class WebSocketConnectHandlerDecoratorFactoryTests {
class WebSocketConnectHandlerDecoratorFactoryTests {
@Mock
ApplicationEventPublisher eventPublisher;
@Mock
WebSocketHandler delegate;
@Mock
WebSocketSession session;
@Captor
ArgumentCaptor<SessionConnectEvent> event;
WebSocketConnectHandlerDecoratorFactory factory;
private WebSocketConnectHandlerDecoratorFactory factory;
@BeforeEach
public void setup() {
void setup() {
MockitoAnnotations.initMocks(this);
this.factory = new WebSocketConnectHandlerDecoratorFactory(this.eventPublisher);
}
@Test
public void constructorNullEventPublisher() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new WebSocketConnectHandlerDecoratorFactory(null))
void constructorNullEventPublisher() {
assertThatIllegalArgumentException().isThrownBy(() -> new WebSocketConnectHandlerDecoratorFactory(null))
.withMessage("eventPublisher cannot be null");
}
@Test
public void decorateAfterConnectionEstablished() throws Exception {
void decorateAfterConnectionEstablished() throws Exception {
WebSocketHandler decorated = this.factory.decorate(this.delegate);
decorated.afterConnectionEstablished(this.session);
@@ -71,13 +74,14 @@ public class WebSocketConnectHandlerDecoratorFactoryTests {
}
@Test
public void decorateAfterConnectionEstablishedEventError() throws Exception {
void decorateAfterConnectionEstablishedEventError() throws Exception {
WebSocketHandler decorated = this.factory.decorate(this.delegate);
willThrow(new IllegalStateException("Test throw on publishEvent"))
.given(this.eventPublisher).publishEvent(any(ApplicationEvent.class));
willThrow(new IllegalStateException("Test throw on publishEvent")).given(this.eventPublisher)
.publishEvent(any(ApplicationEvent.class));
decorated.afterConnectionEstablished(this.session);
verify(this.eventPublisher).publishEvent(any(SessionConnectEvent.class));
}
}

View File

@@ -44,7 +44,7 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
public class WebSocketRegistryListenerTests {
class WebSocketRegistryListenerTests {
@Mock
private WebSocketSession wsSession;
@@ -73,7 +73,7 @@ public class WebSocketRegistryListenerTests {
private WebSocketRegistryListener listener;
@BeforeEach
public void setup() {
void setup() {
MockitoAnnotations.initMocks(this);
String sessionId = "session-id";
MapSession session = new MapSession(sessionId);
@@ -96,14 +96,14 @@ public class WebSocketRegistryListenerTests {
this.listener = new WebSocketRegistryListener();
this.connect = new SessionConnectEvent(this.listener, this.wsSession);
this.connect2 = new SessionConnectEvent(this.listener, this.wsSession2);
this.disconnect = new SessionDisconnectEvent(this.listener, this.message,
this.wsSession.getId(), CloseStatus.NORMAL);
this.disconnect = new SessionDisconnectEvent(this.listener, this.message, this.wsSession.getId(),
CloseStatus.NORMAL);
this.deleted = new SessionDeletedEvent(this.listener, session);
this.expired = new SessionExpiredEvent(this.listener, session);
}
@Test
public void onApplicationEventConnectSessionDeleted() throws Exception {
void onApplicationEventConnectSessionDeleted() throws Exception {
this.listener.onApplicationEvent(this.connect);
this.listener.onApplicationEvent(this.deleted);
@@ -112,7 +112,7 @@ public class WebSocketRegistryListenerTests {
}
@Test
public void onApplicationEventConnectSessionExpired() throws Exception {
void onApplicationEventConnectSessionExpired() throws Exception {
this.listener.onApplicationEvent(this.connect);
this.listener.onApplicationEvent(this.expired);
@@ -121,7 +121,7 @@ public class WebSocketRegistryListenerTests {
}
@Test
public void onApplicationEventConnectSessionDeletedNullPrincipal() throws Exception {
void onApplicationEventConnectSessionDeletedNullPrincipal() throws Exception {
given(this.wsSession.getPrincipal()).willReturn(null);
this.listener.onApplicationEvent(this.connect);
@@ -131,7 +131,7 @@ public class WebSocketRegistryListenerTests {
}
@Test
public void onApplicationEventConnectDisconnect() throws Exception {
void onApplicationEventConnectDisconnect() throws Exception {
this.listener.onApplicationEvent(this.connect);
this.listener.onApplicationEvent(this.disconnect);
@@ -143,7 +143,7 @@ public class WebSocketRegistryListenerTests {
// gh-76
@Test
@SuppressWarnings("unchecked")
public void onApplicationEventConnectDisconnectCleanup() {
void onApplicationEventConnectDisconnectCleanup() {
this.listener.onApplicationEvent(this.connect);
this.listener.onApplicationEvent(this.disconnect);
@@ -154,7 +154,7 @@ public class WebSocketRegistryListenerTests {
}
@Test
public void onApplicationEventConnectDisconnectNullSession() throws Exception {
void onApplicationEventConnectDisconnectNullSession() {
this.listener.onApplicationEvent(this.connect);
this.attributes.clear();
@@ -164,7 +164,7 @@ public class WebSocketRegistryListenerTests {
}
@Test
public void onApplicationEventConnectConnectDisonnect() throws Exception {
void onApplicationEventConnectConnectDisonnect() throws Exception {
this.listener.onApplicationEvent(this.connect);
this.listener.onApplicationEvent(this.connect2);
this.listener.onApplicationEvent(this.disconnect);

View File

@@ -49,27 +49,29 @@ import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
class SessionRepositoryMessageInterceptorTests {
public class SessionRepositoryMessageInterceptorTests {
@Mock
SessionRepository<Session> sessionRepository;
@Mock
MessageChannel channel;
@Mock
Session session;
Message<?> createMessage;
private Message<?> createMessage;
SimpMessageHeaderAccessor headers;
private SimpMessageHeaderAccessor headers;
SessionRepositoryMessageInterceptor<Session> interceptor;
private SessionRepositoryMessageInterceptor<Session> interceptor;
@BeforeEach
public void setup() {
void setup() {
MockitoAnnotations.initMocks(this);
this.interceptor = new SessionRepositoryMessageInterceptor<>(
this.sessionRepository);
this.interceptor = new SessionRepositoryMessageInterceptor<>(this.sessionRepository);
this.headers = SimpMessageHeaderAccessor.create();
this.headers.setSessionId("session");
this.headers.setSessionAttributes(new HashMap<>());
@@ -80,123 +82,112 @@ public class SessionRepositoryMessageInterceptorTests {
}
@Test
public void preSendconstructorNullRepository() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new SessionRepositoryMessageInterceptor<>(null))
void preSendconstructorNullRepository() {
assertThatIllegalArgumentException().isThrownBy(() -> new SessionRepositoryMessageInterceptor<>(null))
.withMessage("sessionRepository cannot be null");
}
@Test
public void preSendNullMessage() {
void preSendNullMessage() {
assertThat(this.interceptor.preSend(null, this.channel)).isNull();
}
@Test
public void preSendConnectAckDoesNotInvokeSessionRepository() {
void preSendConnectAckDoesNotInvokeSessionRepository() {
setMessageType(SimpMessageType.CONNECT_ACK);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyZeroInteractions(this.sessionRepository);
verifyNoMoreInteractions(this.sessionRepository);
}
@Test
public void preSendHeartbeatDoesNotInvokeSessionRepository() {
void preSendHeartbeatDoesNotInvokeSessionRepository() {
setMessageType(SimpMessageType.HEARTBEAT);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyZeroInteractions(this.sessionRepository);
verifyNoMoreInteractions(this.sessionRepository);
}
@Test
public void preSendDisconnectDoesNotInvokeSessionRepository() {
void preSendDisconnectDoesNotInvokeSessionRepository() {
setMessageType(SimpMessageType.DISCONNECT);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyZeroInteractions(this.sessionRepository);
verifyNoMoreInteractions(this.sessionRepository);
}
@Test
public void preSendOtherDoesNotInvokeSessionRepository() {
void preSendOtherDoesNotInvokeSessionRepository() {
setMessageType(SimpMessageType.OTHER);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyZeroInteractions(this.sessionRepository);
verifyNoMoreInteractions(this.sessionRepository);
}
@Test
public void setMatchingMessageTypesNull() {
void setMatchingMessageTypesNull() {
assertThatIllegalArgumentException().isThrownBy(() -> this.interceptor.setMatchingMessageTypes(null))
.withMessage("matchingMessageTypes cannot be null or empty");
}
@Test
void setMatchingMessageTypesEmpty() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.interceptor.setMatchingMessageTypes(null))
.isThrownBy(() -> this.interceptor.setMatchingMessageTypes(Collections.emptySet()))
.withMessage("matchingMessageTypes cannot be null or empty");
}
@Test
public void setMatchingMessageTypesEmpty() {
assertThatIllegalArgumentException().isThrownBy(
() -> this.interceptor.setMatchingMessageTypes(Collections.emptySet()))
.withMessage("matchingMessageTypes cannot be null or empty");
}
@Test
public void preSendSetMatchingMessageTypes() {
void preSendSetMatchingMessageTypes() {
this.interceptor.setMatchingMessageTypes(EnumSet.of(SimpMessageType.DISCONNECT));
setMessageType(SimpMessageType.DISCONNECT);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verify(this.sessionRepository).findById(anyString());
verify(this.sessionRepository).save(this.session);
}
@Test
public void preSendConnectUpdatesLastUpdateTime() {
void preSendConnectUpdatesLastUpdateTime() {
setMessageType(SimpMessageType.CONNECT);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verify(this.session).setLastAccessedTime(argThat(isAlmostNow()));
verify(this.sessionRepository).save(this.session);
}
@Test
public void preSendMessageUpdatesLastUpdateTime() {
void preSendMessageUpdatesLastUpdateTime() {
setMessageType(SimpMessageType.MESSAGE);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verify(this.session).setLastAccessedTime(argThat(isAlmostNow()));
verify(this.sessionRepository).save(this.session);
}
@Test
public void preSendSubscribeUpdatesLastUpdateTime() {
void preSendSubscribeUpdatesLastUpdateTime() {
setMessageType(SimpMessageType.SUBSCRIBE);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verify(this.session).setLastAccessedTime(argThat(isAlmostNow()));
verify(this.sessionRepository).save(this.session);
}
@Test
public void preSendUnsubscribeUpdatesLastUpdateTime() {
void preSendUnsubscribeUpdatesLastUpdateTime() {
setMessageType(SimpMessageType.UNSUBSCRIBE);
this.session.setLastAccessedTime(Instant.EPOCH);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verify(this.session).setLastAccessedTime(argThat(isAlmostNow()));
verify(this.sessionRepository).save(this.session);
@@ -204,7 +195,7 @@ public class SessionRepositoryMessageInterceptorTests {
// This will updated when SPR-12288 is resolved
@Test
public void preSendExpiredSession() {
void preSendExpiredSession() {
setSessionId("expired");
this.interceptor.preSend(createMessage(), this.channel);
@@ -213,74 +204,67 @@ public class SessionRepositoryMessageInterceptorTests {
}
@Test
public void preSendNullSessionId() {
void preSendNullSessionId() {
setSessionId(null);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyZeroInteractions(this.sessionRepository);
verifyNoMoreInteractions(this.sessionRepository);
}
@Test
public void preSendNullSessionAttributes() {
void preSendNullSessionAttributes() {
this.headers.setSessionAttributes(null);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyZeroInteractions(this.sessionRepository);
verifyNoMoreInteractions(this.sessionRepository);
}
@Test
public void beforeHandshakeNotServletServerHttpRequest() throws Exception {
void beforeHandshakeNotServletServerHttpRequest() {
assertThat(this.interceptor.beforeHandshake(null, null, null, null)).isTrue();
verifyZeroInteractions(this.sessionRepository);
verifyNoMoreInteractions(this.sessionRepository);
}
@Test
public void beforeHandshakeNullSession() throws Exception {
ServletServerHttpRequest request = new ServletServerHttpRequest(
new MockHttpServletRequest());
void beforeHandshakeNullSession() {
ServletServerHttpRequest request = new ServletServerHttpRequest(new MockHttpServletRequest());
assertThat(this.interceptor.beforeHandshake(request, null, null, null)).isTrue();
verifyZeroInteractions(this.sessionRepository);
verifyNoMoreInteractions(this.sessionRepository);
}
@Test
public void beforeHandshakeSession() throws Exception {
void beforeHandshakeSession() {
MockHttpServletRequest httpRequest = new MockHttpServletRequest();
HttpSession httpSession = httpRequest.getSession();
ServletServerHttpRequest request = new ServletServerHttpRequest(httpRequest);
Map<String, Object> attributes = new HashMap<>();
assertThat(this.interceptor.beforeHandshake(request, null, null, attributes))
.isTrue();
assertThat(this.interceptor.beforeHandshake(request, null, null, attributes)).isTrue();
assertThat(attributes.size()).isEqualTo(1);
assertThat(SessionRepositoryMessageInterceptor.getSessionId(attributes))
.isEqualTo(httpSession.getId());
assertThat(SessionRepositoryMessageInterceptor.getSessionId(attributes)).isEqualTo(httpSession.getId());
}
/**
* At the moment there is no need for afterHandshake to do anything.
*/
@Test
public void afterHandshakeDoesNothing() {
void afterHandshakeDoesNothing() {
this.interceptor.afterHandshake(null, null, null, null);
verifyZeroInteractions(this.sessionRepository);
verifyNoMoreInteractions(this.sessionRepository);
}
private void setSessionId(String id) {
SessionRepositoryMessageInterceptor
.setSessionId(this.headers.getSessionAttributes(), id);
SessionRepositoryMessageInterceptor.setSessionId(this.headers.getSessionAttributes(), id);
}
private Message<?> createMessage() {
this.createMessage = MessageBuilder.createMessage("",
this.headers.getMessageHeaders());
this.createMessage = MessageBuilder.createMessage("", this.headers.getMessageHeaders());
return this.createMessage;
}
@@ -302,4 +286,5 @@ public class SessionRepositoryMessageInterceptorTests {
}
}
}

View File

@@ -5,7 +5,6 @@ description = "Spring Session Redis implementation"
dependencies {
compile project(':spring-session-core')
compile ("org.springframework.data:spring-data-redis") {
exclude group: "org.slf4j", module: 'slf4j-api'
exclude group: "org.slf4j", module: 'jcl-over-slf4j'
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,9 @@ import org.springframework.context.ApplicationListener;
import org.springframework.session.events.AbstractSessionEvent;
public class SessionEventRegistry implements ApplicationListener<AbstractSessionEvent> {
private Map<String, AbstractSessionEvent> events = new HashMap<>();
private ConcurrentMap<String, Object> locks = new ConcurrentHashMap<>();
@Override
@@ -48,14 +50,12 @@ public class SessionEventRegistry implements ApplicationListener<AbstractSession
}
@SuppressWarnings("unchecked")
public <E extends AbstractSessionEvent> E getEvent(String sessionId)
throws InterruptedException {
public <E extends AbstractSessionEvent> E getEvent(String sessionId) throws InterruptedException {
return (E) waitForEvent(sessionId);
}
@SuppressWarnings("unchecked")
private <E extends AbstractSessionEvent> E waitForEvent(String sessionId)
throws InterruptedException {
private <E extends AbstractSessionEvent> E waitForEvent(String sessionId) throws InterruptedException {
Object lock = getLock(sessionId);
synchronized (lock) {
if (!this.events.containsKey(sessionId)) {
@@ -68,4 +68,5 @@ public class SessionEventRegistry implements ApplicationListener<AbstractSession
private Object getLock(String sessionId) {
return this.locks.computeIfAbsent(sessionId, (k) -> new Object());
}
}

View File

@@ -23,20 +23,19 @@ import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
/**
* Base class for {@link RedisOperationsSessionRepository} integration tests.
* Base class for Redis integration tests.
*
* @author Vedran Pavic
*/
public abstract class AbstractRedisITests {
private static final String DOCKER_IMAGE = "redis:5.0.5";
private static final String DOCKER_IMAGE = "redis:5.0.10";
protected static class BaseConfig {
@Bean
public GenericContainer redisContainer() {
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
.withExposedPorts(6379);
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE).withExposedPorts(6379);
redisContainer.start();
return redisContainer;
}
@@ -44,8 +43,7 @@ public abstract class AbstractRedisITests {
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(
redisContainer().getContainerIpAddress(),
redisContainer().getFirstMappedPort());
redisContainer().getContainerIpAddress(), redisContainer().getFirstMappedPort());
return new LettuceConnectionFactory(configuration);
}

View File

@@ -25,6 +25,7 @@ import reactor.core.publisher.Mono;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.Session;
import org.springframework.session.data.redis.ReactiveRedisSessionRepository.RedisSession;
import org.springframework.session.data.redis.config.annotation.web.server.EnableRedisWebSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -34,22 +35,21 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
/**
* Integration tests for {@link ReactiveRedisOperationsSessionRepository}.
* Integration tests for {@link ReactiveRedisSessionRepository}.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
class ReactiveRedisSessionRepositoryITests extends AbstractRedisITests {
@Autowired
private ReactiveRedisOperationsSessionRepository repository;
private ReactiveRedisSessionRepository repository;
@Test
public void saves() throws InterruptedException {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
void saves() {
RedisSession toSave = this.repository.createSession().block();
String expectedAttributeName = "a";
String expectedAttributeValue = "b";
@@ -70,9 +70,8 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
}
@Test // gh-1399
public void saveMultipleTimes() {
ReactiveRedisOperationsSessionRepository.RedisSession session = this.repository
.createSession().block();
void saveMultipleTimes() {
RedisSession session = this.repository.createSession().block();
session.setAttribute("attribute1", "value1");
Mono<Void> save1 = this.repository.save(session);
session.setAttribute("attribute2", "value2");
@@ -81,9 +80,8 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
}
@Test
public void putAllOnSingleAttrDoesNotRemoveOld() {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
void putAllOnSingleAttrDoesNotRemoveOld() {
RedisSession toSave = this.repository.createSession().block();
toSave.setAttribute("a", "b");
this.repository.save(toSave).block();
@@ -103,17 +101,15 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
}
@Test
public void changeSessionIdWhenOnlyChangeId() throws Exception {
void changeSessionIdWhenOnlyChangeId() {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
RedisSession toSave = this.repository.createSession().block();
toSave.setAttribute(attrName, attrValue);
this.repository.save(toSave).block();
ReactiveRedisOperationsSessionRepository.RedisSession findById = this.repository
.findById(toSave.getId()).block();
RedisSession findById = this.repository.findById(toSave.getId()).block();
assertThat(findById.<String>getAttribute(attrName)).isEqualTo(attrValue);
@@ -124,17 +120,14 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
assertThat(this.repository.findById(originalFindById).block()).isNull();
ReactiveRedisOperationsSessionRepository.RedisSession findByChangeSessionId = this.repository
.findById(changeSessionId).block();
RedisSession findByChangeSessionId = this.repository.findById(changeSessionId).block();
assertThat(findByChangeSessionId.<String>getAttribute(attrName))
.isEqualTo(attrValue);
assertThat(findByChangeSessionId.<String>getAttribute(attrName)).isEqualTo(attrValue);
}
@Test
public void changeSessionIdWhenChangeTwice() throws Exception {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
void changeSessionIdWhenChangeTwice() {
RedisSession toSave = this.repository.createSession().block();
this.repository.save(toSave).block();
@@ -150,17 +143,15 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
}
@Test
public void changeSessionIdWhenSetAttributeOnChangedSession() throws Exception {
void changeSessionIdWhenSetAttributeOnChangedSession() {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
RedisSession toSave = this.repository.createSession().block();
this.repository.save(toSave).block();
ReactiveRedisOperationsSessionRepository.RedisSession findById = this.repository
.findById(toSave.getId()).block();
RedisSession findById = this.repository.findById(toSave.getId()).block();
findById.setAttribute(attrName, attrValue);
@@ -171,17 +162,14 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
assertThat(this.repository.findById(originalFindById).block()).isNull();
ReactiveRedisOperationsSessionRepository.RedisSession findByChangeSessionId = this.repository
.findById(changeSessionId).block();
RedisSession findByChangeSessionId = this.repository.findById(changeSessionId).block();
assertThat(findByChangeSessionId.<String>getAttribute(attrName))
.isEqualTo(attrValue);
assertThat(findByChangeSessionId.<String>getAttribute(attrName)).isEqualTo(attrValue);
}
@Test
public void changeSessionIdWhenHasNotSaved() throws Exception {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
void changeSessionIdWhenHasNotSaved() {
RedisSession toSave = this.repository.createSession().block();
String originalId = toSave.getId();
toSave.changeSessionId();
@@ -193,9 +181,8 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
// gh-954
@Test
public void changeSessionIdSaveTwice() {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
void changeSessionIdSaveTwice() {
RedisSession toSave = this.repository.createSession().block();
String originalId = toSave.getId();
toSave.changeSessionId();
@@ -208,23 +195,20 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
// gh-1111
@Test
public void changeSessionSaveOldSessionInstance() {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
void changeSessionSaveOldSessionInstance() {
RedisSession toSave = this.repository.createSession().block();
String sessionId = toSave.getId();
this.repository.save(toSave).block();
ReactiveRedisOperationsSessionRepository.RedisSession session = this.repository
.findById(sessionId).block();
RedisSession session = this.repository.findById(sessionId).block();
session.changeSessionId();
session.setLastAccessedTime(Instant.now());
this.repository.save(session).block();
toSave.setLastAccessedTime(Instant.now());
assertThatIllegalStateException()
.isThrownBy(() -> this.repository.save(toSave).block())
assertThatIllegalStateException().isThrownBy(() -> this.repository.save(toSave).block())
.withMessage("Session was invalidated");
assertThat(this.repository.findById(sessionId).block()).isNull();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.session.data.SessionEventRegistry;
import org.springframework.session.data.redis.RedisOperationsSessionRepository.RedisSession;
import org.springframework.session.data.redis.RedisIndexedSessionRepository.RedisSession;
import org.springframework.session.data.redis.config.annotation.SpringSessionRedisOperations;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.events.SessionCreatedEvent;
@@ -48,17 +48,23 @@ import org.springframework.test.context.web.WebAppConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link RedisIndexedSessionRepository}.
*
* @author Rob Winch
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests {
class RedisIndexedSessionRepositoryITests extends AbstractRedisITests {
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
private static final String INDEX_NAME = FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME;
@Autowired
private RedisOperationsSessionRepository repository;
private RedisIndexedSessionRepository repository;
@Autowired
private SessionEventRegistry registry;
@@ -71,34 +77,31 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
private SecurityContext changedContext;
@BeforeEach
public void setup() {
void setup() {
if (this.registry != null) {
this.registry.clear();
}
this.context = SecurityContextHolder.createEmptyContext();
this.context.setAuthentication(
new UsernamePasswordAuthenticationToken("username-" + UUID.randomUUID(),
"na", AuthorityUtils.createAuthorityList("ROLE_USER")));
this.context.setAuthentication(new UsernamePasswordAuthenticationToken("username-" + UUID.randomUUID(), "na",
AuthorityUtils.createAuthorityList("ROLE_USER")));
this.changedContext = SecurityContextHolder.createEmptyContext();
this.changedContext.setAuthentication(new UsernamePasswordAuthenticationToken(
"changedContext-" + UUID.randomUUID(), "na",
AuthorityUtils.createAuthorityList("ROLE_USER")));
"changedContext-" + UUID.randomUUID(), "na", AuthorityUtils.createAuthorityList("ROLE_USER")));
}
@Test
public void saves() throws InterruptedException {
void saves() throws InterruptedException {
String username = "saves-" + System.currentTimeMillis();
String usernameSessionKey = "RedisOperationsSessionRepositoryITests:index:"
+ INDEX_NAME + ":" + username;
String usernameSessionKey = "RedisIndexedSessionRepositoryITests:index:" + INDEX_NAME + ":" + username;
RedisSession toSave = this.repository.createSession();
String expectedAttributeName = "a";
String expectedAttributeValue = "b";
toSave.setAttribute(expectedAttributeName, expectedAttributeValue);
Authentication toSaveToken = new UsernamePasswordAuthenticationToken(username,
"password", AuthorityUtils.createAuthorityList("ROLE_USER"));
Authentication toSaveToken = new UsernamePasswordAuthenticationToken(username, "password",
AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContext toSaveContext = SecurityContextHolder.createEmptyContext();
toSaveContext.setAuthentication(toSaveToken);
toSave.setAttribute(SPRING_SECURITY_CONTEXT, toSaveContext);
@@ -108,10 +111,8 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
this.repository.save(toSave);
assertThat(this.registry.receivedEvent(toSave.getId())).isTrue();
assertThat(this.registry.<SessionCreatedEvent>getEvent(toSave.getId()))
.isInstanceOf(SessionCreatedEvent.class);
assertThat(this.redis.boundSetOps(usernameSessionKey).members())
.contains(toSave.getId());
assertThat(this.registry.<SessionCreatedEvent>getEvent(toSave.getId())).isInstanceOf(SessionCreatedEvent.class);
assertThat(this.redis.boundSetOps(usernameSessionKey).members()).contains(toSave.getId());
Session session = this.repository.findById(toSave.getId());
@@ -127,16 +128,14 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
assertThat(this.repository.findById(toSave.getId())).isNull();
assertThat(this.registry.<SessionDestroyedEvent>getEvent(toSave.getId()))
.isInstanceOf(SessionDestroyedEvent.class);
assertThat(this.redis.boundSetOps(usernameSessionKey).members())
.doesNotContain(toSave.getId());
assertThat(this.redis.boundSetOps(usernameSessionKey).members()).doesNotContain(toSave.getId());
assertThat(this.registry.getEvent(toSave.getId()).getSession()
.<String>getAttribute(expectedAttributeName))
assertThat(this.registry.getEvent(toSave.getId()).getSession().<String>getAttribute(expectedAttributeName))
.isEqualTo(expectedAttributeValue);
}
@Test
public void putAllOnSingleAttrDoesNotRemoveOld() {
void putAllOnSingleAttrDoesNotRemoveOld() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute("a", "b");
@@ -157,15 +156,15 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Test
public void findByPrincipalName() throws Exception {
void findByPrincipalName() throws Exception {
String principalName = "findByPrincipalName" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
@@ -173,7 +172,28 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
this.repository.deleteById(toSave.getId());
assertThat(this.registry.receivedEvent(toSave.getId())).isTrue();
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
assertThat(findByPrincipalName).hasSize(0);
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
}
@Test
void findByPrincipalNameExpireRemovesIndex() {
String principalName = "findByPrincipalNameExpireRemovesIndex" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
this.repository.save(toSave);
String body = "RedisIndexedSessionRepositoryITests:sessions:expires:" + toSave.getId();
String channel = "__keyevent@0__:expired";
DefaultMessage message = new DefaultMessage(channel.getBytes(StandardCharsets.UTF_8),
body.getBytes(StandardCharsets.UTF_8));
byte[] pattern = new byte[] {};
this.repository.onMessage(message, pattern);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).hasSize(0);
@@ -181,34 +201,8 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Test
public void findByPrincipalNameExpireRemovesIndex() throws Exception {
String principalName = "findByPrincipalNameExpireRemovesIndex"
+ UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
this.repository.save(toSave);
String body = "RedisOperationsSessionRepositoryITests:sessions:expires:"
+ toSave.getId();
String channel = "__keyevent@0__:expired";
DefaultMessage message = new DefaultMessage(
channel.getBytes(StandardCharsets.UTF_8),
body.getBytes(StandardCharsets.UTF_8));
byte[] pattern = new byte[] {};
this.repository.onMessage(message, pattern);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
assertThat(findByPrincipalName).hasSize(0);
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
}
@Test
public void findByPrincipalNameNoPrincipalNameChange() throws Exception {
String principalName = "findByPrincipalNameNoPrincipalNameChange"
+ UUID.randomUUID();
void findByPrincipalNameNoPrincipalNameChange() {
String principalName = "findByPrincipalNameNoPrincipalNameChange" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
@@ -217,17 +211,16 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute("other", "value");
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByPrincipalNameNoPrincipalNameChangeReload() throws Exception {
String principalName = "findByPrincipalNameNoPrincipalNameChangeReload"
+ UUID.randomUUID();
void findByPrincipalNameNoPrincipalNameChangeReload() {
String principalName = "findByPrincipalNameNoPrincipalNameChangeReload" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
@@ -238,15 +231,15 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute("other", "value");
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByDeletedPrincipalName() throws Exception {
void findByDeletedPrincipalName() {
String principalName = "findByDeletedPrincipalName" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
@@ -256,14 +249,14 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute(INDEX_NAME, null);
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).isEmpty();
}
@Test
public void findByChangedPrincipalName() throws Exception {
void findByChangedPrincipalName() {
String principalName = "findByChangedPrincipalName" + UUID.randomUUID();
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
@@ -274,19 +267,18 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute(INDEX_NAME, principalNameChanged);
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).isEmpty();
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalNameChanged);
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByDeletedPrincipalNameReload() throws Exception {
void findByDeletedPrincipalNameReload() {
String principalName = "findByDeletedPrincipalName" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
@@ -297,14 +289,14 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
getSession.setAttribute(INDEX_NAME, null);
this.repository.save(getSession);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).isEmpty();
}
@Test
public void findByChangedPrincipalNameReload() throws Exception {
void findByChangedPrincipalNameReload() {
String principalName = "findByChangedPrincipalName" + UUID.randomUUID();
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
@@ -317,26 +309,25 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
getSession.setAttribute(INDEX_NAME, principalNameChanged);
this.repository.save(getSession);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).isEmpty();
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalNameChanged);
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findBySecurityPrincipalName() throws Exception {
void findBySecurityPrincipalName() throws Exception {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
@@ -344,7 +335,27 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
this.repository.deleteById(toSave.getId());
assertThat(this.registry.receivedEvent(toSave.getId())).isTrue();
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
assertThat(findByPrincipalName).hasSize(0);
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
}
@Test
void findBySecurityPrincipalNameExpireRemovesIndex() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
this.repository.save(toSave);
String body = "RedisIndexedSessionRepositoryITests:sessions:expires:" + toSave.getId();
String channel = "__keyevent@0__:expired";
DefaultMessage message = new DefaultMessage(channel.getBytes(StandardCharsets.UTF_8),
body.getBytes(StandardCharsets.UTF_8));
byte[] pattern = new byte[] {};
this.repository.onMessage(message, pattern);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).hasSize(0);
@@ -352,30 +363,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Test
public void findBySecurityPrincipalNameExpireRemovesIndex() throws Exception {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
this.repository.save(toSave);
String body = "RedisOperationsSessionRepositoryITests:sessions:expires:"
+ toSave.getId();
String channel = "__keyevent@0__:expired";
DefaultMessage message = new DefaultMessage(
channel.getBytes(StandardCharsets.UTF_8),
body.getBytes(StandardCharsets.UTF_8));
byte[] pattern = new byte[] {};
this.repository.onMessage(message, pattern);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
assertThat(findByPrincipalName).hasSize(0);
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
}
@Test
public void findByPrincipalNameNoSecurityPrincipalNameChange() throws Exception {
void findByPrincipalNameNoSecurityPrincipalNameChange() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
@@ -384,16 +372,15 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute("other", "value");
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByPrincipalNameNoSecurityPrincipalNameChangeReload()
throws Exception {
void findByPrincipalNameNoSecurityPrincipalNameChangeReload() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
@@ -404,15 +391,15 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute("other", "value");
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByDeletedSecurityPrincipalName() throws Exception {
void findByDeletedSecurityPrincipalName() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
@@ -421,14 +408,14 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute(SPRING_SECURITY_CONTEXT, null);
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).isEmpty();
}
@Test
public void findByChangedSecurityPrincipalName() throws Exception {
void findByChangedSecurityPrincipalName() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
@@ -437,19 +424,18 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.changedContext);
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).isEmpty();
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getChangedSecurityName());
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByDeletedSecurityPrincipalNameReload() throws Exception {
void findByDeletedSecurityPrincipalNameReload() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
@@ -459,14 +445,14 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
getSession.setAttribute(INDEX_NAME, null);
this.repository.save(getSession);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getChangedSecurityName());
assertThat(findByPrincipalName).isEmpty();
}
@Test
public void findByChangedSecurityPrincipalNameReload() throws Exception {
void findByChangedSecurityPrincipalNameReload() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
@@ -477,19 +463,18 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
getSession.setAttribute(SPRING_SECURITY_CONTEXT, this.changedContext);
this.repository.save(getSession);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).isEmpty();
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getChangedSecurityName());
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void changeSessionIdWhenOnlyChangeId() throws Exception {
void changeSessionIdWhenOnlyChangeId() {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
RedisSession toSave = this.repository.createSession();
@@ -514,7 +499,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Test
public void changeSessionIdWhenChangeTwice() throws Exception {
void changeSessionIdWhenChangeTwice() {
RedisSession toSave = this.repository.createSession();
this.repository.save(toSave);
@@ -531,7 +516,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Test
public void changeSessionIdWhenSetAttributeOnChangedSession() throws Exception {
void changeSessionIdWhenSetAttributeOnChangedSession() {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
@@ -556,7 +541,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Test
public void changeSessionIdWhenHasNotSaved() throws Exception {
void changeSessionIdWhenHasNotSaved() {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
@@ -572,7 +557,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
// gh-962
@Test
public void changeSessionIdSaveTwice() {
void changeSessionIdSaveTwice() {
RedisSession toSave = this.repository.createSession();
String originalId = toSave.getId();
toSave.changeSessionId();
@@ -586,7 +571,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
// gh-1137
@Test
public void changeSessionIdWhenSessionIsDeleted() {
void changeSessionIdWhenSessionIsDeleted() {
RedisSession toSave = this.repository.createSession();
String sessionId = toSave.getId();
this.repository.save(toSave);
@@ -601,7 +586,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Test // gh-1270
public void changeSessionIdSaveConcurrently() {
void changeSessionIdSaveConcurrently() {
RedisSession toSave = this.repository.createSession();
String originalId = toSave.getId();
this.repository.save(toSave);
@@ -628,11 +613,11 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Configuration
@EnableRedisHttpSession(redisNamespace = "RedisOperationsSessionRepositoryITests")
@EnableRedisHttpSession(redisNamespace = "RedisIndexedSessionRepositoryITests")
static class Config extends BaseConfig {
@Bean
public SessionEventRegistry sessionEventRegistry() {
SessionEventRegistry sessionEventRegistry() {
return new SessionEventRegistry();
}

View File

@@ -32,7 +32,7 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.session.MapSession;
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
import org.springframework.session.data.redis.SimpleRedisOperationsSessionRepository.RedisSession;
import org.springframework.session.data.redis.RedisSessionRepository.RedisSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
@@ -41,25 +41,24 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
/**
* Integration tests for {@link SimpleRedisOperationsSessionRepository}.
* Integration tests for {@link RedisSessionRepository}.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
class SimpleRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
class RedisSessionRepositoryITests extends AbstractRedisITests {
@Autowired
private SimpleRedisOperationsSessionRepository sessionRepository;
private RedisSessionRepository sessionRepository;
@Test
void save_NewSession_ShouldSaveSession() {
RedisSession session = createAndSaveSession(Instant.now());
assertThat(session.getMaxInactiveInterval()).isEqualTo(
Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS));
assertThat(session.getAttributeNames())
.isEqualTo(Collections.singleton("attribute1"));
assertThat(session.getMaxInactiveInterval())
.isEqualTo(Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS));
assertThat(session.getAttributeNames()).isEqualTo(Collections.singleton("attribute1"));
assertThat(session.<String>getAttribute("attribute1")).isEqualTo("value1");
}
@@ -72,8 +71,7 @@ class SimpleRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
void save_DeletedSession_ShouldThrowException() {
RedisSession session = createAndSaveSession(Instant.now());
this.sessionRepository.deleteById(session.getId());
assertThatIllegalStateException()
.isThrownBy(() -> this.sessionRepository.save(session))
assertThatIllegalStateException().isThrownBy(() -> this.sessionRepository.save(session))
.withMessage("Session was invalidated");
}
@@ -164,8 +162,7 @@ class SimpleRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
this.sessionRepository.deleteById(originalSessionId);
updateSession(session, Instant.now(), "attribute1", "value1");
String newSessionId = session.changeSessionId();
assertThatIllegalStateException()
.isThrownBy(() -> this.sessionRepository.save(session))
assertThatIllegalStateException().isThrownBy(() -> this.sessionRepository.save(session))
.withMessage("Session was invalidated");
assertThat(this.sessionRepository.findById(newSessionId)).isNull();
assertThat(this.sessionRepository.findById(originalSessionId)).isNull();
@@ -182,8 +179,7 @@ class SimpleRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
this.sessionRepository.save(copy1);
updateSession(copy2, now.plusSeconds(2L), "attribute3", "value3");
String newSessionId2 = copy2.changeSessionId();
assertThatIllegalStateException()
.isThrownBy(() -> this.sessionRepository.save(copy2))
assertThatIllegalStateException().isThrownBy(() -> this.sessionRepository.save(copy2))
.withMessage("Session was invalidated");
assertThat(this.sessionRepository.findById(newSessionId1)).isNotNull();
assertThat(this.sessionRepository.findById(newSessionId2)).isNull();
@@ -220,8 +216,8 @@ class SimpleRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
return this.sessionRepository.findById(session.getId());
}
private static void updateSession(RedisSession session, Instant lastAccessedTime,
String attributeName, Object attributeValue) {
private static void updateSession(RedisSession session, Instant lastAccessedTime, String attributeName,
Object attributeValue) {
session.setLastAccessedTime(lastAccessedTime);
session.setAttribute(attributeName, attributeValue);
}
@@ -231,12 +227,11 @@ class SimpleRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
static class Config extends BaseConfig {
@Bean
public SimpleRedisOperationsSessionRepository sessionRepository(
RedisConnectionFactory redisConnectionFactory) {
RedisSessionRepository sessionRepository(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.afterPropertiesSet();
return new SimpleRedisOperationsSessionRepository(redisTemplate);
return new RedisSessionRepository(redisTemplate);
}
}

View File

@@ -44,8 +44,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Session>
extends AbstractRedisITests {
class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Session> extends AbstractRedisITests {
@Autowired
private SessionRepository<S> repository;
@@ -56,16 +55,16 @@ public class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Session
private final Object lock = new Object();
@BeforeEach
public void setup() {
void setup() {
this.registry.setLock(this.lock);
}
@Test
public void expireFiresSessionExpiredEvent() throws InterruptedException {
void expireFiresSessionExpiredEvent() throws InterruptedException {
S toSave = this.repository.createSession();
toSave.setAttribute("a", "b");
Authentication toSaveToken = new UsernamePasswordAuthenticationToken("user",
"password", AuthorityUtils.createAuthorityList("ROLE_USER"));
Authentication toSaveToken = new UsernamePasswordAuthenticationToken("user", "password",
AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContext toSaveContext = SecurityContextHolder.createEmptyContext();
toSaveContext.setAuthentication(toSaveToken);
toSave.setAttribute("SPRING_SECURITY_CONTEXT", toSaveContext);
@@ -89,9 +88,10 @@ public class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Session
assertThat(this.registry.receivedEvent()).isTrue();
}
static class SessionExpiredEventRegistry
implements ApplicationListener<SessionExpiredEvent> {
static class SessionExpiredEventRegistry implements ApplicationListener<SessionExpiredEvent> {
private boolean receivedEvent;
private Object lock;
@Override
@@ -102,13 +102,14 @@ public class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Session
}
}
public boolean receivedEvent() {
boolean receivedEvent() {
return this.receivedEvent;
}
public void setLock(Object lock) {
void setLock(Object lock) {
this.lock = lock;
}
}
@Configuration
@@ -116,7 +117,7 @@ public class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Session
static class Config extends BaseConfig {
@Bean
public SessionExpiredEventRegistry sessionDestroyedEventRegistry() {
SessionExpiredEventRegistry sessionDestroyedEventRegistry() {
return new SessionExpiredEventRegistry();
}

View File

@@ -21,10 +21,10 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.FlushMode;
import org.springframework.session.Session;
import org.springframework.session.SessionRepository;
import org.springframework.session.data.redis.AbstractRedisITests;
import org.springframework.session.data.redis.RedisFlushMode;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -35,14 +35,13 @@ import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class RedisOperationsSessionRepositoryFlushImmediatelyITests<S extends Session>
extends AbstractRedisITests {
class RedisIndexedSessionRepositoryFlushImmediatelyITests<S extends Session> extends AbstractRedisITests {
@Autowired
private SessionRepository<S> sessionRepository;
@Test
public void savesOnCreate() throws InterruptedException {
void savesOnCreate() {
S created = this.sessionRepository.createSession();
S getSession = this.sessionRepository.findById(created.getId());
@@ -51,7 +50,7 @@ public class RedisOperationsSessionRepositoryFlushImmediatelyITests<S extends Se
}
@Configuration
@EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE)
@EnableRedisHttpSession(flushMode = FlushMode.IMMEDIATE)
static class RedisHttpSessionConfig extends BaseConfig {
}

View File

@@ -45,7 +45,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class RedisListenerContainerTaskExecutorITests extends AbstractRedisITests {
class RedisListenerContainerTaskExecutorITests extends AbstractRedisITests {
@Autowired
private SessionTaskExecutor executor;
@@ -54,10 +54,9 @@ public class RedisListenerContainerTaskExecutorITests extends AbstractRedisITest
private RedisOperations<Object, Object> redis;
@Test
public void testRedisDelEventsAreDispatchedInSessionTaskExecutor()
throws InterruptedException {
BoundSetOperations<Object, Object> ops = this.redis.boundSetOps(
"spring:session:RedisListenerContainerTaskExecutorITests:expirations:dummy");
void testRedisDelEventsAreDispatchedInSessionTaskExecutor() throws InterruptedException {
BoundSetOperations<Object, Object> ops = this.redis
.boundSetOps("spring:session:RedisListenerContainerTaskExecutorITests:expirations:dummy");
ops.add("value");
ops.remove("value");
assertThat(this.executor.taskDispatched()).isTrue();
@@ -65,7 +64,8 @@ public class RedisListenerContainerTaskExecutorITests extends AbstractRedisITest
}
static class SessionTaskExecutor implements TaskExecutor {
private Object lock = new Object();
private final Object lock = new Object();
private final Executor executor;
@@ -88,7 +88,7 @@ public class RedisListenerContainerTaskExecutorITests extends AbstractRedisITest
}
}
public boolean taskDispatched() throws InterruptedException {
boolean taskDispatched() throws InterruptedException {
if (this.taskDispatched != null) {
return this.taskDispatched;
}
@@ -97,6 +97,7 @@ public class RedisListenerContainerTaskExecutorITests extends AbstractRedisITest
}
return (this.taskDispatched != null) ? this.taskDispatched : Boolean.FALSE;
}
}
@Configuration
@@ -104,12 +105,12 @@ public class RedisListenerContainerTaskExecutorITests extends AbstractRedisITest
static class Config extends BaseConfig {
@Bean
public Executor springSessionRedisTaskExecutor() {
Executor springSessionRedisTaskExecutor() {
return new SessionTaskExecutor(Executors.newSingleThreadExecutor());
}
@Bean
public Executor springSessionRedisSubscriptionExecutor() {
Executor springSessionRedisSubscriptionExecutor() {
return new SimpleAsyncTaskExecutor();
}

View File

@@ -16,321 +16,39 @@
package org.springframework.session.data.redis;
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Mono;
import org.springframework.data.redis.core.ReactiveRedisOperations;
import org.springframework.session.MapSession;
import org.springframework.session.ReactiveSessionRepository;
import org.springframework.session.Session;
import org.springframework.util.Assert;
/**
* A {@link ReactiveSessionRepository} that is implemented using Spring Data's
* {@link ReactiveRedisOperations}.
* This {@link ReactiveSessionRepository} implementation is kept in order to support
* migration to {@link ReactiveRedisSessionRepository} in a backwards compatible manner.
*
* @author Vedran Pavic
* @since 2.0
* @since 2.0.0
* @deprecated since 2.2.0 in favor of {@link ReactiveRedisSessionRepository}
*/
public class ReactiveRedisOperationsSessionRepository implements
ReactiveSessionRepository<ReactiveRedisOperationsSessionRepository.RedisSession> {
@Deprecated
public class ReactiveRedisOperationsSessionRepository extends ReactiveRedisSessionRepository {
/**
* The default namespace for each key and channel in Redis used by Spring Session.
* Create a new {@link ReactiveRedisOperationsSessionRepository} instance.
* @param sessionRedisOperations the {@link ReactiveRedisOperations} to use for
* managing sessions
* @see ReactiveRedisSessionRepository#ReactiveRedisSessionRepository(ReactiveRedisOperations)
*/
public static final String DEFAULT_NAMESPACE = "spring:session";
private final ReactiveRedisOperations<String, Object> sessionRedisOperations;
/**
* The namespace for every key used by Spring Session in Redis.
*/
private String namespace = DEFAULT_NAMESPACE + ":";
/**
* If non-null, this value is used to override the default value for
* {@link RedisSession#setMaxInactiveInterval(Duration)}.
*/
private Integer defaultMaxInactiveInterval;
private RedisFlushMode redisFlushMode = RedisFlushMode.ON_SAVE;
public ReactiveRedisOperationsSessionRepository(
ReactiveRedisOperations<String, Object> sessionRedisOperations) {
Assert.notNull(sessionRedisOperations, "sessionRedisOperations cannot be null");
this.sessionRedisOperations = sessionRedisOperations;
}
public void setRedisKeyNamespace(String namespace) {
Assert.hasText(namespace, "namespace cannot be null or empty");
this.namespace = namespace.trim() + ":";
}
/**
* Sets the maximum inactive interval in seconds between requests before newly created
* sessions will be invalidated. A negative time indicates that the session will never
* timeout. The default is 1800 (30 minutes).
*
* @param defaultMaxInactiveInterval the number of seconds that the {@link Session}
* should be kept alive between client requests.
*/
public void setDefaultMaxInactiveInterval(int defaultMaxInactiveInterval) {
this.defaultMaxInactiveInterval = defaultMaxInactiveInterval;
public ReactiveRedisOperationsSessionRepository(ReactiveRedisOperations<String, Object> sessionRedisOperations) {
super(sessionRedisOperations);
}
/**
* Sets the redis flush mode. Default flush mode is {@link RedisFlushMode#ON_SAVE}.
*
* @param redisFlushMode the new redis flush mode
* @deprecated since 2.2.0 as support {@code IMMEDIATE} is removed
*/
@Deprecated
public void setRedisFlushMode(RedisFlushMode redisFlushMode) {
Assert.notNull(redisFlushMode, "redisFlushMode cannot be null");
this.redisFlushMode = redisFlushMode;
}
/**
* Returns the {@link ReactiveRedisOperations} used for sessions.
* @return the {@link ReactiveRedisOperations} used for sessions
* @since 2.1.0
*/
public ReactiveRedisOperations<String, Object> getSessionRedisOperations() {
return this.sessionRedisOperations;
}
@Override
public Mono<RedisSession> createSession() {
return Mono.defer(() -> {
RedisSession session = new RedisSession();
if (this.defaultMaxInactiveInterval != null) {
session.setMaxInactiveInterval(
Duration.ofSeconds(this.defaultMaxInactiveInterval));
}
return Mono.just(session);
});
}
@Override
public Mono<Void> save(RedisSession session) {
if (session.isNew) {
return session.save();
}
String sessionKey = getSessionKey(
session.hasChangedSessionId() ? session.originalSessionId
: session.getId());
return this.sessionRedisOperations.hasKey(sessionKey).flatMap((exists) -> exists
? session.save()
: Mono.error(new IllegalStateException("Session was invalidated")));
}
@Override
public Mono<RedisSession> findById(String id) {
String sessionKey = getSessionKey(id);
// @formatter:off
return this.sessionRedisOperations.opsForHash().entries(sessionKey)
.collectMap((e) -> e.getKey().toString(), Map.Entry::getValue)
.filter((map) -> !map.isEmpty())
.map(new RedisSessionMapper(id))
.filter((session) -> !session.isExpired())
.map(RedisSession::new)
.switchIfEmpty(Mono.defer(() -> deleteById(id).then(Mono.empty())));
// @formatter:on
}
@Override
public Mono<Void> deleteById(String id) {
String sessionKey = getSessionKey(id);
return this.sessionRedisOperations.delete(sessionKey).then();
}
private static String getAttributeKey(String attributeName) {
return RedisSessionMapper.ATTRIBUTE_PREFIX + attributeName;
}
private String getSessionKey(String sessionId) {
return this.namespace + "sessions:" + sessionId;
}
/**
* A custom implementation of {@link Session} that uses a {@link MapSession} as the
* basis for its mapping. It keeps track of any attributes that have changed. When
* {@link RedisSession#saveDelta()} is invoked all the attributes that have been
* changed will be persisted.
*/
final class RedisSession implements Session {
private final MapSession cached;
private final Map<String, Object> delta = new HashMap<>();
private boolean isNew;
private String originalSessionId;
/**
* Creates a new instance ensuring to mark all of the new attributes to be
* persisted in the next save operation.
*/
RedisSession() {
this(new MapSession());
this.delta.put(RedisSessionMapper.CREATION_TIME_KEY,
getCreationTime().toEpochMilli());
this.delta.put(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
(int) getMaxInactiveInterval().getSeconds());
this.delta.put(RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
getLastAccessedTime().toEpochMilli());
this.isNew = true;
this.flushImmediateIfNecessary();
}
/**
* Creates a new instance from the provided {@link MapSession}.
*
* @param mapSession the {@link MapSession} that represents the persisted session
* that was retrieved. Cannot be null.
*/
RedisSession(MapSession mapSession) {
Assert.notNull(mapSession, "mapSession cannot be null");
this.cached = mapSession;
this.originalSessionId = mapSession.getId();
}
@Override
public String getId() {
return this.cached.getId();
}
@Override
public String changeSessionId() {
return this.cached.changeSessionId();
}
@Override
public <T> T getAttribute(String attributeName) {
return this.cached.getAttribute(attributeName);
}
@Override
public Set<String> getAttributeNames() {
return this.cached.getAttributeNames();
}
@Override
public void setAttribute(String attributeName, Object attributeValue) {
this.cached.setAttribute(attributeName, attributeValue);
putAndFlush(getAttributeKey(attributeName), attributeValue);
}
@Override
public void removeAttribute(String attributeName) {
this.cached.removeAttribute(attributeName);
putAndFlush(getAttributeKey(attributeName), null);
}
@Override
public Instant getCreationTime() {
return this.cached.getCreationTime();
}
@Override
public void setLastAccessedTime(Instant lastAccessedTime) {
this.cached.setLastAccessedTime(lastAccessedTime);
putAndFlush(RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
getLastAccessedTime().toEpochMilli());
}
@Override
public Instant getLastAccessedTime() {
return this.cached.getLastAccessedTime();
}
@Override
public void setMaxInactiveInterval(Duration interval) {
this.cached.setMaxInactiveInterval(interval);
putAndFlush(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
(int) getMaxInactiveInterval().getSeconds());
}
@Override
public Duration getMaxInactiveInterval() {
return this.cached.getMaxInactiveInterval();
}
@Override
public boolean isExpired() {
return this.cached.isExpired();
}
private boolean hasChangedSessionId() {
return !getId().equals(this.originalSessionId);
}
private void flushImmediateIfNecessary() {
if (ReactiveRedisOperationsSessionRepository.this.redisFlushMode == RedisFlushMode.IMMEDIATE) {
save();
}
}
private void putAndFlush(String a, Object v) {
this.delta.put(a, v);
flushImmediateIfNecessary();
}
private Mono<Void> save() {
return Mono.defer(() -> saveChangeSessionId().then(saveDelta())
.doOnSuccess((aVoid) -> this.isNew = false));
}
private Mono<Void> saveDelta() {
if (this.delta.isEmpty()) {
return Mono.empty();
}
String sessionKey = getSessionKey(getId());
Mono<Boolean> update = ReactiveRedisOperationsSessionRepository.this.sessionRedisOperations
.opsForHash().putAll(sessionKey, new HashMap<>(this.delta));
Mono<Boolean> setTtl = ReactiveRedisOperationsSessionRepository.this.sessionRedisOperations
.expire(sessionKey, getMaxInactiveInterval());
return update.and(setTtl).and((s) -> {
this.delta.clear();
s.onComplete();
}).then();
}
private Mono<Void> saveChangeSessionId() {
if (!hasChangedSessionId()) {
return Mono.empty();
}
String sessionId = getId();
Publisher<Void> replaceSessionId = (s) -> {
this.originalSessionId = sessionId;
s.onComplete();
};
if (this.isNew) {
return Mono.from(replaceSessionId);
}
else {
String originalSessionKey = getSessionKey(this.originalSessionId);
String sessionKey = getSessionKey(sessionId);
return ReactiveRedisOperationsSessionRepository.this.sessionRedisOperations
.rename(originalSessionKey, sessionKey).and(replaceSessionId);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More