Compare commits
721 Commits
Author | SHA1 | Date |
---|---|---|
|
2196f6da73 | |
|
c21293bb24 | |
|
33038d3e1e | |
|
b66509b4e1 | |
|
e20e2393c9 | |
|
a2d4ecf8ac | |
|
05172cf77b | |
|
4420c92173 | |
|
da8eac3483 | |
|
cb51a44e2b | |
|
5e04d98260 | |
|
61acc52137 | |
|
f1a3971148 | |
|
dd353034de | |
|
c2e838a603 | |
|
6f1bcc4bfa | |
|
2542430e5b | |
|
43b06ca9b9 | |
|
533544d8fc | |
|
5ec993bb8c | |
|
1ebc557bd5 | |
|
2eaad0585c | |
|
46022d2a4e | |
|
a5dbc5bb22 | |
|
16718f676d | |
|
c1924f2fcd | |
|
473fc1b19e | |
|
a79d0e0d10 | |
|
44099d3d21 | |
|
2440667aab | |
|
7db43ef820 | |
|
d97539bc46 | |
|
8c25063273 | |
|
489336255a | |
|
fde0ae4ac9 | |
|
643f6112c7 | |
|
4bf6fcefab | |
|
9d85c379bd | |
|
9d63a74bbc | |
|
f059a953d3 | |
|
1f293cc653 | |
|
49c7546662 | |
|
c92617a015 | |
|
a9bf744b68 | |
|
b503ad3a9a | |
|
a350ead232 | |
|
55a97aa7ad | |
|
06dd6aec3c | |
|
a1038a5e64 | |
|
99f8c4cd0d | |
|
2edd8f9d62 | |
|
3353090bc6 | |
|
ad22bc033f | |
|
dee42bfe2d | |
|
307dc1c477 | |
|
64aad6d060 | |
|
0f41e906b9 | |
|
c65a259637 | |
|
1b44bafda1 | |
|
e4a58a53d0 | |
|
34a8e1bd82 | |
|
af941e0a9a | |
|
7f225a8df5 | |
|
cae3fb578c | |
|
f175d132b3 | |
|
2ca6703f55 | |
|
f59fc4020a | |
|
80c384e92c | |
|
0634c11eee | |
|
bf075ec89c | |
|
f74ed943e5 | |
|
80436abbb6 | |
|
09311ff44e | |
|
9f1e033caf | |
|
4854fec275 | |
|
e83ad75d3e | |
|
657c537cc2 | |
|
0753e7dbf2 | |
|
1d4b9d372f | |
|
e878db0abf | |
|
58e2f9c872 | |
|
1023ed65a6 | |
|
266f9c44e0 | |
|
3fdc1db7ce | |
|
a111f1f68f | |
|
b10262c9bc | |
|
485180df4f | |
|
94fce6f689 | |
|
761302452b | |
|
3f2e1b2466 | |
|
74daedff76 | |
|
169b1b10b0 | |
|
652414155c | |
|
1e4cc948f2 | |
|
4fd9626854 | |
|
8a9528ebdc | |
|
1ed8eb08e0 | |
|
49ba8aa668 | |
|
53cda6a6a1 | |
|
d5717b71ab | |
|
79ad5e6999 | |
|
871f82d116 | |
|
0187b77761 | |
|
04038101d2 | |
|
45bf83d737 | |
|
f7e7664a5a | |
|
6ee519ec57 | |
|
92fe4c55f7 | |
|
911578e560 | |
|
fbcc1fdec6 | |
|
c280fdefe8 | |
|
319e462cba | |
|
aa06ab1e25 | |
|
09967b1a5d | |
|
5c0d2ee180 | |
|
bb19585601 | |
|
f2c2d19a9c | |
|
3db8b5fb26 | |
|
e313624263 | |
|
af2436de84 | |
|
4a62872d63 | |
|
f5d6bea934 | |
|
419d78b359 | |
|
b6950f8fb0 | |
|
f8ce17c751 | |
|
4a30228978 | |
|
f3df45ace1 | |
|
3aaf4b7b0a | |
|
4af0d6d747 | |
|
3c3726b89e | |
|
92ee73df30 | |
|
418e057afc | |
|
1fda419b17 | |
|
4c8cabcb3a | |
|
dec46b45d7 | |
|
57992512b7 | |
|
b566b73be6 | |
|
532ea9abc1 | |
|
ea05f6df15 | |
|
23c9b6510b | |
|
9bb62a074b | |
|
fe975214cd | |
|
c099462e6f | |
|
ee2730ca8d | |
|
b28d390c69 | |
|
e7ffa33d65 | |
|
dadfd9a35d | |
|
2d312ed5f5 | |
|
ee72caf7dc | |
|
a30e832915 | |
|
0ae23de2b5 | |
|
2a521ce4e9 | |
|
3cced515ce | |
|
279de9e807 | |
|
97c89b480f | |
|
82795f9966 | |
|
7c8a15629b | |
|
ef37765625 | |
|
bba56ffc8b | |
|
6f909114e7 | |
|
79091f926d | |
|
155e3bd5e6 | |
|
8008076e04 | |
|
4b2d358384 | |
|
17e655b7e5 | |
|
2b3a8ff647 | |
|
36732bd74a | |
|
352925bbe8 | |
|
f8f6e59d1a | |
|
08a641c1a2 | |
|
26364c27e2 | |
|
787840735b | |
|
e2ba4dad2a | |
|
7a595f1b83 | |
|
922592938a | |
|
b23d7fe203 | |
|
f9d4589259 | |
|
d4fce9a068 | |
|
cc20b3ec3b | |
|
f28bea16c5 | |
|
4ba14c139e | |
|
ad3a18d086 | |
|
98b4afe527 | |
|
a8caeed578 | |
|
bc968fc671 | |
|
1c1a35f6be | |
|
eb307b91ec | |
|
14791f0593 | |
|
474c9cdeb1 | |
|
cbdd7cf23b | |
|
569fa5fd7d | |
|
5a2f90d1f1 | |
|
5301c8d905 | |
|
4f6bbac13e | |
|
54ffc42309 | |
|
8c5a25ee5c | |
|
30d3889079 | |
|
e8b6ab14bc | |
|
5344fb218a | |
|
bdb05639bc | |
|
db10e3d1ed | |
|
ae86895953 | |
|
93c9413ac0 | |
|
f93c43cb8a | |
|
c3aca4b126 | |
|
b3db525f0f | |
|
52c55788a2 | |
|
990644919a | |
|
2756424035 | |
|
9c727be8f2 | |
|
e4e3988433 | |
|
0959271061 | |
|
8c7e0c675f | |
|
0b601118bd | |
|
5348880b69 | |
|
7979a51f65 | |
|
27715dee20 | |
|
d27aedf92a | |
|
b3c28f1ef3 | |
|
f3b44031a6 | |
|
f6da5e7a5c | |
|
8d63043d9e | |
|
b43d2f2088 | |
|
0b0b742758 | |
|
b61e38bef8 | |
|
6490b749db | |
|
9a1d9f677b | |
|
1cd14c96a5 | |
|
51b606e941 | |
|
c5e28c9133 | |
|
c4cace3f74 | |
|
b7695200a9 | |
|
5cec09dd02 | |
|
cae5a811ad | |
|
0afd40fa40 | |
|
3265a2672d | |
|
b6a1c29763 | |
|
9a3a3b1b5e | |
|
6354d802c0 | |
|
bc46bb2a24 | |
|
3b2c8abf50 | |
|
dc341edfdd | |
|
3a9ab15696 | |
|
8d87586395 | |
|
d3bab5f82d | |
|
862db41134 | |
|
42cc7775f4 | |
|
5c95ee798c | |
|
14703cbafd | |
|
3b98af30f5 | |
|
8d000e008f | |
|
335a0b76b5 | |
|
4a1de8534f | |
|
630bb335ea | |
|
c1d51f8687 | |
|
255ea92a57 | |
|
b01dc92233 | |
|
2cf854c5b6 | |
|
4cb2c62230 | |
|
3e12b5692f | |
|
2d1c6615ac | |
|
e9daa9a0bb | |
|
d96267f12b | |
|
9363f03d8d | |
|
aac1845cac | |
|
7689389349 | |
|
f81f2decf1 | |
|
cb0e868472 | |
|
a465cdbf66 | |
|
391e745840 | |
|
ad9a7eecb2 | |
|
c417d2e0a4 | |
|
66ba91876a | |
|
73b5e6a4d1 | |
|
d9fce46848 | |
|
2e76cda4ba | |
|
943f0ae257 | |
|
43fee1678a | |
|
11de7d1ca6 | |
|
6642bf7beb | |
|
fc68b001d8 | |
|
24c25aeae4 | |
|
1acda68d39 | |
|
c53ea0a08c | |
|
6c84674c33 | |
|
4ebf09ad12 | |
|
b02371f763 | |
|
853c6586ee | |
|
a2b680a0e1 | |
|
fb452160e9 | |
|
4be3dc2262 | |
|
ae1e700df9 | |
|
95305691ab | |
|
bc60749949 | |
|
6d13034455 | |
|
2b6a0d533e | |
|
35bceeead2 | |
|
209d4ab5bc | |
|
6f18f1b881 | |
|
2e8eb526bb | |
|
aebecb3007 | |
|
2314d15430 | |
|
cdd39bafd7 | |
|
b71d6475c3 | |
|
7e28314f30 | |
|
780adbf61c | |
|
612714f35e | |
|
0c53038904 | |
|
fae6b0aea0 | |
|
2e09167986 | |
|
67da54e634 | |
|
e20437195e | |
|
748bba378a | |
|
602c149e7f | |
|
297b4dfe70 | |
|
53e4f172b7 | |
|
a7a05491fc | |
|
a9319d6047 | |
|
a3613927c9 | |
|
7ada32ca77 | |
|
51eb4124ee | |
|
b7e1210159 | |
|
bfeceda28a | |
|
d786aa4383 | |
|
02d73ea4f7 | |
|
f374e38f6a | |
|
6c0118f2b0 | |
|
ff83fea96e | |
|
b439c07153 | |
|
74a5d13fe9 | |
|
009bd441f6 | |
|
a6b4400de7 | |
|
8c0018d739 | |
|
3bfcfaa795 | |
|
96afc3f944 | |
|
0e396efaea | |
|
a8161a5e9d | |
|
d157740b26 | |
|
445fc182fb | |
|
4503cac003 | |
|
5a9f5a9b68 | |
|
10fc3fd8f8 | |
|
328f4c5e49 | |
|
b2848d6408 | |
|
350beccbc0 | |
|
641b72db65 | |
|
eeac38b70b | |
|
b9be1179a2 | |
|
8651e971ea | |
|
111418fbc5 | |
|
2215e64a79 | |
|
08ce5b0ccd | |
|
91d30115e5 | |
|
0c53233128 | |
|
f22e4853c3 | |
|
9b83de2351 | |
|
83468d4cd8 | |
|
26c3ec1020 | |
|
3e0a7869e6 | |
|
27d6579573 | |
|
8a75b23e62 | |
|
0d5482d3b6 | |
|
347381419d | |
|
336e7de9fc | |
|
e9c08b8dcc | |
|
0ad349acea | |
|
e2ecc61ca8 | |
|
1de09fb81d | |
|
ed1ee79aef | |
|
4f18e5f1a8 | |
|
7ca0323878 | |
|
83ad15ba3b | |
|
8f0d87a964 | |
|
d183ab4b17 | |
|
d8d47a0441 | |
|
3dbc767ef9 | |
|
da4971e4ac | |
|
eb5f7a2c0a | |
|
07c18ea9f1 | |
|
b3c38a30ae | |
|
dec994ff88 | |
|
fb078a7b6e | |
|
84a403b540 | |
|
b38e719557 | |
|
bd4475d73d | |
|
996aaf62be | |
|
8e7b781d8d | |
|
45775d4481 | |
|
43972621ae | |
|
1cb1727eff | |
|
42203b2d19 | |
|
681336be3a | |
|
c3262719b2 | |
|
4f31950e99 | |
|
1496183f54 | |
|
1e79cb1baf | |
|
e865648d90 | |
|
0a67bbe626 | |
|
b268a938f2 | |
|
b14e5d8d08 | |
|
7caf07bd5c | |
|
04b1b1ca7c | |
|
a0b1df68d5 | |
|
a6cf0365ce | |
|
2dc80b4047 | |
|
4f6243fc2c | |
|
6fba2c2a35 | |
|
2532ae7e22 | |
|
0ef1df58ce | |
|
9daa60d97a | |
|
629777b7c7 | |
|
9ffe550172 | |
|
cb750d2fc5 | |
|
39318d1e65 | |
|
700904cfe2 | |
|
507f868fe9 | |
|
08afe86de0 | |
|
cf95bc19a6 | |
|
f14544d847 | |
|
f0a449d43d | |
|
ec0aca4846 | |
|
2d53253db8 | |
|
4951451f9d | |
|
540161b189 | |
|
b5405d2fe9 | |
|
ac4ea31895 | |
|
0aa40377e1 | |
|
c72475f3e7 | |
|
1a18d57a9b | |
|
0099d7419e | |
|
bdbbcec6fa | |
|
4498b46512 | |
|
99cf0e3cfe | |
|
6a55d7b49b | |
|
c7621bb6be | |
|
4b0b9e5e36 | |
|
3701741d0a | |
|
a2b906ba51 | |
|
3dbbd6db8c | |
|
652401b76c | |
|
d7c482aa16 | |
|
ee83ff5f6a | |
|
d0c742bc7b | |
|
fb56a107ce | |
|
11cbb6aff2 | |
|
b0ab4f8102 | |
|
9924cb87db | |
|
1cf51e1ca5 | |
|
c34ef83314 | |
|
f159701a64 | |
|
d3a9bc54a7 | |
|
1b00d38fda | |
|
4d0cce7791 | |
|
450eb48303 | |
|
e764878b6d | |
|
c86eb5298a | |
|
ee87246974 | |
|
7a73925c90 | |
|
4dc1b644fe | |
|
0fc1a40f3b | |
|
2e8428b760 | |
|
634933b3e5 | |
|
5ca904c17a | |
|
5da4913122 | |
|
e13e1a6efc | |
|
59e3e241e4 | |
|
bc0285b53d | |
|
a4240a86a0 | |
|
3e0e7cde68 | |
|
6574dae603 | |
|
43e0527a6a | |
|
f33c1e6f52 | |
|
3ca81e3227 | |
|
3c757ac48f | |
|
9b0a2cd652 | |
|
7e1af36c1c | |
|
d26a192881 | |
|
b30fa76473 | |
|
63360f3620 | |
|
9e9e412335 | |
|
6207e41473 | |
|
fd4f2b8af5 | |
|
b1a072f423 | |
|
e3d886e29c | |
|
56e7002116 | |
|
f4fce7caa7 | |
|
4f2e2d1671 | |
|
aabc33476e | |
|
d8ff59c36e | |
|
67613c3ac0 | |
|
6f86a16caa | |
|
8a10ec4b6f | |
|
144ddd6517 | |
|
556d970435 | |
|
0b32cde654 | |
|
ed507004af | |
|
6be4edbcc0 | |
|
0368edd306 | |
|
593b977fdd | |
|
c76b1c3068 | |
|
7031c94ba9 | |
|
98cdb3aab9 | |
|
dddebef4b1 | |
|
4104d08dae | |
|
54572d227b | |
|
d9c06d3d5a | |
|
9780b91263 | |
|
b5edbd80e9 | |
|
447b83ef36 | |
|
e64839dc8b | |
|
303f15943f | |
|
4810c48519 | |
|
984a3cd5b1 | |
|
dc6fec6ed4 | |
|
bcacae7e0c | |
|
426e5630bd | |
|
6911c1362d | |
|
3bb34894c8 | |
|
5417f7ac34 | |
|
e9a7ec7da8 | |
|
4d8270084f | |
|
83b7d6e34b | |
|
fa3d12e421 | |
|
fd90e18cf9 | |
|
d2eca01763 | |
|
3099405278 | |
|
fef00c9f7f | |
|
d0629d6594 | |
|
bd90d1266e | |
|
e4ec422b3d | |
|
5afbe56450 | |
|
d4795b8e5e | |
|
a396130c7b | |
|
2bc0e4fbd8 | |
|
7b33888ad4 | |
|
a9314b4dcd | |
|
0aac151e63 | |
|
1e2ad8fa04 | |
|
15af6a7371 | |
|
0623275641 | |
|
239f384ac0 | |
|
2d63763c58 | |
|
9d89264985 | |
|
1c803ce0dd | |
|
a759f981f6 | |
|
4af6640903 | |
|
b6a44dc31f | |
|
24a1b0b449 | |
|
d9b894dc9b | |
|
02c9175dea | |
|
efe3ec191e | |
|
987ff8ca54 | |
|
dd67968bc9 | |
|
669f404676 | |
|
4aa0d9dcac | |
|
90cc5be79f | |
|
f28caee30d | |
|
8d2c090af8 | |
|
a977d260bd | |
|
1554c74c2a | |
|
ab9feff7fa | |
|
08c42701d9 | |
|
63adb82145 | |
|
85afbc6d82 | |
|
d39047183e | |
|
438df257b5 | |
|
ccbf678f5a | |
|
1b7d0b5755 | |
|
d185b319f3 | |
|
4a888ca1db | |
|
92c3d1835a | |
|
aa3bed5e28 | |
|
42c494caa2 | |
|
3f03a3d55e | |
|
75dbbad1f7 | |
|
b888ba46da | |
|
ed96ed6e8c | |
|
055b0993da | |
|
056ed4f226 | |
|
86deef6abf | |
|
9a70591f31 | |
|
79d409a8fc | |
|
3dcd2b79f2 | |
|
2d9b258f3d | |
|
123b8c6d3d | |
|
fc2700674e | |
|
19a7331c3e | |
|
987635972d | |
|
b1b5880f48 | |
|
0c9fcd096c | |
|
11d6c434d9 | |
|
78bc232af4 | |
|
4697f2ea51 | |
|
985e108ccb | |
|
023cbd42f0 | |
|
5e9995999c | |
|
12312c75ef | |
|
5e8d1d4b31 | |
|
96d096e2f9 | |
|
8001061a3c | |
|
f51f872c28 | |
|
552c145213 | |
|
e70edced2f | |
|
7f7d5b157f | |
|
f50e779942 | |
|
c4af7d6c75 | |
|
a6afc39956 | |
|
c8d29fd3fe | |
|
d353038c58 | |
|
8bfb170ebc | |
|
b52c55d633 | |
|
6d3cb8eff7 | |
|
d618f6b1ec | |
|
d785a7f26b | |
|
fafd0bbd20 | |
|
972ceca8cd | |
|
71ff804717 | |
|
c4a4b632c1 | |
|
2c4d162f40 | |
|
3e41807e1d | |
|
4761e13228 | |
|
a5b195f3f2 | |
|
cec58df657 | |
|
e741934a2d | |
|
363d9b555a | |
|
b2e6cb0259 | |
|
fbe0ccf0ae | |
|
576d67a4f8 | |
|
3ffdf6ee1a | |
|
856602ddc4 | |
|
f3ac2d5906 | |
|
254068083d | |
|
b15974024c | |
|
fe371aba17 | |
|
62649ae3ed | |
|
05ae5837e7 | |
|
dc03e3749b | |
|
ff11e21d73 | |
|
16439ad6e3 | |
|
f3082e7802 | |
|
89c7a681c0 | |
|
86bb1b4e57 | |
|
bf0998fe54 | |
|
efa806e3b5 | |
|
75f9138a1a | |
|
4d499c3e46 | |
|
da2365b8cb | |
|
4716cb3713 | |
|
1eaa54759a | |
|
f547bc27a5 | |
|
db5680a79c | |
|
6adddb4c09 | |
|
24a23c4f72 | |
|
a3343797f4 | |
|
98ce1d736e | |
|
e1e8914de2 | |
|
5656c13f31 | |
|
6723cfd809 | |
|
12bf4507d8 | |
|
3dba915c01 | |
|
89c64ef443 | |
|
011d42cb2a | |
|
f272fb6659 | |
|
bab9cdb47f | |
|
3c01fdfeaa | |
|
303d4910bd | |
|
74320454c9 | |
|
0d192347fd | |
|
76157c77fa | |
|
007720d28d | |
|
dcd25abcce | |
|
99629d0d32 | |
|
72e6ddd919 | |
|
26a35c9012 | |
|
6c288c9def | |
|
1157a30d06 | |
|
d744d8c497 | |
|
55443f7c44 | |
|
eb14624047 | |
|
49d3bd32c4 | |
|
f1ed5098a3 | |
|
3fa7c3a521 | |
|
369b1e92f9 | |
|
9d1b4897f1 | |
|
09b631d6c0 | |
|
5f5443ea67 | |
|
d9750462bc | |
|
05ba546a09 | |
|
31a9958a06 | |
|
39a91dda9d | |
|
2907fec181 | |
|
2e09df4e1a | |
|
3a40b0a623 | |
|
f5be18587c | |
|
43f5eb5f79 | |
|
dc3fe1b17d | |
|
717ddac137 | |
|
7ad90fb963 | |
|
c76b087025 | |
|
9b1c07c0eb | |
|
a0a785ec92 | |
|
ca7e025dfd | |
|
8fa656d3da | |
|
2a907ba369 | |
|
795c5f6f73 | |
|
234501a07a | |
|
4bbd68325f | |
|
2660e04c1d | |
|
8bc611c913 | |
|
b46006b227 | |
|
92321b16a0 | |
|
73e5a3551e | |
|
b42a060d0a | |
|
2fa20f3def | |
|
b7282c00ae | |
|
e595327610 | |
|
6e82427ffe | |
|
72befafe67 | |
|
f655db371f | |
|
4679579800 | |
|
d4b37a70ed |
|
@ -23,7 +23,7 @@ inputs:
|
||||||
java-version:
|
java-version:
|
||||||
description: 'Java version to use for the build'
|
description: 'Java version to use for the build'
|
||||||
required: false
|
required: false
|
||||||
default: '24'
|
default: '25'
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
|
@ -34,7 +34,7 @@ runs:
|
||||||
tool-cache: true
|
tool-cache: true
|
||||||
docker-images: false
|
docker-images: false
|
||||||
- name: Set Up Java
|
- name: Set Up Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v5
|
||||||
with:
|
with:
|
||||||
distribution: ${{ inputs.java-early-access == 'true' && 'temurin' || (inputs.java-distribution || 'liberica') }}
|
distribution: ${{ inputs.java-early-access == 'true' && 'temurin' || (inputs.java-distribution || 'liberica') }}
|
||||||
java-version: |
|
java-version: |
|
||||||
|
@ -42,12 +42,12 @@ runs:
|
||||||
${{ inputs.java-toolchain == 'true' && '24' || '' }}
|
${{ inputs.java-toolchain == 'true' && '24' || '' }}
|
||||||
- name: Set Up Gradle With Read/Write Cache
|
- name: Set Up Gradle With Read/Write Cache
|
||||||
if: ${{ inputs.cache-read-only == 'false' }}
|
if: ${{ inputs.cache-read-only == 'false' }}
|
||||||
uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2
|
uses: gradle/actions/setup-gradle@748248ddd2a24f49513d8f472f81c3a07d4d50e1 # v4.4.4
|
||||||
with:
|
with:
|
||||||
cache-read-only: false
|
cache-read-only: false
|
||||||
develocity-access-key: ${{ inputs.develocity-access-key }}
|
develocity-access-key: ${{ inputs.develocity-access-key }}
|
||||||
- name: Set Up Gradle
|
- name: Set Up Gradle
|
||||||
uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2
|
uses: gradle/actions/setup-gradle@748248ddd2a24f49513d8f472f81c3a07d4d50e1 # v4.4.4
|
||||||
with:
|
with:
|
||||||
develocity-access-key: ${{ inputs.develocity-access-key }}
|
develocity-access-key: ${{ inputs.develocity-access-key }}
|
||||||
develocity-token-expiry: 4
|
develocity-token-expiry: 4
|
||||||
|
|
|
@ -21,14 +21,14 @@ runs:
|
||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
- name: Set Up JFrog CLI
|
- name: Set Up JFrog CLI
|
||||||
uses: jfrog/setup-jfrog-cli@2bc6e55719cd37dfb2f655a1e4f16c3440182a9f # v4.5.13
|
uses: jfrog/setup-jfrog-cli@c32bf10843e4071112c4ea3abf622d3b27cd8c17 # v4.7.0
|
||||||
env:
|
env:
|
||||||
JF_ENV_SPRING: ${{ inputs.jfrog-cli-config-token }}
|
JF_ENV_SPRING: ${{ inputs.jfrog-cli-config-token }}
|
||||||
- name: Download Artifacts
|
- name: Download Artifacts
|
||||||
shell: bash
|
shell: bash
|
||||||
run: jf rt download --spec ${{ format('{0}/artifacts.spec', github.action_path) }} --spec-vars 'buildName=${{ format('spring-boot-{0}', inputs.plugin-version) }};buildNumber=${{ inputs.build-number }}'
|
run: jf rt download --spec ${{ format('{0}/artifacts.spec', github.action_path) }} --spec-vars 'buildName=${{ format('spring-boot-{0}', inputs.plugin-version) }};buildNumber=${{ inputs.build-number }}'
|
||||||
- name: Set Up Java
|
- name: Set Up Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v5
|
||||||
with:
|
with:
|
||||||
distribution: 'liberica'
|
distribution: 'liberica'
|
||||||
java-version: '17'
|
java-version: '17'
|
||||||
|
|
|
@ -17,7 +17,7 @@ runs:
|
||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
- name: Set Up JFrog CLI
|
- name: Set Up JFrog CLI
|
||||||
uses: jfrog/setup-jfrog-cli@2bc6e55719cd37dfb2f655a1e4f16c3440182a9f # v4.5.13
|
uses: jfrog/setup-jfrog-cli@c32bf10843e4071112c4ea3abf622d3b27cd8c17 # v4.7.0
|
||||||
env:
|
env:
|
||||||
JF_ENV_SPRING: ${{ inputs.jfrog-cli-config-token }}
|
JF_ENV_SPRING: ${{ inputs.jfrog-cli-config-token }}
|
||||||
- name: Download Release Artifacts
|
- name: Download Release Artifacts
|
||||||
|
|
|
@ -6,3 +6,11 @@ updates:
|
||||||
interval: "weekly"
|
interval: "weekly"
|
||||||
labels:
|
labels:
|
||||||
- "type: task"
|
- "type: task"
|
||||||
|
- "status: waiting-for-triage"
|
||||||
|
- package-ecosystem: "npm"
|
||||||
|
directory: "/antora"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
labels:
|
||||||
|
- "type: task"
|
||||||
|
- "status: waiting-for-triage"
|
||||||
|
|
|
@ -23,16 +23,13 @@ jobs:
|
||||||
toolchain: true
|
toolchain: true
|
||||||
- version: 21
|
- version: 21
|
||||||
toolchain: true
|
toolchain: true
|
||||||
- version: 24
|
|
||||||
toolchain: false
|
|
||||||
- version: 25
|
- version: 25
|
||||||
early-access: true
|
toolchain: false
|
||||||
toolchain: true
|
|
||||||
exclude:
|
exclude:
|
||||||
- os:
|
- os:
|
||||||
name: Linux
|
name: Linux
|
||||||
java:
|
java:
|
||||||
version: 24
|
version: 25
|
||||||
- os:
|
- os:
|
||||||
name: ${{ github.repository == 'spring-projects/spring-boot-commercial' && 'Windows' }}
|
name: ${{ github.repository == 'spring-projects/spring-boot-commercial' && 'Windows' }}
|
||||||
steps:
|
steps:
|
||||||
|
|
|
@ -75,7 +75,7 @@ jobs:
|
||||||
runs-on: ${{ vars.UBUNTU_SMALL || 'ubuntu-latest' }}
|
runs-on: ${{ vars.UBUNTU_SMALL || 'ubuntu-latest' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Set up JFrog CLI
|
- name: Set up JFrog CLI
|
||||||
uses: jfrog/setup-jfrog-cli@2bc6e55719cd37dfb2f655a1e4f16c3440182a9f # v4.5.13
|
uses: jfrog/setup-jfrog-cli@c32bf10843e4071112c4ea3abf622d3b27cd8c17 # v4.7.0
|
||||||
env:
|
env:
|
||||||
JF_ENV_SPRING: ${{ secrets.JF_ARTIFACTORY_SPRING }}
|
JF_ENV_SPRING: ${{ secrets.JF_ARTIFACTORY_SPRING }}
|
||||||
- name: Promote build
|
- name: Promote build
|
||||||
|
|
|
@ -86,7 +86,7 @@ jobs:
|
||||||
runs-on: ${{ vars.UBUNTU_SMALL || 'ubuntu-latest' }}
|
runs-on: ${{ vars.UBUNTU_SMALL || 'ubuntu-latest' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Set up JFrog CLI
|
- name: Set up JFrog CLI
|
||||||
uses: jfrog/setup-jfrog-cli@2bc6e55719cd37dfb2f655a1e4f16c3440182a9f # v4.5.13
|
uses: jfrog/setup-jfrog-cli@c32bf10843e4071112c4ea3abf622d3b27cd8c17 # v4.7.0
|
||||||
env:
|
env:
|
||||||
JF_ENV_SPRING: ${{ vars.COMMERCIAL && secrets.COMMERCIAL_JF_ARTIFACTORY_SPRING || secrets.JF_ARTIFACTORY_SPRING }}
|
JF_ENV_SPRING: ${{ vars.COMMERCIAL && secrets.COMMERCIAL_JF_ARTIFACTORY_SPRING || secrets.JF_ARTIFACTORY_SPRING }}
|
||||||
- name: Promote open source build
|
- name: Promote open source build
|
||||||
|
|
|
@ -49,7 +49,7 @@ jobs:
|
||||||
path: send-notification
|
path: send-notification
|
||||||
sparse-checkout: .github/actions/send-notification
|
sparse-checkout: .github/actions/send-notification
|
||||||
- name: Set Up Java
|
- name: Set Up Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v5
|
||||||
with:
|
with:
|
||||||
distribution: 'liberica'
|
distribution: 'liberica'
|
||||||
java-version: 17
|
java-version: 17
|
||||||
|
@ -59,7 +59,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
stable: true
|
stable: true
|
||||||
- name: Set Up Gradle
|
- name: Set Up Gradle
|
||||||
uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2
|
uses: gradle/actions/setup-gradle@748248ddd2a24f49513d8f472f81c3a07d4d50e1 # v4.4.4
|
||||||
with:
|
with:
|
||||||
cache-read-only: false
|
cache-read-only: false
|
||||||
- name: Configure Gradle Properties
|
- name: Configure Gradle Properties
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
# Enable auto-env through the sdkman_auto_env config
|
# Enable auto-env through the sdkman_auto_env config
|
||||||
# Add key=value pairs of SDKs to use below
|
# Add key=value pairs of SDKs to use below
|
||||||
java=24.0.2-librca
|
java=25-librca
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
"@springio/antora-xref-extension": "1.0.0-alpha.4",
|
"@springio/antora-xref-extension": "1.0.0-alpha.4",
|
||||||
"@springio/antora-zip-contents-collector-extension": "1.0.0-alpha.8",
|
"@springio/antora-zip-contents-collector-extension": "1.0.0-alpha.8",
|
||||||
"@springio/asciidoctor-extensions": "1.0.0-alpha.17",
|
"@springio/asciidoctor-extensions": "1.0.0-alpha.17",
|
||||||
"patch-package": "^8.0.0"
|
"patch-package": "^8.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@antora/asciidoc-loader": {
|
"node_modules/@antora/asciidoc-loader": {
|
||||||
|
@ -575,14 +575,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz",
|
||||||
"integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ=="
|
"integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ=="
|
||||||
},
|
},
|
||||||
"node_modules/at-least-node": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/atomic-sleep": {
|
"node_modules/atomic-sleep": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
|
||||||
|
@ -591,6 +583,21 @@
|
||||||
"node": ">=8.0.0"
|
"node": ">=8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/available-typed-arrays": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"possible-typed-array-names": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
@ -626,9 +633,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
|
@ -718,15 +726,44 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/call-bind": {
|
"node_modules/call-bind": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
|
||||||
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
|
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.0",
|
||||||
"es-define-property": "^1.0.0",
|
"es-define-property": "^1.0.0",
|
||||||
"es-errors": "^1.3.0",
|
|
||||||
"function-bind": "^1.1.2",
|
|
||||||
"get-intrinsic": "^1.2.4",
|
"get-intrinsic": "^1.2.4",
|
||||||
"set-function-length": "^1.2.1"
|
"set-function-length": "^1.2.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/call-bind-apply-helpers": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/call-bound": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.2",
|
||||||
|
"get-intrinsic": "^1.3.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
|
@ -1150,6 +1187,20 @@
|
||||||
"resolved": "https://registry.npmjs.org/diff3/-/diff3-0.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/diff3/-/diff3-0.0.3.tgz",
|
||||||
"integrity": "sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g=="
|
"integrity": "sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g=="
|
||||||
},
|
},
|
||||||
|
"node_modules/dunder-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.1",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"gopd": "^1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/duplexify": {
|
"node_modules/duplexify": {
|
||||||
"version": "4.1.3",
|
"version": "4.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz",
|
||||||
|
@ -1170,12 +1221,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/es-define-property": {
|
"node_modules/es-define-property": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||||
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||||
"dependencies": {
|
"license": "MIT",
|
||||||
"get-intrinsic": "^1.2.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
|
@ -1188,6 +1237,18 @@
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/es-object-atoms": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/event-target-shim": {
|
"node_modules/event-target-shim": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
||||||
|
@ -1316,23 +1377,38 @@
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/for-each": {
|
||||||
|
"version": "0.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
|
||||||
|
"integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-callable": "^1.2.7"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fs-constants": {
|
"node_modules/fs-constants": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
|
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
|
||||||
},
|
},
|
||||||
"node_modules/fs-extra": {
|
"node_modules/fs-extra": {
|
||||||
"version": "9.1.0",
|
"version": "10.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||||
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
|
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"at-least-node": "^1.0.0",
|
|
||||||
"graceful-fs": "^4.2.0",
|
"graceful-fs": "^4.2.0",
|
||||||
"jsonfile": "^6.0.1",
|
"jsonfile": "^6.0.1",
|
||||||
"universalify": "^2.0.0"
|
"universalify": "^2.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fs-mkdirp-stream": {
|
"node_modules/fs-mkdirp-stream": {
|
||||||
|
@ -1361,15 +1437,21 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/get-intrinsic": {
|
"node_modules/get-intrinsic": {
|
||||||
"version": "1.2.4",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||||
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.2",
|
||||||
|
"es-define-property": "^1.0.1",
|
||||||
"es-errors": "^1.3.0",
|
"es-errors": "^1.3.0",
|
||||||
|
"es-object-atoms": "^1.1.1",
|
||||||
"function-bind": "^1.1.2",
|
"function-bind": "^1.1.2",
|
||||||
"has-proto": "^1.0.1",
|
"get-proto": "^1.0.1",
|
||||||
"has-symbols": "^1.0.3",
|
"gopd": "^1.2.0",
|
||||||
"hasown": "^2.0.0"
|
"has-symbols": "^1.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"math-intrinsics": "^1.1.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
|
@ -1378,6 +1460,19 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/get-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"dunder-proto": "^1.0.1",
|
||||||
|
"es-object-atoms": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/get-stream": {
|
"node_modules/get-stream": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
|
||||||
|
@ -1441,11 +1536,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/gopd": {
|
"node_modules/gopd": {
|
||||||
"version": "1.0.1",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||||
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||||
"dependencies": {
|
"license": "MIT",
|
||||||
"get-intrinsic": "^1.1.3"
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
@ -1495,10 +1591,11 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/has-proto": {
|
"node_modules/has-symbols": {
|
||||||
"version": "1.0.3",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||||
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
|
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
},
|
},
|
||||||
|
@ -1506,10 +1603,14 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/has-symbols": {
|
"node_modules/has-tostringtag": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||||
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
|
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-symbols": "^1.0.3"
|
||||||
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
},
|
},
|
||||||
|
@ -1538,9 +1639,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/help-me/node_modules/brace-expansion": {
|
"node_modules/help-me/node_modules/brace-expansion": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0"
|
"balanced-match": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
@ -1640,6 +1742,18 @@
|
||||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||||
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
|
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
|
||||||
},
|
},
|
||||||
|
"node_modules/is-callable": {
|
||||||
|
"version": "1.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
|
||||||
|
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-docker": {
|
"node_modules/is-docker": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
|
||||||
|
@ -1713,6 +1827,21 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-typed-array": {
|
||||||
|
"version": "1.1.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
|
||||||
|
"integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"which-typed-array": "^1.1.16"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-unc-path": {
|
"node_modules/is-unc-path": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
|
||||||
|
@ -1856,9 +1985,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jsonfile": {
|
"node_modules/jsonfile": {
|
||||||
"version": "6.1.0",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
|
||||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"universalify": "^2.0.0"
|
"universalify": "^2.0.0"
|
||||||
},
|
},
|
||||||
|
@ -1980,6 +2110,15 @@
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/math-intrinsics": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/micromatch": {
|
"node_modules/micromatch": {
|
||||||
"version": "4.0.8",
|
"version": "4.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||||
|
@ -2185,38 +2324,30 @@
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/os-tmpdir": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pako": {
|
"node_modules/pako": {
|
||||||
"version": "1.0.11",
|
"version": "1.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||||
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
|
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
|
||||||
},
|
},
|
||||||
"node_modules/patch-package": {
|
"node_modules/patch-package": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz",
|
||||||
"integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==",
|
"integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@yarnpkg/lockfile": "^1.1.0",
|
"@yarnpkg/lockfile": "^1.1.0",
|
||||||
"chalk": "^4.1.2",
|
"chalk": "^4.1.2",
|
||||||
"ci-info": "^3.7.0",
|
"ci-info": "^3.7.0",
|
||||||
"cross-spawn": "^7.0.3",
|
"cross-spawn": "^7.0.3",
|
||||||
"find-yarn-workspace-root": "^2.0.0",
|
"find-yarn-workspace-root": "^2.0.0",
|
||||||
"fs-extra": "^9.0.0",
|
"fs-extra": "^10.0.0",
|
||||||
"json-stable-stringify": "^1.0.2",
|
"json-stable-stringify": "^1.0.2",
|
||||||
"klaw-sync": "^6.0.0",
|
"klaw-sync": "^6.0.0",
|
||||||
"minimist": "^1.2.6",
|
"minimist": "^1.2.6",
|
||||||
"open": "^7.4.2",
|
"open": "^7.4.2",
|
||||||
"rimraf": "^2.6.3",
|
|
||||||
"semver": "^7.5.3",
|
"semver": "^7.5.3",
|
||||||
"slash": "^2.0.0",
|
"slash": "^2.0.0",
|
||||||
"tmp": "^0.0.33",
|
"tmp": "^0.2.4",
|
||||||
"yaml": "^2.2.2"
|
"yaml": "^2.2.2"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
@ -2426,6 +2557,15 @@
|
||||||
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz",
|
||||||
"integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA=="
|
"integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/possible-typed-array-names": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/process": {
|
"node_modules/process": {
|
||||||
"version": "0.11.10",
|
"version": "0.11.10",
|
||||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||||
|
@ -2506,9 +2646,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/readdir-glob/node_modules/brace-expansion": {
|
"node_modules/readdir-glob/node_modules/brace-expansion": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0"
|
"balanced-match": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
@ -2594,18 +2735,6 @@
|
||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rimraf": {
|
|
||||||
"version": "2.7.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
|
||||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
|
||||||
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
|
||||||
"dependencies": {
|
|
||||||
"glob": "^7.1.3"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"rimraf": "bin.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/safe-buffer": {
|
"node_modules/safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
@ -2704,15 +2833,23 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/sha.js": {
|
"node_modules/sha.js": {
|
||||||
"version": "2.4.11",
|
"version": "2.4.12",
|
||||||
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
|
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz",
|
||||||
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
|
"integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==",
|
||||||
|
"license": "(MIT AND BSD-3-Clause)",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"inherits": "^2.0.1",
|
"inherits": "^2.0.4",
|
||||||
"safe-buffer": "^5.0.1"
|
"safe-buffer": "^5.2.1",
|
||||||
|
"to-buffer": "^1.2.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"sha.js": "bin.js"
|
"sha.js": "bin.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/shebang-command": {
|
"node_modules/shebang-command": {
|
||||||
|
@ -2954,14 +3091,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tmp": {
|
"node_modules/tmp": {
|
||||||
"version": "0.0.33",
|
"version": "0.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
|
||||||
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
"integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==",
|
||||||
"dependencies": {
|
"license": "MIT",
|
||||||
"os-tmpdir": "~1.0.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.6.0"
|
"node": ">=14.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/to-absolute-glob": {
|
"node_modules/to-absolute-glob": {
|
||||||
|
@ -2977,9 +3112,24 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/to-buffer": {
|
"node_modules/to-buffer": {
|
||||||
"version": "1.1.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz",
|
||||||
"integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg=="
|
"integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"isarray": "^2.0.5",
|
||||||
|
"safe-buffer": "^5.2.1",
|
||||||
|
"typed-array-buffer": "^1.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/to-buffer/node_modules/isarray": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/to-regex-range": {
|
"node_modules/to-regex-range": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
|
@ -3003,6 +3153,20 @@
|
||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/typed-array-buffer": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bound": "^1.0.3",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"is-typed-array": "^1.1.14"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/uglify-js": {
|
"node_modules/uglify-js": {
|
||||||
"version": "3.17.4",
|
"version": "3.17.4",
|
||||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
|
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
|
||||||
|
@ -3045,6 +3209,7 @@
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.0.0"
|
"node": ">= 10.0.0"
|
||||||
}
|
}
|
||||||
|
@ -3252,6 +3417,27 @@
|
||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/which-typed-array": {
|
||||||
|
"version": "1.1.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
|
||||||
|
"integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"available-typed-arrays": "^1.0.7",
|
||||||
|
"call-bind": "^1.0.8",
|
||||||
|
"call-bound": "^1.0.4",
|
||||||
|
"for-each": "^0.3.5",
|
||||||
|
"get-proto": "^1.0.1",
|
||||||
|
"gopd": "^1.2.0",
|
||||||
|
"has-tostringtag": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/wordwrap": {
|
"node_modules/wordwrap": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
"@springio/antora-zip-contents-collector-extension": "1.0.0-alpha.8",
|
"@springio/antora-zip-contents-collector-extension": "1.0.0-alpha.8",
|
||||||
"@asciidoctor/tabs": "1.0.0-beta.6",
|
"@asciidoctor/tabs": "1.0.0-beta.6",
|
||||||
"@springio/asciidoctor-extensions": "1.0.0-alpha.17",
|
"@springio/asciidoctor-extensions": "1.0.0-alpha.17",
|
||||||
"patch-package": "^8.0.0"
|
"patch-package": "^8.0.1"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"ui-bundle-url": "https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.18/ui-bundle.zip"
|
"ui-bundle-url": "https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.18/ui-bundle.zip"
|
||||||
|
|
|
@ -80,7 +80,6 @@ tasks.register("integrationTest") {
|
||||||
ant.propertyref(name: "ivy.class.path")
|
ant.propertyref(name: "ivy.class.path")
|
||||||
}
|
}
|
||||||
plainlistener()
|
plainlistener()
|
||||||
file(layout.buildDirectory.dir("test-results/integrationTest")).mkdirs()
|
|
||||||
xmllistener(toDir: resultsDir)
|
xmllistener(toDir: resultsDir)
|
||||||
fileset(dir: layout.buildDirectory.dir("it").get().asFile.toString(), includes: "**/build.xml")
|
fileset(dir: layout.buildDirectory.dir("it").get().asFile.toString(), includes: "**/build.xml")
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,8 +59,6 @@ dependencies {
|
||||||
|
|
||||||
testImplementation(project(":test-support:spring-boot-gradle-test-support"))
|
testImplementation(project(":test-support:spring-boot-gradle-test-support"))
|
||||||
testImplementation(project(":test-support:spring-boot-test-support"))
|
testImplementation(project(":test-support:spring-boot-test-support"))
|
||||||
testImplementation("com.fasterxml.jackson.core:jackson-databind")
|
|
||||||
testImplementation("com.fasterxml.jackson.module:jackson-module-parameter-names")
|
|
||||||
testImplementation("com.tngtech.archunit:archunit-junit5:1.4.0")
|
testImplementation("com.tngtech.archunit:archunit-junit5:1.4.0")
|
||||||
testImplementation("net.java.dev.jna:jna-platform")
|
testImplementation("net.java.dev.jna:jna-platform")
|
||||||
testImplementation("org.apache.commons:commons-compress")
|
testImplementation("org.apache.commons:commons-compress")
|
||||||
|
@ -70,6 +68,7 @@ dependencies {
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-compiler-runner:$kotlinVersion")
|
testImplementation("org.jetbrains.kotlin:kotlin-compiler-runner:$kotlinVersion")
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-daemon-client:$kotlinVersion")
|
testImplementation("org.jetbrains.kotlin:kotlin-daemon-client:$kotlinVersion")
|
||||||
testImplementation("org.tomlj:tomlj:1.0.0")
|
testImplementation("org.tomlj:tomlj:1.0.0")
|
||||||
|
testImplementation("tools.jackson.core:jackson-databind")
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.boot.gradle.plugin;
|
package org.springframework.boot.gradle.plugin;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
@ -38,6 +39,7 @@ import org.gradle.jvm.application.scripts.TemplateBasedScriptGenerator;
|
||||||
import org.gradle.util.GradleVersion;
|
import org.gradle.util.GradleVersion;
|
||||||
|
|
||||||
import org.springframework.boot.gradle.tasks.run.BootRun;
|
import org.springframework.boot.gradle.tasks.run.BootRun;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action that is executed in response to the {@link ApplicationPlugin} being applied.
|
* Action that is executed in response to the {@link ApplicationPlugin} being applied.
|
||||||
|
@ -110,7 +112,7 @@ final class ApplicationPluginAction implements PluginApplicationAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String loadResource(String name) {
|
private String loadResource(String name) {
|
||||||
try (InputStreamReader reader = new InputStreamReader(getClass().getResourceAsStream(name))) {
|
try (InputStreamReader reader = new InputStreamReader(getResourceAsStream(name))) {
|
||||||
char[] buffer = new char[4096];
|
char[] buffer = new char[4096];
|
||||||
int read;
|
int read;
|
||||||
StringWriter writer = new StringWriter();
|
StringWriter writer = new StringWriter();
|
||||||
|
@ -124,6 +126,12 @@ final class ApplicationPluginAction implements PluginApplicationAction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private InputStream getResourceAsStream(String name) {
|
||||||
|
InputStream stream = getClass().getResourceAsStream(name);
|
||||||
|
Assert.state(stream != null, "Resource '%s' not found'".formatted(name));
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
private void configureFilePermissions(CopySpec copySpec, int mode) {
|
private void configureFilePermissions(CopySpec copySpec, int mode) {
|
||||||
if (GradleVersion.current().compareTo(GradleVersion.version("8.3")) >= 0) {
|
if (GradleVersion.current().compareTo(GradleVersion.version("8.3")) >= 0) {
|
||||||
copySpec.filePermissions((filePermissions) -> filePermissions.unix(Integer.toString(mode, 8)));
|
copySpec.filePermissions((filePermissions) -> filePermissions.unix(Integer.toString(mode, 8)));
|
||||||
|
@ -133,9 +141,13 @@ final class ApplicationPluginAction implements PluginApplicationAction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
private void configureFileMode(CopySpec copySpec, int mode) {
|
private void configureFileMode(CopySpec copySpec, int mode) {
|
||||||
copySpec.setFileMode(mode);
|
try {
|
||||||
|
copySpec.getClass().getMethod("setFileMode", Integer.class).invoke(copySpec, Integer.valueOf(mode));
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new RuntimeException("Failed to set file mode on CopySpec", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package org.springframework.boot.gradle.plugin;
|
package org.springframework.boot.gradle.plugin;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
|
@ -33,7 +32,7 @@ import org.gradle.api.specs.Spec;
|
||||||
*/
|
*/
|
||||||
class JarTypeFileSpec implements Spec<File> {
|
class JarTypeFileSpec implements Spec<File> {
|
||||||
|
|
||||||
private static final Set<String> EXCLUDED_JAR_TYPES = Collections.singleton("dependencies-starter");
|
private static final Set<String> EXCLUDED_JAR_TYPES = Set.of("dependencies-starter", "development-tool");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSatisfiedBy(File file) {
|
public boolean isSatisfiedBy(File file) {
|
||||||
|
|
|
@ -285,7 +285,6 @@ final class JavaPluginAction implements PluginApplicationAction {
|
||||||
private void configureProductionRuntimeClasspathConfiguration(Project project) {
|
private void configureProductionRuntimeClasspathConfiguration(Project project) {
|
||||||
Configuration productionRuntimeClasspath = project.getConfigurations()
|
Configuration productionRuntimeClasspath = project.getConfigurations()
|
||||||
.create(SpringBootPlugin.PRODUCTION_RUNTIME_CLASSPATH_CONFIGURATION_NAME);
|
.create(SpringBootPlugin.PRODUCTION_RUNTIME_CLASSPATH_CONFIGURATION_NAME);
|
||||||
productionRuntimeClasspath.setVisible(false);
|
|
||||||
Configuration runtimeClasspath = project.getConfigurations()
|
Configuration runtimeClasspath = project.getConfigurations()
|
||||||
.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME);
|
.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME);
|
||||||
productionRuntimeClasspath.attributes((attributes) -> {
|
productionRuntimeClasspath.attributes((attributes) -> {
|
||||||
|
|
|
@ -104,7 +104,6 @@ class WarPluginAction implements PluginApplicationAction {
|
||||||
.set(project.provider(() -> javaPluginExtension(project).getTargetCompatibility()));
|
.set(project.provider(() -> javaPluginExtension(project).getTargetCompatibility()));
|
||||||
bootWar.resolvedArtifacts(runtimeClasspath.getIncoming().getArtifacts().getResolvedArtifacts());
|
bootWar.resolvedArtifacts(runtimeClasspath.getIncoming().getArtifacts().getResolvedArtifacts());
|
||||||
});
|
});
|
||||||
bootWarProvider.map(War::getClasspath);
|
|
||||||
return bootWarProvider;
|
return bootWarProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ import org.springframework.util.Assert;
|
||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
@CacheableTask
|
@CacheableTask
|
||||||
public class ProcessTestAot extends AbstractAot {
|
public abstract class ProcessTestAot extends AbstractAot {
|
||||||
|
|
||||||
private @Nullable FileCollection classpathRoots;
|
private @Nullable FileCollection classpathRoots;
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ public abstract class BuildInfoProperties implements Serializable {
|
||||||
|
|
||||||
private final SetProperty<String> excludes;
|
private final SetProperty<String> excludes;
|
||||||
|
|
||||||
private final Supplier<String> creationTime = () -> DateTimeFormatter.ISO_INSTANT.format(Instant.now());
|
private final Supplier<@Nullable String> creationTime = () -> DateTimeFormatter.ISO_INSTANT.format(Instant.now());
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public BuildInfoProperties(Project project, SetProperty<String> excludes) {
|
public BuildInfoProperties(Project project, SetProperty<String> excludes) {
|
||||||
|
@ -143,14 +143,18 @@ public abstract class BuildInfoProperties implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> @Nullable T getIfNotExcluded(Property<T> property, String name) {
|
private <T> @Nullable T getIfNotExcluded(Property<T> property, String name) {
|
||||||
return getIfNotExcluded(property, name, () -> null);
|
Supplier<@Nullable T> supplier = () -> null;
|
||||||
|
return getIfNotExcluded(property, name, supplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> @Nullable T getIfNotExcluded(Property<T> property, String name, Supplier<T> defaultValue) {
|
private <T> @Nullable T getIfNotExcluded(Property<T> property, String name, Supplier<@Nullable T> defaultValue) {
|
||||||
if (this.excludes.getOrElse(Collections.emptySet()).contains(name)) {
|
if (this.excludes.getOrElse(Collections.emptySet()).contains(name)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return property.getOrElse(defaultValue.get());
|
if (property.isPresent()) {
|
||||||
|
return property.get();
|
||||||
|
}
|
||||||
|
return defaultValue.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> coerceToStringValues(Map<String, Object> input) {
|
private Map<String, String> coerceToStringValues(Map<String, Object> input) {
|
||||||
|
@ -159,7 +163,9 @@ public abstract class BuildInfoProperties implements Serializable {
|
||||||
if (value instanceof Provider<?> provider) {
|
if (value instanceof Provider<?> provider) {
|
||||||
value = provider.getOrNull();
|
value = provider.getOrNull();
|
||||||
}
|
}
|
||||||
output.put(key, (value != null) ? value.toString() : null);
|
if (value != null) {
|
||||||
|
output.put(key, value.toString());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
@ -167,7 +173,12 @@ public abstract class BuildInfoProperties implements Serializable {
|
||||||
private Map<String, Object> applyExclusions(Map<String, Object> input) {
|
private Map<String, Object> applyExclusions(Map<String, Object> input) {
|
||||||
Map<String, Object> output = new HashMap<>();
|
Map<String, Object> output = new HashMap<>();
|
||||||
Set<String> exclusions = this.excludes.getOrElse(Collections.emptySet());
|
Set<String> exclusions = this.excludes.getOrElse(Collections.emptySet());
|
||||||
input.forEach((key, value) -> output.put(key, (!exclusions.contains(key)) ? value : null));
|
input.forEach((key, value) -> {
|
||||||
|
boolean isExcluded = exclusions.contains(key);
|
||||||
|
if (!isExcluded) {
|
||||||
|
output.put(key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,6 @@ import org.gradle.api.tasks.Nested;
|
||||||
import org.gradle.api.tasks.Optional;
|
import org.gradle.api.tasks.Optional;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.boot.loader.tools.LoaderImplementation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Spring Boot "fat" archive task.
|
* A Spring Boot "fat" archive task.
|
||||||
*
|
*
|
||||||
|
@ -137,15 +135,6 @@ public interface BootArchive extends Task {
|
||||||
*/
|
*/
|
||||||
void resolvedArtifacts(Provider<Set<ResolvedArtifactResult>> resolvedArtifacts);
|
void resolvedArtifacts(Provider<Set<ResolvedArtifactResult>> resolvedArtifacts);
|
||||||
|
|
||||||
/**
|
|
||||||
* The loader implementation that should be used with the archive.
|
|
||||||
* @return the loader implementation
|
|
||||||
* @since 3.2.0
|
|
||||||
*/
|
|
||||||
@Input
|
|
||||||
@Optional
|
|
||||||
Property<LoaderImplementation> getLoaderImplementation();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the JAR tools should be included as a dependency in the layered
|
* Returns whether the JAR tools should be included as a dependency in the layered
|
||||||
* archive.
|
* archive.
|
||||||
|
|
|
@ -22,32 +22,24 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.gradle.api.file.ConfigurableFilePermissions;
|
import org.gradle.api.file.ConfigurableFilePermissions;
|
||||||
import org.gradle.api.file.CopySpec;
|
import org.gradle.api.file.CopySpec;
|
||||||
import org.gradle.api.file.FileCopyDetails;
|
import org.gradle.api.file.FileCopyDetails;
|
||||||
import org.gradle.api.file.FileTreeElement;
|
import org.gradle.api.file.FileTreeElement;
|
||||||
import org.gradle.api.file.RelativePath;
|
|
||||||
import org.gradle.api.internal.file.copy.CopyAction;
|
import org.gradle.api.internal.file.copy.CopyAction;
|
||||||
import org.gradle.api.internal.file.copy.CopyActionProcessingStream;
|
|
||||||
import org.gradle.api.internal.file.copy.FileCopyDetailsInternal;
|
|
||||||
import org.gradle.api.java.archives.Attributes;
|
import org.gradle.api.java.archives.Attributes;
|
||||||
import org.gradle.api.java.archives.Manifest;
|
import org.gradle.api.java.archives.Manifest;
|
||||||
import org.gradle.api.provider.Property;
|
import org.gradle.api.provider.Property;
|
||||||
import org.gradle.api.specs.Spec;
|
import org.gradle.api.specs.Spec;
|
||||||
import org.gradle.api.specs.Specs;
|
import org.gradle.api.specs.Specs;
|
||||||
import org.gradle.api.tasks.WorkResult;
|
|
||||||
import org.gradle.api.tasks.bundling.Jar;
|
import org.gradle.api.tasks.bundling.Jar;
|
||||||
import org.gradle.api.tasks.util.PatternSet;
|
import org.gradle.api.tasks.util.PatternSet;
|
||||||
import org.gradle.util.GradleVersion;
|
import org.gradle.util.GradleVersion;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.boot.loader.tools.LoaderImplementation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support class for implementations of {@link BootArchive}.
|
* Support class for implementations of {@link BootArchive}.
|
||||||
*
|
*
|
||||||
|
@ -123,13 +115,11 @@ class BootArchiveSupport {
|
||||||
return (version != null) ? version : "unknown";
|
return (version != null) ? version : "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyAction createCopyAction(Jar jar, ResolvedDependencies resolvedDependencies,
|
CopyAction createCopyAction(Jar jar, ResolvedDependencies resolvedDependencies, boolean supportsSignatureFile) {
|
||||||
LoaderImplementation loaderImplementation, boolean supportsSignatureFile) {
|
return createCopyAction(jar, resolvedDependencies, supportsSignatureFile, null, null);
|
||||||
return createCopyAction(jar, resolvedDependencies, loaderImplementation, supportsSignatureFile, null, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyAction createCopyAction(Jar jar, ResolvedDependencies resolvedDependencies,
|
CopyAction createCopyAction(Jar jar, ResolvedDependencies resolvedDependencies, boolean supportsSignatureFile,
|
||||||
LoaderImplementation loaderImplementation, boolean supportsSignatureFile,
|
|
||||||
@Nullable LayerResolver layerResolver, @Nullable String jarmodeToolsLocation) {
|
@Nullable LayerResolver layerResolver, @Nullable String jarmodeToolsLocation) {
|
||||||
File output = jar.getArchiveFile().get().getAsFile();
|
File output = jar.getArchiveFile().get().getAsFile();
|
||||||
Manifest manifest = jar.getManifest();
|
Manifest manifest = jar.getManifest();
|
||||||
|
@ -145,9 +135,8 @@ class BootArchiveSupport {
|
||||||
String encoding = jar.getMetadataCharset();
|
String encoding = jar.getMetadataCharset();
|
||||||
CopyAction action = new BootZipCopyAction(output, manifest, preserveFileTimestamps, dirPermissions,
|
CopyAction action = new BootZipCopyAction(output, manifest, preserveFileTimestamps, dirPermissions,
|
||||||
filePermissions, includeDefaultLoader, jarmodeToolsLocation, requiresUnpack, exclusions, launchScript,
|
filePermissions, includeDefaultLoader, jarmodeToolsLocation, requiresUnpack, exclusions, launchScript,
|
||||||
librarySpec, compressionResolver, encoding, resolvedDependencies, supportsSignatureFile, layerResolver,
|
librarySpec, compressionResolver, encoding, resolvedDependencies, supportsSignatureFile, layerResolver);
|
||||||
loaderImplementation);
|
return action;
|
||||||
return jar.isReproducibleFileOrder() ? new ReproducibleOrderingCopyAction(action) : action;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable Integer getUnixNumericDirPermissions(CopySpec copySpec) {
|
private @Nullable Integer getUnixNumericDirPermissions(CopySpec copySpec) {
|
||||||
|
@ -164,14 +153,22 @@ class BootArchiveSupport {
|
||||||
return permissions.isPresent() ? permissions.get().toUnixNumeric() : null;
|
return permissions.isPresent() ? permissions.get().toUnixNumeric() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
private @Nullable Integer getDirMode(CopySpec copySpec) {
|
private @Nullable Integer getDirMode(CopySpec copySpec) {
|
||||||
return copySpec.getDirMode();
|
try {
|
||||||
|
return (Integer) copySpec.getClass().getMethod("getDirMode").invoke(copySpec);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new RuntimeException("Failed to get dir mode from CopySpec", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
private @Nullable Integer getFileMode(CopySpec copySpec) {
|
private @Nullable Integer getFileMode(CopySpec copySpec) {
|
||||||
return copySpec.getFileMode();
|
try {
|
||||||
|
return (Integer) copySpec.getClass().getMethod("getFileMode").invoke(copySpec);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new RuntimeException("Failed to get file mode from CopySpec", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isUsingDefaultLoader(Jar jar) {
|
private boolean isUsingDefaultLoader(Jar jar) {
|
||||||
|
@ -234,26 +231,4 @@ class BootArchiveSupport {
|
||||||
details.setRelativePath(details.getRelativeSourcePath());
|
details.setRelativePath(details.getRelativeSourcePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link CopyAction} variant that sorts entries to ensure reproducible ordering.
|
|
||||||
*/
|
|
||||||
private static final class ReproducibleOrderingCopyAction implements CopyAction {
|
|
||||||
|
|
||||||
private final CopyAction delegate;
|
|
||||||
|
|
||||||
private ReproducibleOrderingCopyAction(CopyAction delegate) {
|
|
||||||
this.delegate = delegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WorkResult execute(CopyActionProcessingStream stream) {
|
|
||||||
return this.delegate.execute((action) -> {
|
|
||||||
Map<RelativePath, FileCopyDetailsInternal> detailsByPath = new TreeMap<>();
|
|
||||||
stream.process((details) -> detailsByPath.put(details.getRelativePath(), details));
|
|
||||||
detailsByPath.values().forEach(action::processFile);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ import org.gradle.work.DisableCachingByDefault;
|
||||||
import org.springframework.boot.buildpack.platform.build.BuildRequest;
|
import org.springframework.boot.buildpack.platform.build.BuildRequest;
|
||||||
import org.springframework.boot.buildpack.platform.build.Builder;
|
import org.springframework.boot.buildpack.platform.build.Builder;
|
||||||
import org.springframework.boot.buildpack.platform.build.BuildpackReference;
|
import org.springframework.boot.buildpack.platform.build.BuildpackReference;
|
||||||
|
import org.springframework.boot.buildpack.platform.build.Cache;
|
||||||
import org.springframework.boot.buildpack.platform.build.Creator;
|
import org.springframework.boot.buildpack.platform.build.Creator;
|
||||||
import org.springframework.boot.buildpack.platform.build.PullPolicy;
|
import org.springframework.boot.buildpack.platform.build.PullPolicy;
|
||||||
import org.springframework.boot.buildpack.platform.docker.transport.DockerEngineException;
|
import org.springframework.boot.buildpack.platform.docker.transport.DockerEngineException;
|
||||||
|
@ -460,14 +461,17 @@ public abstract class BootBuildImage extends DefaultTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
private BuildRequest customizeCaches(BuildRequest request) {
|
private BuildRequest customizeCaches(BuildRequest request) {
|
||||||
if (this.buildWorkspace.asCache() != null) {
|
Cache buildWorkspaceCache = this.buildWorkspace.asCache();
|
||||||
request = request.withBuildWorkspace((this.buildWorkspace.asCache()));
|
if (buildWorkspaceCache != null) {
|
||||||
|
request = request.withBuildWorkspace(buildWorkspaceCache);
|
||||||
}
|
}
|
||||||
if (this.buildCache.asCache() != null) {
|
Cache buildCache = this.buildCache.asCache();
|
||||||
request = request.withBuildCache(this.buildCache.asCache());
|
if (buildCache != null) {
|
||||||
|
request = request.withBuildCache(buildCache);
|
||||||
}
|
}
|
||||||
if (this.launchCache.asCache() != null) {
|
Cache launchCache = this.launchCache.asCache();
|
||||||
request = request.withLaunchCache(this.launchCache.asCache());
|
if (launchCache != null) {
|
||||||
|
request = request.withLaunchCache(launchCache);
|
||||||
}
|
}
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,6 @@ import org.gradle.api.tasks.bundling.Jar;
|
||||||
import org.gradle.work.DisableCachingByDefault;
|
import org.gradle.work.DisableCachingByDefault;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.boot.loader.tools.LoaderImplementation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A custom {@link Jar} task that produces a Spring Boot executable jar.
|
* A custom {@link Jar} task that produces a Spring Boot executable jar.
|
||||||
*
|
*
|
||||||
|
@ -145,13 +143,12 @@ public abstract class BootJar extends Jar implements BootArchive {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CopyAction createCopyAction() {
|
protected CopyAction createCopyAction() {
|
||||||
LoaderImplementation loaderImplementation = getLoaderImplementation().getOrElse(LoaderImplementation.DEFAULT);
|
|
||||||
LayerResolver layerResolver = null;
|
LayerResolver layerResolver = null;
|
||||||
if (!isLayeredDisabled()) {
|
if (!isLayeredDisabled()) {
|
||||||
layerResolver = new LayerResolver(this.resolvedDependencies, this.layered, this::isLibrary);
|
layerResolver = new LayerResolver(this.resolvedDependencies, this.layered, this::isLibrary);
|
||||||
}
|
}
|
||||||
String jarmodeToolsLocation = isIncludeJarmodeTools() ? LIB_DIRECTORY : null;
|
String jarmodeToolsLocation = isIncludeJarmodeTools() ? LIB_DIRECTORY : null;
|
||||||
return this.support.createCopyAction(this, this.resolvedDependencies, loaderImplementation, true, layerResolver,
|
return this.support.createCopyAction(this, this.resolvedDependencies, true, layerResolver,
|
||||||
jarmodeToolsLocation);
|
jarmodeToolsLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,6 @@ import org.gradle.api.tasks.bundling.War;
|
||||||
import org.gradle.work.DisableCachingByDefault;
|
import org.gradle.work.DisableCachingByDefault;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.boot.loader.tools.LoaderImplementation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A custom {@link War} task that produces a Spring Boot executable war.
|
* A custom {@link War} task that produces a Spring Boot executable war.
|
||||||
*
|
*
|
||||||
|
@ -119,14 +117,13 @@ public abstract class BootWar extends War implements BootArchive {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CopyAction createCopyAction() {
|
protected CopyAction createCopyAction() {
|
||||||
LoaderImplementation loaderImplementation = getLoaderImplementation().getOrElse(LoaderImplementation.DEFAULT);
|
|
||||||
LayerResolver layerResolver = null;
|
LayerResolver layerResolver = null;
|
||||||
if (!isLayeredDisabled()) {
|
if (!isLayeredDisabled()) {
|
||||||
layerResolver = new LayerResolver(this.resolvedDependencies, this.layered, this::isLibrary);
|
layerResolver = new LayerResolver(this.resolvedDependencies, this.layered, this::isLibrary);
|
||||||
}
|
}
|
||||||
String jarmodeToolsLocation = isIncludeJarmodeTools() ? LIB_DIRECTORY : null;
|
String jarmodeToolsLocation = isIncludeJarmodeTools() ? LIB_DIRECTORY : null;
|
||||||
return this.support.createCopyAction(this, this.resolvedDependencies, loaderImplementation, false,
|
return this.support.createCopyAction(this, this.resolvedDependencies, false, layerResolver,
|
||||||
layerResolver, jarmodeToolsLocation);
|
jarmodeToolsLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isIncludeJarmodeTools() {
|
private boolean isIncludeJarmodeTools() {
|
||||||
|
|
|
@ -22,13 +22,11 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.security.MessageDigest;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HexFormat;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -62,7 +60,6 @@ import org.springframework.boot.loader.tools.JarModeLibrary;
|
||||||
import org.springframework.boot.loader.tools.Layer;
|
import org.springframework.boot.loader.tools.Layer;
|
||||||
import org.springframework.boot.loader.tools.LayersIndex;
|
import org.springframework.boot.loader.tools.LayersIndex;
|
||||||
import org.springframework.boot.loader.tools.LibraryCoordinates;
|
import org.springframework.boot.loader.tools.LibraryCoordinates;
|
||||||
import org.springframework.boot.loader.tools.LoaderImplementation;
|
|
||||||
import org.springframework.boot.loader.tools.NativeImageArgFile;
|
import org.springframework.boot.loader.tools.NativeImageArgFile;
|
||||||
import org.springframework.boot.loader.tools.ReachabilityMetadataProperties;
|
import org.springframework.boot.loader.tools.ReachabilityMetadataProperties;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
@ -111,7 +108,7 @@ class BootZipCopyAction implements CopyAction {
|
||||||
|
|
||||||
private final Function<FileCopyDetails, ZipCompression> compressionResolver;
|
private final Function<FileCopyDetails, ZipCompression> compressionResolver;
|
||||||
|
|
||||||
private final String encoding;
|
private final @Nullable String encoding;
|
||||||
|
|
||||||
private final ResolvedDependencies resolvedDependencies;
|
private final ResolvedDependencies resolvedDependencies;
|
||||||
|
|
||||||
|
@ -119,15 +116,13 @@ class BootZipCopyAction implements CopyAction {
|
||||||
|
|
||||||
private final @Nullable LayerResolver layerResolver;
|
private final @Nullable LayerResolver layerResolver;
|
||||||
|
|
||||||
private final LoaderImplementation loaderImplementation;
|
|
||||||
|
|
||||||
BootZipCopyAction(File output, Manifest manifest, boolean preserveFileTimestamps, @Nullable Integer dirMode,
|
BootZipCopyAction(File output, Manifest manifest, boolean preserveFileTimestamps, @Nullable Integer dirMode,
|
||||||
@Nullable Integer fileMode, boolean includeDefaultLoader, @Nullable String jarmodeToolsLocation,
|
@Nullable Integer fileMode, boolean includeDefaultLoader, @Nullable String jarmodeToolsLocation,
|
||||||
Spec<FileTreeElement> requiresUnpack, Spec<FileTreeElement> exclusions,
|
Spec<FileTreeElement> requiresUnpack, Spec<FileTreeElement> exclusions,
|
||||||
@Nullable LaunchScriptConfiguration launchScript, Spec<FileCopyDetails> librarySpec,
|
@Nullable LaunchScriptConfiguration launchScript, Spec<FileCopyDetails> librarySpec,
|
||||||
Function<FileCopyDetails, ZipCompression> compressionResolver, String encoding,
|
Function<FileCopyDetails, ZipCompression> compressionResolver, @Nullable String encoding,
|
||||||
ResolvedDependencies resolvedDependencies, boolean supportsSignatureFile,
|
ResolvedDependencies resolvedDependencies, boolean supportsSignatureFile,
|
||||||
@Nullable LayerResolver layerResolver, LoaderImplementation loaderImplementation) {
|
@Nullable LayerResolver layerResolver) {
|
||||||
this.output = output;
|
this.output = output;
|
||||||
this.manifest = manifest;
|
this.manifest = manifest;
|
||||||
this.preserveFileTimestamps = preserveFileTimestamps;
|
this.preserveFileTimestamps = preserveFileTimestamps;
|
||||||
|
@ -144,7 +139,6 @@ class BootZipCopyAction implements CopyAction {
|
||||||
this.resolvedDependencies = resolvedDependencies;
|
this.resolvedDependencies = resolvedDependencies;
|
||||||
this.supportsSignatureFile = supportsSignatureFile;
|
this.supportsSignatureFile = supportsSignatureFile;
|
||||||
this.layerResolver = layerResolver;
|
this.layerResolver = layerResolver;
|
||||||
this.loaderImplementation = loaderImplementation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -328,8 +322,7 @@ class BootZipCopyAction implements CopyAction {
|
||||||
// Always write loader entries after META-INF directory (see gh-16698)
|
// Always write loader entries after META-INF directory (see gh-16698)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LoaderZipEntries loaderEntries = new LoaderZipEntries(getTime(), getDirMode(), getFileMode(),
|
LoaderZipEntries loaderEntries = new LoaderZipEntries(getTime(), getDirMode(), getFileMode());
|
||||||
BootZipCopyAction.this.loaderImplementation);
|
|
||||||
this.writtenLoaderEntries = loaderEntries.writeTo(this.out);
|
this.writtenLoaderEntries = loaderEntries.writeTo(this.out);
|
||||||
if (BootZipCopyAction.this.layerResolver != null) {
|
if (BootZipCopyAction.this.layerResolver != null) {
|
||||||
for (String name : this.writtenLoaderEntries.getFiles()) {
|
for (String name : this.writtenLoaderEntries.getFiles()) {
|
||||||
|
@ -390,7 +383,8 @@ class BootZipCopyAction implements CopyAction {
|
||||||
if (classPathIndex != null) {
|
if (classPathIndex != null) {
|
||||||
Set<String> libraryNames = this.writtenLibraries.keySet();
|
Set<String> libraryNames = this.writtenLibraries.keySet();
|
||||||
List<String> lines = libraryNames.stream().map((line) -> "- \"" + line + "\"").toList();
|
List<String> lines = libraryNames.stream().map((line) -> "- \"" + line + "\"").toList();
|
||||||
ZipEntryContentWriter writer = ZipEntryContentWriter.fromLines(BootZipCopyAction.this.encoding, lines);
|
ZipEntryContentWriter writer = ZipEntryContentWriter.fromLines((BootZipCopyAction.this.encoding != null)
|
||||||
|
? BootZipCopyAction.this.encoding : StandardCharsets.UTF_8.name(), lines);
|
||||||
writeEntry(classPathIndex, writer, true);
|
writeEntry(classPathIndex, writer, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -415,7 +409,8 @@ class BootZipCopyAction implements CopyAction {
|
||||||
}
|
}
|
||||||
NativeImageArgFile argFile = new NativeImageArgFile(excludes);
|
NativeImageArgFile argFile = new NativeImageArgFile(excludes);
|
||||||
argFile.writeIfNecessary((lines) -> {
|
argFile.writeIfNecessary((lines) -> {
|
||||||
ZipEntryContentWriter writer = ZipEntryContentWriter.fromLines(BootZipCopyAction.this.encoding, lines);
|
ZipEntryContentWriter writer = ZipEntryContentWriter.fromLines((BootZipCopyAction.this.encoding != null)
|
||||||
|
? BootZipCopyAction.this.encoding : StandardCharsets.UTF_8.name(), lines);
|
||||||
writeEntry(NativeImageArgFile.LOCATION, writer, true);
|
writeEntry(NativeImageArgFile.LOCATION, writer, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -509,9 +504,13 @@ class BootZipCopyAction implements CopyAction {
|
||||||
? details.getPermissions().toUnixNumeric() : getMode(details);
|
? details.getPermissions().toUnixNumeric() : getMode(details);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
private int getMode(FileCopyDetails details) {
|
private int getMode(FileCopyDetails details) {
|
||||||
return details.getMode();
|
try {
|
||||||
|
return (int) details.getClass().getMethod("getMode").invoke(details);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new RuntimeException("Failed to get mode from FileCopyDetails", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -587,36 +586,24 @@ class BootZipCopyAction implements CopyAction {
|
||||||
|
|
||||||
private static final int BUFFER_SIZE = 32 * 1024;
|
private static final int BUFFER_SIZE = 32 * 1024;
|
||||||
|
|
||||||
private final @Nullable MessageDigest messageDigest;
|
private final boolean unpack;
|
||||||
|
|
||||||
private final CRC32 crc = new CRC32();
|
private final CRC32 crc = new CRC32();
|
||||||
|
|
||||||
private long size;
|
private long size;
|
||||||
|
|
||||||
StoredEntryPreparator(InputStream inputStream, boolean unpack) throws IOException {
|
StoredEntryPreparator(InputStream inputStream, boolean unpack) throws IOException {
|
||||||
this.messageDigest = (unpack) ? sha1Digest() : null;
|
this.unpack = unpack;
|
||||||
try (inputStream) {
|
try (inputStream) {
|
||||||
load(inputStream);
|
load(inputStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MessageDigest sha1Digest() {
|
|
||||||
try {
|
|
||||||
return MessageDigest.getInstance("SHA-1");
|
|
||||||
}
|
|
||||||
catch (NoSuchAlgorithmException ex) {
|
|
||||||
throw new IllegalStateException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void load(InputStream inputStream) throws IOException {
|
private void load(InputStream inputStream) throws IOException {
|
||||||
byte[] buffer = new byte[BUFFER_SIZE];
|
byte[] buffer = new byte[BUFFER_SIZE];
|
||||||
int bytesRead;
|
int bytesRead;
|
||||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
this.crc.update(buffer, 0, bytesRead);
|
this.crc.update(buffer, 0, bytesRead);
|
||||||
if (this.messageDigest != null) {
|
|
||||||
this.messageDigest.update(buffer, 0, bytesRead);
|
|
||||||
}
|
|
||||||
this.size += bytesRead;
|
this.size += bytesRead;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -626,8 +613,8 @@ class BootZipCopyAction implements CopyAction {
|
||||||
entry.setCompressedSize(this.size);
|
entry.setCompressedSize(this.size);
|
||||||
entry.setCrc(this.crc.getValue());
|
entry.setCrc(this.crc.getValue());
|
||||||
entry.setMethod(ZipEntry.STORED);
|
entry.setMethod(ZipEntry.STORED);
|
||||||
if (this.messageDigest != null) {
|
if (this.unpack) {
|
||||||
entry.setComment("UNPACK:" + HexFormat.of().formatHex(this.messageDigest.digest()));
|
entry.setComment("UNPACK");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
|
||||||
import org.gradle.api.file.FileTreeElement;
|
import org.gradle.api.file.FileTreeElement;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.boot.loader.tools.LoaderImplementation;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StreamUtils;
|
import org.springframework.util.StreamUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,27 +41,22 @@ import org.springframework.util.StreamUtils;
|
||||||
*/
|
*/
|
||||||
class LoaderZipEntries {
|
class LoaderZipEntries {
|
||||||
|
|
||||||
private final LoaderImplementation loaderImplementation;
|
|
||||||
|
|
||||||
private final @Nullable Long entryTime;
|
private final @Nullable Long entryTime;
|
||||||
|
|
||||||
private final int dirMode;
|
private final int dirMode;
|
||||||
|
|
||||||
private final int fileMode;
|
private final int fileMode;
|
||||||
|
|
||||||
LoaderZipEntries(@Nullable Long entryTime, int dirMode, int fileMode,
|
LoaderZipEntries(@Nullable Long entryTime, int dirMode, int fileMode) {
|
||||||
@Nullable LoaderImplementation loaderImplementation) {
|
|
||||||
this.entryTime = entryTime;
|
this.entryTime = entryTime;
|
||||||
this.dirMode = dirMode;
|
this.dirMode = dirMode;
|
||||||
this.fileMode = fileMode;
|
this.fileMode = fileMode;
|
||||||
this.loaderImplementation = (loaderImplementation != null) ? loaderImplementation
|
|
||||||
: LoaderImplementation.DEFAULT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WrittenEntries writeTo(ZipArchiveOutputStream out) throws IOException {
|
WrittenEntries writeTo(ZipArchiveOutputStream out) throws IOException {
|
||||||
WrittenEntries written = new WrittenEntries();
|
WrittenEntries written = new WrittenEntries();
|
||||||
try (ZipInputStream loaderJar = new ZipInputStream(
|
try (ZipInputStream loaderJar = new ZipInputStream(
|
||||||
getClass().getResourceAsStream("/" + this.loaderImplementation.getJarResourceName()))) {
|
getResourceAsStream("/META-INF/loader/spring-boot-loader.jar"))) {
|
||||||
java.util.zip.ZipEntry entry = loaderJar.getNextEntry();
|
java.util.zip.ZipEntry entry = loaderJar.getNextEntry();
|
||||||
while (entry != null) {
|
while (entry != null) {
|
||||||
if (entry.isDirectory() && !entry.getName().equals("META-INF/")) {
|
if (entry.isDirectory() && !entry.getName().equals("META-INF/")) {
|
||||||
|
@ -78,6 +73,12 @@ class LoaderZipEntries {
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private InputStream getResourceAsStream(String name) {
|
||||||
|
InputStream stream = getClass().getResourceAsStream(name);
|
||||||
|
Assert.state(stream != null, "Resource '%s not found'".formatted(name));
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
private void writeDirectory(ZipArchiveEntry entry, ZipArchiveOutputStream out) throws IOException {
|
private void writeDirectory(ZipArchiveEntry entry, ZipArchiveOutputStream out) throws IOException {
|
||||||
prepareEntry(entry, this.dirMode);
|
prepareEntry(entry, this.dirMode);
|
||||||
out.putArchiveEntry(entry);
|
out.putArchiveEntry(entry);
|
||||||
|
|
|
@ -124,7 +124,7 @@ class PackagingDocumentationTests {
|
||||||
try (JarFile jar = new JarFile(file)) {
|
try (JarFile jar = new JarFile(file)) {
|
||||||
JarEntry entry = jar.getJarEntry("BOOT-INF/lib/jruby-complete-1.7.25.jar");
|
JarEntry entry = jar.getJarEntry("BOOT-INF/lib/jruby-complete-1.7.25.jar");
|
||||||
assertThat(entry).isNotNull();
|
assertThat(entry).isNotNull();
|
||||||
assertThat(entry.getComment()).startsWith("UNPACK:");
|
assertThat(entry.getComment()).isEqualTo("UNPACK");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,6 @@ import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.internal.project.ProjectInternal;
|
|
||||||
import org.gradle.initialization.GradlePropertiesController;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
|
@ -173,11 +171,7 @@ class BuildInfoTests {
|
||||||
|
|
||||||
private Project createProject(String projectName) {
|
private Project createProject(String projectName) {
|
||||||
File projectDir = new File(this.temp, projectName);
|
File projectDir = new File(this.temp, projectName);
|
||||||
Project project = GradleProjectBuilder.builder().withProjectDir(projectDir).withName(projectName).build();
|
return GradleProjectBuilder.builder().withProjectDir(projectDir).withName(projectName).build();
|
||||||
((ProjectInternal) project).getServices()
|
|
||||||
.get(GradlePropertiesController.class)
|
|
||||||
.loadGradlePropertiesFrom(projectDir, false);
|
|
||||||
return project;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private BuildInfo createTask(Project project) {
|
private BuildInfo createTask(Project project) {
|
||||||
|
|
|
@ -108,16 +108,6 @@ abstract class AbstractBootArchiveIntegrationTests {
|
||||||
assertThat(firstHash).isEqualTo(secondHash);
|
assertThat(firstHash).isEqualTo(secondHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestTemplate
|
|
||||||
void classicLoader() throws IOException {
|
|
||||||
assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName).getOutcome())
|
|
||||||
.isEqualTo(TaskOutcome.SUCCESS);
|
|
||||||
File jar = new File(this.gradleBuild.getProjectDir(), "build/libs").listFiles()[0];
|
|
||||||
try (JarFile jarFile = new JarFile(jar)) {
|
|
||||||
assertThat(jarFile.getEntry("org/springframework/boot/loader/LaunchedURLClassLoader.class")).isNotNull();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
void upToDateWhenBuiltTwice() {
|
void upToDateWhenBuiltTwice() {
|
||||||
assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName).getOutcome())
|
assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName).getOutcome())
|
||||||
|
@ -243,15 +233,9 @@ abstract class AbstractBootArchiveIntegrationTests {
|
||||||
.filter((entry) -> !entry.isDirectory())
|
.filter((entry) -> !entry.isDirectory())
|
||||||
.map(JarEntry::getName)
|
.map(JarEntry::getName)
|
||||||
.filter((name) -> name.startsWith(this.libPath));
|
.filter((name) -> name.startsWith(this.libPath));
|
||||||
if (this.gradleBuild.gradleVersionIsLessThan("9.0.0-rc-1")) {
|
|
||||||
assertThat(libEntryNames).containsExactly(this.libPath + "two-1.0.jar",
|
assertThat(libEntryNames).containsExactly(this.libPath + "two-1.0.jar",
|
||||||
this.libPath + "commons-io-2.19.0.jar");
|
this.libPath + "commons-io-2.19.0.jar");
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
assertThat(libEntryNames).containsExactly(this.libPath + "commons-io-2.19.0.jar",
|
|
||||||
this.libPath + "two-1.0.jar");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
|
@ -293,6 +277,7 @@ abstract class AbstractBootArchiveIntegrationTests {
|
||||||
void jarTypeFilteringIsApplied() throws IOException {
|
void jarTypeFilteringIsApplied() throws IOException {
|
||||||
File flatDirRepository = new File(this.gradleBuild.getProjectDir(), "repository");
|
File flatDirRepository = new File(this.gradleBuild.getProjectDir(), "repository");
|
||||||
createDependenciesStarterJar(new File(flatDirRepository, "starter.jar"));
|
createDependenciesStarterJar(new File(flatDirRepository, "starter.jar"));
|
||||||
|
createDependenciesDeveloperToolsJar(new File(flatDirRepository, "devonly.jar"));
|
||||||
createStandardJar(new File(flatDirRepository, "standard.jar"));
|
createStandardJar(new File(flatDirRepository, "standard.jar"));
|
||||||
assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName).getOutcome())
|
assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName).getOutcome())
|
||||||
.isEqualTo(TaskOutcome.SUCCESS);
|
.isEqualTo(TaskOutcome.SUCCESS);
|
||||||
|
@ -669,6 +654,10 @@ abstract class AbstractBootArchiveIntegrationTests {
|
||||||
createJar(location, (attributes) -> attributes.putValue("Spring-Boot-Jar-Type", "dependencies-starter"));
|
createJar(location, (attributes) -> attributes.putValue("Spring-Boot-Jar-Type", "dependencies-starter"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createDependenciesDeveloperToolsJar(File location) throws IOException {
|
||||||
|
createJar(location, (attributes) -> attributes.putValue("Spring-Boot-Jar-Type", "development-tool"));
|
||||||
|
}
|
||||||
|
|
||||||
private void createJar(File location, Consumer<Attributes> attributesConfigurer) throws IOException {
|
private void createJar(File location, Consumer<Attributes> attributesConfigurer) throws IOException {
|
||||||
location.getParentFile().mkdirs();
|
location.getParentFile().mkdirs();
|
||||||
Manifest manifest = new Manifest();
|
Manifest manifest = new Manifest();
|
||||||
|
|
|
@ -27,6 +27,8 @@ import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.nio.file.attribute.PosixFilePermission;
|
import java.nio.file.attribute.PosixFilePermission;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -35,6 +37,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.jar.JarOutputStream;
|
import java.util.jar.JarOutputStream;
|
||||||
|
@ -65,7 +68,6 @@ import org.junit.jupiter.api.io.TempDir;
|
||||||
import org.springframework.boot.gradle.junit.GradleProjectBuilder;
|
import org.springframework.boot.gradle.junit.GradleProjectBuilder;
|
||||||
import org.springframework.boot.loader.tools.DefaultLaunchScript;
|
import org.springframework.boot.loader.tools.DefaultLaunchScript;
|
||||||
import org.springframework.boot.loader.tools.JarModeLibrary;
|
import org.springframework.boot.loader.tools.JarModeLibrary;
|
||||||
import org.springframework.boot.loader.tools.LoaderImplementation;
|
|
||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.util.FileCopyUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
@ -283,17 +285,6 @@ abstract class AbstractBootArchiveTests<T extends Jar & BootArchive> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void loaderIsWrittenToTheRootOfTheJarWhenUsingClassicLoader() throws IOException {
|
|
||||||
this.task.getMainClass().set("com.example.Main");
|
|
||||||
this.task.getLoaderImplementation().set(LoaderImplementation.CLASSIC);
|
|
||||||
executeTask();
|
|
||||||
try (JarFile jarFile = new JarFile(this.task.getArchiveFile().get().getAsFile())) {
|
|
||||||
assertThat(jarFile.getEntry("org/springframework/boot/loader/LaunchedURLClassLoader.class")).isNotNull();
|
|
||||||
assertThat(jarFile.getEntry("org/springframework/boot/loader/")).isNotNull();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void unpackCommentIsAddedToEntryIdentifiedByAPattern() throws IOException {
|
void unpackCommentIsAddedToEntryIdentifiedByAPattern() throws IOException {
|
||||||
this.task.getMainClass().set("com.example.Main");
|
this.task.getMainClass().set("com.example.Main");
|
||||||
|
@ -301,7 +292,7 @@ abstract class AbstractBootArchiveTests<T extends Jar & BootArchive> {
|
||||||
this.task.requiresUnpack("**/one.jar");
|
this.task.requiresUnpack("**/one.jar");
|
||||||
executeTask();
|
executeTask();
|
||||||
try (JarFile jarFile = new JarFile(this.task.getArchiveFile().get().getAsFile())) {
|
try (JarFile jarFile = new JarFile(this.task.getArchiveFile().get().getAsFile())) {
|
||||||
assertThat(jarFile.getEntry(this.libPath + "one.jar").getComment()).startsWith("UNPACK:");
|
assertThat(jarFile.getEntry(this.libPath + "one.jar").getComment()).isEqualTo("UNPACK");
|
||||||
assertThat(jarFile.getEntry(this.libPath + "two.jar").getComment()).isNull();
|
assertThat(jarFile.getEntry(this.libPath + "two.jar").getComment()).isNull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,7 +304,7 @@ abstract class AbstractBootArchiveTests<T extends Jar & BootArchive> {
|
||||||
this.task.requiresUnpack((element) -> element.getName().endsWith("two.jar"));
|
this.task.requiresUnpack((element) -> element.getName().endsWith("two.jar"));
|
||||||
executeTask();
|
executeTask();
|
||||||
try (JarFile jarFile = new JarFile(this.task.getArchiveFile().get().getAsFile())) {
|
try (JarFile jarFile = new JarFile(this.task.getArchiveFile().get().getAsFile())) {
|
||||||
assertThat(jarFile.getEntry(this.libPath + "two.jar").getComment()).startsWith("UNPACK:");
|
assertThat(jarFile.getEntry(this.libPath + "two.jar").getComment()).isEqualTo("UNPACK");
|
||||||
assertThat(jarFile.getEntry(this.libPath + "one.jar").getComment()).isNull();
|
assertThat(jarFile.getEntry(this.libPath + "one.jar").getComment()).isNull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -419,23 +410,46 @@ abstract class AbstractBootArchiveTests<T extends Jar & BootArchive> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void reproducibleOrderingCanBeEnabled() throws IOException {
|
void archiveIsReproducibleByDefault() throws IOException {
|
||||||
this.task.getMainClass().set("com.example.Main");
|
this.task.getMainClass().set("com.example.Main");
|
||||||
this.task.from(newFile("bravo.txt"), newFile("alpha.txt"), newFile("charlie.txt"));
|
this.task.from(newFiles("files/b/bravo.txt", "files/a/alpha.txt", "files/c/charlie.txt"));
|
||||||
this.task.setReproducibleFileOrder(true);
|
|
||||||
executeTask();
|
executeTask();
|
||||||
assertThat(this.task.getArchiveFile().get().getAsFile()).exists();
|
assertThat(this.task.getArchiveFile().get().getAsFile()).exists();
|
||||||
List<String> textFiles = new ArrayList<>();
|
List<String> files = new ArrayList<>();
|
||||||
try (JarFile jarFile = new JarFile(this.task.getArchiveFile().get().getAsFile())) {
|
try (JarFile jarFile = new JarFile(this.task.getArchiveFile().get().getAsFile())) {
|
||||||
Enumeration<JarEntry> entries = jarFile.entries();
|
Enumeration<JarEntry> entries = jarFile.entries();
|
||||||
while (entries.hasMoreElements()) {
|
while (entries.hasMoreElements()) {
|
||||||
JarEntry entry = entries.nextElement();
|
JarEntry entry = entries.nextElement();
|
||||||
if (entry.getName().endsWith(".txt")) {
|
assertThat(entry.getLastModifiedTime().toMillis())
|
||||||
textFiles.add(entry.getName());
|
.isEqualTo(ZipEntryConstants.CONSTANT_TIME_FOR_ZIP_ENTRIES);
|
||||||
|
if (entry.getName().startsWith("files/")) {
|
||||||
|
files.add(entry.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertThat(files).containsExactly("files/", "files/a/", "files/a/alpha.txt", "files/b/", "files/b/bravo.txt",
|
||||||
|
"files/c/", "files/c/charlie.txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void archiveReproducibilityCanBeDisabled() throws IOException {
|
||||||
|
this.task.getMainClass().set("com.example.Main");
|
||||||
|
this.task.from(newFiles("files/b/bravo.txt", "files/a/alpha.txt", "files/c/charlie.txt"));
|
||||||
|
this.task.setPreserveFileTimestamps(true);
|
||||||
|
this.task.setReproducibleFileOrder(false);
|
||||||
|
executeTask();
|
||||||
|
assertThat(this.task.getArchiveFile().get().getAsFile()).exists();
|
||||||
|
try (JarFile jarFile = new JarFile(this.task.getArchiveFile().get().getAsFile())) {
|
||||||
|
Enumeration<JarEntry> entries = jarFile.entries();
|
||||||
|
while (entries.hasMoreElements()) {
|
||||||
|
JarEntry entry = entries.nextElement();
|
||||||
|
if (entry.getName().endsWith(".txt") || entry.getName().startsWith("BOOT-INF/lib/")) {
|
||||||
|
OffsetDateTime lastModifiedTime = entry.getLastModifiedTime().toInstant().atOffset(ZoneOffset.UTC);
|
||||||
|
assertThat(lastModifiedTime)
|
||||||
|
.isNotEqualTo(OffsetDateTime.of(1980, 2, 1, 0, 0, 0, 0, ZoneOffset.UTC));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertThat(textFiles).containsExactly("alpha.txt", "bravo.txt", "charlie.txt");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -675,6 +689,19 @@ abstract class AbstractBootArchiveTests<T extends Jar & BootArchive> {
|
||||||
return entryNames;
|
return entryNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected File newFiles(String... names) throws IOException {
|
||||||
|
File dir = new File(this.temp, UUID.randomUUID().toString());
|
||||||
|
dir.mkdir();
|
||||||
|
List<File> files = new ArrayList<>();
|
||||||
|
for (String name : names) {
|
||||||
|
File file = new File(dir, name);
|
||||||
|
file.getParentFile().mkdirs();
|
||||||
|
file.createNewFile();
|
||||||
|
files.add(file);
|
||||||
|
}
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
protected File newFile(String name) throws IOException {
|
protected File newFile(String name) throws IOException {
|
||||||
File file = new File(this.temp, name);
|
File file = new File(this.temp, name);
|
||||||
file.createNewFile();
|
file.createNewFile();
|
||||||
|
|
|
@ -30,8 +30,8 @@ import org.junit.jupiter.api.io.TempDir;
|
||||||
import org.springframework.boot.buildpack.platform.build.BuildRequest;
|
import org.springframework.boot.buildpack.platform.build.BuildRequest;
|
||||||
import org.springframework.boot.buildpack.platform.build.BuildpackReference;
|
import org.springframework.boot.buildpack.platform.build.BuildpackReference;
|
||||||
import org.springframework.boot.buildpack.platform.build.PullPolicy;
|
import org.springframework.boot.buildpack.platform.build.PullPolicy;
|
||||||
|
import org.springframework.boot.buildpack.platform.docker.ImagePlatform;
|
||||||
import org.springframework.boot.buildpack.platform.docker.type.Binding;
|
import org.springframework.boot.buildpack.platform.docker.type.Binding;
|
||||||
import org.springframework.boot.buildpack.platform.docker.type.ImagePlatform;
|
|
||||||
import org.springframework.boot.buildpack.platform.docker.type.ImageReference;
|
import org.springframework.boot.buildpack.platform.docker.type.ImageReference;
|
||||||
import org.springframework.boot.gradle.junit.GradleProjectBuilder;
|
import org.springframework.boot.gradle.junit.GradleProjectBuilder;
|
||||||
|
|
||||||
|
|
|
@ -66,18 +66,10 @@ class BootJarIntegrationTests extends AbstractBootArchiveIntegrationTests {
|
||||||
copyClasspathApplication();
|
copyClasspathApplication();
|
||||||
BuildResult result = this.gradleBuild.build("launch");
|
BuildResult result = this.gradleBuild.build("launch");
|
||||||
String output = result.getOutput();
|
String output = result.getOutput();
|
||||||
if (this.gradleBuild.gradleVersionIsLessThan("9.0.0-rc-1")) {
|
|
||||||
assertThat(output).containsPattern("1\\. .*classes");
|
assertThat(output).containsPattern("1\\. .*classes");
|
||||||
assertThat(output).containsPattern("2\\. .*library-1.0-SNAPSHOT.jar");
|
assertThat(output).containsPattern("2\\. .*library-1.0-SNAPSHOT.jar");
|
||||||
assertThat(output).containsPattern("3\\. .*commons-lang3-3.9.jar");
|
assertThat(output).containsPattern("3\\. .*commons-lang3-3.9.jar");
|
||||||
assertThat(output).containsPattern("4\\. .*spring-boot-jarmode-tools.*.jar");
|
assertThat(output).containsPattern("4\\. .*spring-boot-jarmode-tools.*.jar");
|
||||||
}
|
|
||||||
else {
|
|
||||||
assertThat(output).containsPattern("1\\. .*classes");
|
|
||||||
assertThat(output).containsPattern("2\\. .*commons-lang3-3.9.jar");
|
|
||||||
assertThat(output).containsPattern("3\\. .*library-1.0-SNAPSHOT.jar");
|
|
||||||
assertThat(output).containsPattern("4\\. .*spring-boot-jarmode-tools.*.jar");
|
|
||||||
}
|
|
||||||
assertThat(output).doesNotContain("5. ");
|
assertThat(output).doesNotContain("5. ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,18 +78,10 @@ class BootJarIntegrationTests extends AbstractBootArchiveIntegrationTests {
|
||||||
copyClasspathApplication();
|
copyClasspathApplication();
|
||||||
BuildResult result = this.gradleBuild.build("launch");
|
BuildResult result = this.gradleBuild.build("launch");
|
||||||
String output = result.getOutput();
|
String output = result.getOutput();
|
||||||
if (this.gradleBuild.gradleVersionIsLessThan("9.0.0-rc-1")) {
|
|
||||||
assertThat(output).containsPattern("1\\. .*classes");
|
assertThat(output).containsPattern("1\\. .*classes");
|
||||||
assertThat(output).containsPattern("2\\. .*spring-boot-jarmode-tools.*.jar");
|
assertThat(output).containsPattern("2\\. .*spring-boot-jarmode-tools.*.jar");
|
||||||
assertThat(output).containsPattern("3\\. .*library-1.0-SNAPSHOT.jar");
|
assertThat(output).containsPattern("3\\. .*library-1.0-SNAPSHOT.jar");
|
||||||
assertThat(output).containsPattern("4\\. .*commons-lang3-3.9.jar");
|
assertThat(output).containsPattern("4\\. .*commons-lang3-3.9.jar");
|
||||||
}
|
|
||||||
else {
|
|
||||||
assertThat(output).containsPattern("1\\. .*classes");
|
|
||||||
assertThat(output).containsPattern("2\\. .*spring-boot-jarmode-tools.*.jar");
|
|
||||||
assertThat(output).containsPattern("3\\. .*commons-lang3-3.9.jar");
|
|
||||||
assertThat(output).containsPattern("4\\. .*library-1.0-SNAPSHOT.jar");
|
|
||||||
}
|
|
||||||
assertThat(output).doesNotContain("5. ");
|
assertThat(output).doesNotContain("5. ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,6 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonView;
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
import com.fasterxml.jackson.core.Versioned;
|
|
||||||
import com.fasterxml.jackson.databind.Module;
|
|
||||||
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
|
|
||||||
import com.sun.jna.Platform;
|
import com.sun.jna.Platform;
|
||||||
import io.spring.gradle.dependencymanagement.DependencyManagementPlugin;
|
import io.spring.gradle.dependencymanagement.DependencyManagementPlugin;
|
||||||
import org.antlr.v4.runtime.Lexer;
|
import org.antlr.v4.runtime.Lexer;
|
||||||
|
@ -39,6 +36,8 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerPluginSupportPlugin;
|
||||||
import org.jetbrains.kotlin.project.model.LanguageSettings;
|
import org.jetbrains.kotlin.project.model.LanguageSettings;
|
||||||
import org.jetbrains.kotlin.tooling.core.KotlinToolingVersion;
|
import org.jetbrains.kotlin.tooling.core.KotlinToolingVersion;
|
||||||
import org.tomlj.Toml;
|
import org.tomlj.Toml;
|
||||||
|
import tools.jackson.core.JsonParser;
|
||||||
|
import tools.jackson.databind.JacksonModule;
|
||||||
|
|
||||||
import org.springframework.asm.ClassVisitor;
|
import org.springframework.asm.ClassVisitor;
|
||||||
import org.springframework.boot.buildpack.platform.build.BuildRequest;
|
import org.springframework.boot.buildpack.platform.build.BuildRequest;
|
||||||
|
@ -103,9 +102,8 @@ public class PluginClasspathGradleBuild extends GradleBuild {
|
||||||
classpath.add(new File(pathOfJarContaining(HttpClientConnectionManager.class)));
|
classpath.add(new File(pathOfJarContaining(HttpClientConnectionManager.class)));
|
||||||
classpath.add(new File(pathOfJarContaining(HttpRequest.class)));
|
classpath.add(new File(pathOfJarContaining(HttpRequest.class)));
|
||||||
classpath.add(new File(pathOfJarContaining(HttpVersionPolicy.class)));
|
classpath.add(new File(pathOfJarContaining(HttpVersionPolicy.class)));
|
||||||
classpath.add(new File(pathOfJarContaining(Module.class)));
|
classpath.add(new File(pathOfJarContaining(JacksonModule.class)));
|
||||||
classpath.add(new File(pathOfJarContaining(Versioned.class)));
|
classpath.add(new File(pathOfJarContaining(JsonParser.class)));
|
||||||
classpath.add(new File(pathOfJarContaining(ParameterNamesModule.class)));
|
|
||||||
classpath.add(new File(pathOfJarContaining("com.github.openjson.JSONObject")));
|
classpath.add(new File(pathOfJarContaining("com.github.openjson.JSONObject")));
|
||||||
classpath.add(new File(pathOfJarContaining(JsonView.class)));
|
classpath.add(new File(pathOfJarContaining(JsonView.class)));
|
||||||
classpath.add(new File(pathOfJarContaining(Platform.class)));
|
classpath.add(new File(pathOfJarContaining(Platform.class)));
|
||||||
|
|
|
@ -21,6 +21,8 @@ plugins {
|
||||||
|
|
||||||
bootJar {
|
bootJar {
|
||||||
mainClass = 'com.example.Application'
|
mainClass = 'com.example.Application'
|
||||||
|
if (GradleVersion.current().compareTo(GradleVersion.version("9.0.0-rc-1")) < 0) {
|
||||||
preserveFileTimestamps = false
|
preserveFileTimestamps = false
|
||||||
reproducibleFileOrder = true
|
reproducibleFileOrder = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ plugins {
|
||||||
|
|
||||||
bootWar {
|
bootWar {
|
||||||
mainClass = 'com.example.Application'
|
mainClass = 'com.example.Application'
|
||||||
|
if (GradleVersion.current().compareTo(GradleVersion.version("9.0.0-rc-1")) < 0) {
|
||||||
preserveFileTimestamps = false
|
preserveFileTimestamps = false
|
||||||
reproducibleFileOrder = true
|
reproducibleFileOrder = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<!-- tag::different-versions[] -->
|
<!-- tag::different-versions[] -->
|
||||||
<properties>
|
<properties>
|
||||||
<slf4j.version>1.7.30</slf4j.version>
|
<slf4j.version>1.7.30</slf4j.version>
|
||||||
<spring-data-releasetrain.version>Moore-SR6</spring-data-releasetrain.version>
|
<spring-data-bom.version>2024.1.10</spring-data-bom.version>
|
||||||
</properties>
|
</properties>
|
||||||
<!-- end::different-versions[] -->
|
<!-- end::different-versions[] -->
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
<!-- Override Spring Data release train provided by Spring Boot -->
|
<!-- Override Spring Data release train provided by Spring Boot -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-releasetrain</artifactId>
|
<artifactId>spring-data-bom</artifactId>
|
||||||
<version>2020.0.0-SR1</version>
|
<version>2024.1.10</version>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
|
@ -67,6 +67,9 @@ include::example$using/different-versions-pom.xml[tags=different-versions]
|
||||||
|
|
||||||
Browse the xref:appendix:dependency-versions/properties.adoc[Dependency Versions Properties] section in the Spring Boot reference for a complete list of dependency version properties.
|
Browse the xref:appendix:dependency-versions/properties.adoc[Dependency Versions Properties] section in the Spring Boot reference for a complete list of dependency version properties.
|
||||||
|
|
||||||
|
WARNING: Each Spring Boot release is designed and tested against a specific set of third-party dependencies.
|
||||||
|
Overriding versions may cause compatibility issues and should be done with care.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[using.import]]
|
[[using.import]]
|
||||||
|
|
|
@ -159,7 +159,7 @@ abstract class AbstractArchiveIntegrationTests {
|
||||||
Optional<JarEntry> match = entries.filter((entry) -> entry.getName().startsWith(prefix))
|
Optional<JarEntry> match = entries.filter((entry) -> entry.getName().startsWith(prefix))
|
||||||
.findFirst();
|
.findFirst();
|
||||||
assertThat(match).as("Name starting with %s", prefix)
|
assertThat(match).as("Name starting with %s", prefix)
|
||||||
.hasValueSatisfying((entry) -> assertThat(entry.getComment()).startsWith("UNPACK:"));
|
.hasValueSatisfying((entry) -> assertThat(entry.getComment()).isEqualTo("UNPACK"));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -37,6 +37,7 @@ import static org.assertj.core.api.Assertions.contentOf;
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Scott Frederick
|
* @author Scott Frederick
|
||||||
|
* @author Moritz Halbritter
|
||||||
*/
|
*/
|
||||||
@ExtendWith(MavenBuildExtension.class)
|
@ExtendWith(MavenBuildExtension.class)
|
||||||
class AotTests {
|
class AotTests {
|
||||||
|
@ -102,6 +103,15 @@ class AotTests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestTemplate
|
||||||
|
void whenAotRunsWithSystemPropertiesSourcesAreGenerated(MavenBuild mavenBuild) {
|
||||||
|
mavenBuild.project("aot-system-properties").goals("package").execute((project) -> {
|
||||||
|
Path aotDirectory = project.toPath().resolve("target/spring-aot/main");
|
||||||
|
assertThat(collectRelativePaths(aotDirectory.resolve("sources")))
|
||||||
|
.contains(Path.of("org", "test", "TestProfileConfiguration__BeanDefinitions.java"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
void whenAotRunsWithJvmArgumentsSourcesAreGenerated(MavenBuild mavenBuild) {
|
void whenAotRunsWithJvmArgumentsSourcesAreGenerated(MavenBuild mavenBuild) {
|
||||||
mavenBuild.project("aot-jvm-arguments").goals("package").execute((project) -> {
|
mavenBuild.project("aot-jvm-arguments").goals("package").execute((project) -> {
|
||||||
|
@ -166,6 +176,17 @@ class AotTests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestTemplate
|
||||||
|
void whenAotRunsWithDevtoolsInClasspathItIsExcluded(MavenBuild mavenBuild) {
|
||||||
|
mavenBuild.project("aot-exclude-devtools").goals("package").execute((project) -> {
|
||||||
|
Path aotDirectory = project.toPath().resolve("target/spring-aot/main");
|
||||||
|
assertThat(aotDirectory).exists();
|
||||||
|
Path sourcesDirectory = aotDirectory.resolve("sources");
|
||||||
|
assertThat(sourcesDirectory).exists();
|
||||||
|
assertThat(collectRelativePaths(sourcesDirectory)).isNotEmpty();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
void whenAotTestRunsSourcesAndResourcesAreGenerated(MavenBuild mavenBuild) {
|
void whenAotTestRunsSourcesAndResourcesAreGenerated(MavenBuild mavenBuild) {
|
||||||
mavenBuild.project("aot-test").goals("test").execute((project) -> {
|
mavenBuild.project("aot-test").goals("test").execute((project) -> {
|
||||||
|
@ -180,6 +201,17 @@ class AotTests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestTemplate
|
||||||
|
void whenTestAotRunsWithDevtoolsInClasspathItIsExcluded(MavenBuild mavenBuild) {
|
||||||
|
mavenBuild.project("aot-test-exclude-devtools").goals("process-test-classes").execute((project) -> {
|
||||||
|
Path aotDirectory = project.toPath().resolve("target/spring-aot/test");
|
||||||
|
assertThat(aotDirectory).exists();
|
||||||
|
Path sourcesDirectory = aotDirectory.resolve("sources");
|
||||||
|
assertThat(sourcesDirectory).exists();
|
||||||
|
assertThat(collectRelativePaths(sourcesDirectory)).isNotEmpty();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
List<Path> collectRelativePaths(Path sourceDirectory) {
|
List<Path> collectRelativePaths(Path sourceDirectory) {
|
||||||
try (Stream<Path> pathStream = Files.walk(sourceDirectory)) {
|
try (Stream<Path> pathStream = Files.walk(sourceDirectory)) {
|
||||||
return pathStream.filter(Files::isRegularFile)
|
return pathStream.filter(Files::isRegularFile)
|
||||||
|
|
|
@ -76,26 +76,6 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestTemplate
|
|
||||||
void whenJarWithClassicLoaderIsRepackagedInPlaceOnlyRepackagedJarIsInstalled(MavenBuild mavenBuild) {
|
|
||||||
mavenBuild.project("jar-with-classic-loader").goals("install").execute((project) -> {
|
|
||||||
File original = new File(project, "target/jar-with-classic-loader-0.0.1.BUILD-SNAPSHOT.jar.original");
|
|
||||||
assertThat(original).isFile();
|
|
||||||
File repackaged = new File(project, "target/jar-with-classic-loader-0.0.1.BUILD-SNAPSHOT.jar");
|
|
||||||
assertThat(launchScript(repackaged)).isEmpty();
|
|
||||||
assertThat(jar(repackaged)).manifest((manifest) -> {
|
|
||||||
manifest.hasMainClass("org.springframework.boot.loader.launch.JarLauncher");
|
|
||||||
manifest.hasStartClass("some.random.Main");
|
|
||||||
manifest.hasAttribute("Not-Used", "Foo");
|
|
||||||
}).hasEntryWithName("org/springframework/boot/loader/launch/JarLauncher.class");
|
|
||||||
assertThat(buildLog(project))
|
|
||||||
.contains("Replacing main artifact " + repackaged + " with repackaged archive,")
|
|
||||||
.contains("The original artifact has been renamed to " + original)
|
|
||||||
.contains("Installing " + repackaged + " to")
|
|
||||||
.doesNotContain("Installing " + original + " to");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
void whenAttachIsDisabledOnlyTheOriginalJarIsInstalled(MavenBuild mavenBuild) {
|
void whenAttachIsDisabledOnlyTheOriginalJarIsInstalled(MavenBuild mavenBuild) {
|
||||||
mavenBuild.project("jar-attach-disabled").goals("install").execute((project) -> {
|
mavenBuild.project("jar-attach-disabled").goals("install").execute((project) -> {
|
||||||
|
@ -196,7 +176,40 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests {
|
||||||
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-context")
|
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-context")
|
||||||
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-core")
|
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-core")
|
||||||
.hasEntryWithNameStartingWith("BOOT-INF/lib/commons-logging")
|
.hasEntryWithNameStartingWith("BOOT-INF/lib/commons-logging")
|
||||||
.doesNotHaveEntryWithName("BOOT-INF/lib/servlet-api-2.5.jar");
|
.doesNotHaveEntryWithNameStartingWith("BOOT-INF/lib/servlet-api-");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestTemplate
|
||||||
|
void whenAnEntryIsOptionalByDefaultDoesNotAppearInTheRepackagedJar(MavenBuild mavenBuild) {
|
||||||
|
mavenBuild.project("jar-optional-default").goals("install").execute((project) -> {
|
||||||
|
File repackaged = new File(project, "target/jar-optional-default-0.0.1.BUILD-SNAPSHOT.jar");
|
||||||
|
assertThat(jar(repackaged)).hasEntryWithNameStartingWith("BOOT-INF/classes/")
|
||||||
|
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-context")
|
||||||
|
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-core")
|
||||||
|
.doesNotHaveEntryWithNameStartingWith("BOOT-INF/lib/log4j-api-");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestTemplate
|
||||||
|
void whenAnEntryIsOptionalAndOptionalsIncludedAppearsInTheRepackagedJar(MavenBuild mavenBuild) {
|
||||||
|
mavenBuild.project("jar-optional-include").goals("install").execute((project) -> {
|
||||||
|
File repackaged = new File(project, "target/jar-optional-include-0.0.1.BUILD-SNAPSHOT.jar");
|
||||||
|
assertThat(jar(repackaged)).hasEntryWithNameStartingWith("BOOT-INF/classes/")
|
||||||
|
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-context")
|
||||||
|
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-core")
|
||||||
|
.hasEntryWithNameStartingWith("BOOT-INF/lib/log4j-api-");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestTemplate
|
||||||
|
void whenAnEntryIsOptionalAndOptionalsExcludedDoesNotAppearInTheRepackagedJar(MavenBuild mavenBuild) {
|
||||||
|
mavenBuild.project("jar-optional-exclude").goals("install").execute((project) -> {
|
||||||
|
File repackaged = new File(project, "target/jar-optional-exclude-0.0.1.BUILD-SNAPSHOT.jar");
|
||||||
|
assertThat(jar(repackaged)).hasEntryWithNameStartingWith("BOOT-INF/classes/")
|
||||||
|
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-context")
|
||||||
|
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-core")
|
||||||
|
.doesNotHaveEntryWithNameStartingWith("BOOT-INF/lib/log4j-api-");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,9 +261,8 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests {
|
||||||
File repackaged = new File(project, "target/jar-exclude-group-0.0.1.BUILD-SNAPSHOT.jar");
|
File repackaged = new File(project, "target/jar-exclude-group-0.0.1.BUILD-SNAPSHOT.jar");
|
||||||
assertThat(jar(repackaged)).hasEntryWithNameStartingWith("BOOT-INF/classes/")
|
assertThat(jar(repackaged)).hasEntryWithNameStartingWith("BOOT-INF/classes/")
|
||||||
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-context")
|
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-context")
|
||||||
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-core")
|
|
||||||
.hasEntryWithNameStartingWith("BOOT-INF/lib/commons-logging")
|
.hasEntryWithNameStartingWith("BOOT-INF/lib/commons-logging")
|
||||||
.doesNotHaveEntryWithName("BOOT-INF/lib/log4j-api-2.4.1.jar");
|
.doesNotHaveEntryWithName("BOOT-INF/lib/log4j-api-");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +400,7 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests {
|
||||||
assertThat(layerIndex.get("application")).contains("BOOT-INF/lib/jar-release-0.0.1.RELEASE.jar",
|
assertThat(layerIndex.get("application")).contains("BOOT-INF/lib/jar-release-0.0.1.RELEASE.jar",
|
||||||
"BOOT-INF/lib/jar-snapshot-0.0.1.BUILD-SNAPSHOT.jar");
|
"BOOT-INF/lib/jar-snapshot-0.0.1.BUILD-SNAPSHOT.jar");
|
||||||
assertThat(layerIndex.get("dependencies"))
|
assertThat(layerIndex.get("dependencies"))
|
||||||
.anyMatch((dependency) -> dependency.startsWith("BOOT-INF/lib/log4j-api-2"));
|
.anyMatch((dependency) -> dependency.startsWith("BOOT-INF/lib/log4j-api-"));
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
// Ignore
|
// Ignore
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>org.springframework.boot.maven.it</groupId>
|
||||||
|
<artifactId>aot-exclude-devtools</artifactId>
|
||||||
|
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>@java.version@</maven.compiler.source>
|
||||||
|
<maven.compiler.target>@java.version@</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>@project.groupId@</groupId>
|
||||||
|
<artifactId>@project.artifactId@</artifactId>
|
||||||
|
<version>@project.version@</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>process-aot</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot</artifactId>
|
||||||
|
<version>@project.version@</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-devtools</artifactId>
|
||||||
|
<version>@project.version@</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-present 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.test;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class SampleApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(SampleApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>org.springframework.boot.maven.it</groupId>
|
||||||
|
<artifactId>aot-system-properties</artifactId>
|
||||||
|
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>@java.version@</maven.compiler.source>
|
||||||
|
<maven.compiler.target>@java.version@</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>@project.groupId@</groupId>
|
||||||
|
<artifactId>@project.artifactId@</artifactId>
|
||||||
|
<version>@project.version@</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>process-aot</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<spring.profiles.active>abc</spring.profiles.active>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot</artifactId>
|
||||||
|
<version>@project.version@</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.servlet</groupId>
|
||||||
|
<artifactId>jakarta.servlet-api</artifactId>
|
||||||
|
<version>@jakarta-servlet.version@</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -14,24 +14,18 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.loader.jar;
|
package org.test;
|
||||||
|
|
||||||
/**
|
import org.springframework.boot.SpringApplication;
|
||||||
* Utilities for dealing with bytes from ZIP files.
|
import org.springframework.context.annotation.Configuration;
|
||||||
*
|
import org.springframework.context.annotation.Import;
|
||||||
* @author Phillip Webb
|
|
||||||
*/
|
|
||||||
final class Bytes {
|
|
||||||
|
|
||||||
private Bytes() {
|
@Configuration(proxyBeanMethods = false)
|
||||||
}
|
@Import(TestProfileConfiguration.class)
|
||||||
|
public class SampleApplication {
|
||||||
|
|
||||||
static long littleEndianValue(byte[] bytes, int offset, int length) {
|
public static void main(String[] args) {
|
||||||
long value = 0;
|
SpringApplication.run(SampleApplication.class, args);
|
||||||
for (int i = length - 1; i >= 0; i--) {
|
|
||||||
value = ((value << 8) | (bytes[offset + i] & 0xFF));
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,18 +14,19 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package smoketest.jersey;
|
package org.test;
|
||||||
|
|
||||||
import org.glassfish.jersey.server.ResourceConfig;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
|
||||||
import org.springframework.stereotype.Component;
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@Profile("abc")
|
||||||
|
class TestProfileConfiguration {
|
||||||
|
|
||||||
@Component
|
@Bean
|
||||||
public class JerseyConfig extends ResourceConfig {
|
public String abc() {
|
||||||
|
return "abc";
|
||||||
public JerseyConfig() {
|
|
||||||
register(Endpoint.class);
|
|
||||||
register(ReverseEndpoint.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>org.springframework.boot.maven.it</groupId>
|
||||||
|
<artifactId>aot-test-exclude-devtools</artifactId>
|
||||||
|
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>@java.version@</maven.compiler.source>
|
||||||
|
<maven.compiler.target>@java.version@</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>@project.groupId@</groupId>
|
||||||
|
<artifactId>@project.artifactId@</artifactId>
|
||||||
|
<version>@project.version@</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>process-test-aot</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot</artifactId>
|
||||||
|
<version>@project.version@</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-devtools</artifactId>
|
||||||
|
<version>@project.version@</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-test</artifactId>
|
||||||
|
<version>@project.version@</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
<version>@junit-jupiter.version@</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-present 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.test;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class SampleApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(SampleApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-present 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.test;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
class SampleApplicationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void contextLoads() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>org.springframework.boot.maven.it</groupId>
|
||||||
|
<artifactId>jar-optional-default</artifactId>
|
||||||
|
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>@java.version@</maven.compiler.source>
|
||||||
|
<maven.compiler.target>@java.version@</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>@project.groupId@</groupId>
|
||||||
|
<artifactId>@project.artifactId@</artifactId>
|
||||||
|
<version>@project.version@</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>repackage</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>@maven-jar-plugin.version@</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-context</artifactId>
|
||||||
|
<version>@spring-framework.version@</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-api</artifactId>
|
||||||
|
<version>@log4j2.version@</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -3,7 +3,7 @@
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.springframework.boot.maven.it</groupId>
|
<groupId>org.springframework.boot.maven.it</groupId>
|
||||||
<artifactId>jar-with-classic-loader</artifactId>
|
<artifactId>jar-optional-exclude</artifactId>
|
||||||
<version>0.0.1.BUILD-SNAPSHOT</version>
|
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
<goal>repackage</goal>
|
<goal>repackage</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<loaderImplementation>CLASSIC</loaderImplementation>
|
<includeOptional>false</includeOptional>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
@ -31,16 +31,6 @@
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
<version>@maven-jar-plugin.version@</version>
|
<version>@maven-jar-plugin.version@</version>
|
||||||
<configuration>
|
|
||||||
<archive>
|
|
||||||
<manifest>
|
|
||||||
<mainClass>some.random.Main</mainClass>
|
|
||||||
</manifest>
|
|
||||||
<manifestEntries>
|
|
||||||
<Not-Used>Foo</Not-Used>
|
|
||||||
</manifestEntries>
|
|
||||||
</archive>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
@ -51,10 +41,10 @@
|
||||||
<version>@spring-framework.version@</version>
|
<version>@spring-framework.version@</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>jakarta.servlet</groupId>
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
<artifactId>jakarta.servlet-api</artifactId>
|
<artifactId>log4j-api</artifactId>
|
||||||
<version>@jakarta-servlet.version@</version>
|
<version>@log4j2.version@</version>
|
||||||
<scope>provided</scope>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
|
@ -14,8 +14,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.docs.howto.jersey.springsecurity;
|
package org.test;
|
||||||
|
|
||||||
class Endpoint {
|
public class SampleApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>org.springframework.boot.maven.it</groupId>
|
||||||
|
<artifactId>jar-optional-include</artifactId>
|
||||||
|
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>@java.version@</maven.compiler.source>
|
||||||
|
<maven.compiler.target>@java.version@</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>@project.groupId@</groupId>
|
||||||
|
<artifactId>@project.artifactId@</artifactId>
|
||||||
|
<version>@project.version@</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>repackage</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<includeOptional>true</includeOptional>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>@maven-jar-plugin.version@</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-context</artifactId>
|
||||||
|
<version>@spring-framework.version@</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-api</artifactId>
|
||||||
|
<version>@log4j2.version@</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -14,8 +14,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.docs.howto.jersey.alongsideanotherwebframework;
|
package org.test;
|
||||||
|
|
||||||
class Endpoint {
|
public class SampleApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -47,7 +47,6 @@ import org.springframework.boot.loader.tools.Layouts.Jar;
|
||||||
import org.springframework.boot.loader.tools.Layouts.None;
|
import org.springframework.boot.loader.tools.Layouts.None;
|
||||||
import org.springframework.boot.loader.tools.Layouts.War;
|
import org.springframework.boot.loader.tools.Layouts.War;
|
||||||
import org.springframework.boot.loader.tools.Libraries;
|
import org.springframework.boot.loader.tools.Libraries;
|
||||||
import org.springframework.boot.loader.tools.LoaderImplementation;
|
|
||||||
import org.springframework.boot.loader.tools.Packager;
|
import org.springframework.boot.loader.tools.Packager;
|
||||||
import org.springframework.boot.loader.tools.layer.CustomLayers;
|
import org.springframework.boot.loader.tools.layer.CustomLayers;
|
||||||
|
|
||||||
|
@ -114,6 +113,13 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo
|
||||||
@Parameter(defaultValue = "false")
|
@Parameter(defaultValue = "false")
|
||||||
public boolean includeSystemScope;
|
public boolean includeSystemScope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Include optional dependencies.
|
||||||
|
* @since 3.5.7
|
||||||
|
*/
|
||||||
|
@Parameter(defaultValue = "false")
|
||||||
|
public boolean includeOptional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Include JAR tools.
|
* Include JAR tools.
|
||||||
* @since 3.3.0
|
* @since 3.3.0
|
||||||
|
@ -142,15 +148,6 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the loader implementation that should be used.
|
|
||||||
* @return the loader implementation or {@code null}
|
|
||||||
* @since 3.2.0
|
|
||||||
*/
|
|
||||||
protected @Nullable LoaderImplementation getLoaderImplementation() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the layout factory that will be used to determine the {@link LayoutType} if
|
* Return the layout factory that will be used to determine the {@link LayoutType} if
|
||||||
* no explicit layout is set.
|
* no explicit layout is set.
|
||||||
|
@ -168,7 +165,6 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo
|
||||||
*/
|
*/
|
||||||
protected <P extends Packager> P getConfiguredPackager(Supplier<P> supplier) {
|
protected <P extends Packager> P getConfiguredPackager(Supplier<P> supplier) {
|
||||||
P packager = supplier.get();
|
P packager = supplier.get();
|
||||||
packager.setLoaderImplementation(getLoaderImplementation());
|
|
||||||
packager.setLayoutFactory(getLayoutFactory());
|
packager.setLayoutFactory(getLayoutFactory());
|
||||||
packager.addMainClassTimeoutWarningListener(new LoggingMainClassTimeoutWarningListener(this::getLog));
|
packager.addMainClassTimeoutWarningListener(new LoggingMainClassTimeoutWarningListener(this::getLog));
|
||||||
packager.setMainClass(this.mainClass);
|
packager.setMainClass(this.mainClass);
|
||||||
|
@ -231,6 +227,9 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo
|
||||||
if (!this.includeSystemScope) {
|
if (!this.includeSystemScope) {
|
||||||
filters.add(new ScopeFilter(null, Artifact.SCOPE_SYSTEM));
|
filters.add(new ScopeFilter(null, Artifact.SCOPE_SYSTEM));
|
||||||
}
|
}
|
||||||
|
if (!this.includeOptional) {
|
||||||
|
filters.add(DependencyFilter.exclude(Artifact::isOptional));
|
||||||
|
}
|
||||||
return filters.toArray(new ArtifactsFilter[0]);
|
return filters.toArray(new ArtifactsFilter[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -39,6 +40,7 @@ import org.apache.maven.toolchain.ToolchainManager;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.boot.loader.tools.FileUtils;
|
import org.springframework.boot.loader.tools.FileUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class to run a Spring Boot application.
|
* Base class to run a Spring Boot application.
|
||||||
|
@ -310,17 +312,20 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
||||||
* @return a {@link RunArguments} defining the JVM arguments
|
* @return a {@link RunArguments} defining the JVM arguments
|
||||||
*/
|
*/
|
||||||
protected RunArguments resolveJvmArguments() {
|
protected RunArguments resolveJvmArguments() {
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
List<@Nullable String> arguments = new ArrayList<>();
|
||||||
if (this.systemPropertyVariables != null) {
|
if (this.systemPropertyVariables != null) {
|
||||||
stringBuilder.append(this.systemPropertyVariables.entrySet()
|
for (Entry<String, String> systemProperty : this.systemPropertyVariables.entrySet()) {
|
||||||
.stream()
|
String argument = SystemPropertyFormatter.format(systemProperty.getKey(), systemProperty.getValue());
|
||||||
.map((e) -> SystemPropertyFormatter.format(e.getKey(), e.getValue()))
|
if (StringUtils.hasText(argument)) {
|
||||||
.collect(Collectors.joining(" ")));
|
arguments.add(argument);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (this.jvmArguments != null) {
|
if (this.jvmArguments != null) {
|
||||||
stringBuilder.append(" ").append(this.jvmArguments);
|
String[] jvmArguments = RunArguments.parseArgs(this.jvmArguments);
|
||||||
|
arguments.addAll(Arrays.asList(jvmArguments));
|
||||||
}
|
}
|
||||||
return new RunArguments(stringBuilder.toString());
|
return new RunArguments(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addJvmArgs(List<String> args) {
|
private void addJvmArgs(List<String> args) {
|
||||||
|
@ -427,21 +432,4 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Format System properties.
|
|
||||||
*/
|
|
||||||
static class SystemPropertyFormatter {
|
|
||||||
|
|
||||||
static String format(@Nullable String key, @Nullable String value) {
|
|
||||||
if (key == null) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if (value == null || value.isEmpty()) {
|
|
||||||
return String.format("-D%s", key);
|
|
||||||
}
|
|
||||||
return String.format("-D%s=\"%s\"", key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ import org.springframework.boot.loader.tools.EntryWriter;
|
||||||
import org.springframework.boot.loader.tools.ImagePackager;
|
import org.springframework.boot.loader.tools.ImagePackager;
|
||||||
import org.springframework.boot.loader.tools.LayoutFactory;
|
import org.springframework.boot.loader.tools.LayoutFactory;
|
||||||
import org.springframework.boot.loader.tools.Libraries;
|
import org.springframework.boot.loader.tools.Libraries;
|
||||||
import org.springframework.boot.loader.tools.LoaderImplementation;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -207,13 +207,6 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
|
||||||
@Parameter
|
@Parameter
|
||||||
private @Nullable LayoutType layout;
|
private @Nullable LayoutType layout;
|
||||||
|
|
||||||
/**
|
|
||||||
* The loader implementation that should be used.
|
|
||||||
* @since 3.2.0
|
|
||||||
*/
|
|
||||||
@Parameter
|
|
||||||
private @Nullable LoaderImplementation loaderImplementation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The layout factory that will be used to create the executable archive if no
|
* The layout factory that will be used to create the executable archive if no
|
||||||
* explicit layout is set. Alternative layouts implementations can be provided by 3rd
|
* explicit layout is set. Alternative layouts implementations can be provided by 3rd
|
||||||
|
@ -237,11 +230,6 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
|
||||||
return this.layout;
|
return this.layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected @Nullable LoaderImplementation getLoaderImplementation() {
|
|
||||||
return this.loaderImplementation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the layout factory that will be used to determine the
|
* Return the layout factory that will be used to determine the
|
||||||
* {@link AbstractPackagerMojo.LayoutType} if no explicit layout is set.
|
* {@link AbstractPackagerMojo.LayoutType} if no explicit layout is set.
|
||||||
|
@ -454,11 +442,12 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void write(ZipEntry jarEntry, EntryWriter entryWriter, TarArchiveOutputStream tar) {
|
private void write(ZipEntry jarEntry, @Nullable EntryWriter entryWriter, TarArchiveOutputStream tar) {
|
||||||
try {
|
try {
|
||||||
TarArchiveEntry tarEntry = convert(jarEntry);
|
TarArchiveEntry tarEntry = convert(jarEntry);
|
||||||
tar.putArchiveEntry(tarEntry);
|
tar.putArchiveEntry(tarEntry);
|
||||||
if (tarEntry.isFile()) {
|
if (tarEntry.isFile()) {
|
||||||
|
Assert.state(entryWriter != null, "'entryWriter' must not be null");
|
||||||
entryWriter.write(tar);
|
entryWriter.write(tar);
|
||||||
}
|
}
|
||||||
tar.closeArchiveEntry();
|
tar.closeArchiveEntry();
|
||||||
|
|
|
@ -21,10 +21,13 @@ import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class to build the command-line arguments of a java process.
|
* Helper class to build the command-line arguments of a java process.
|
||||||
*
|
*
|
||||||
|
@ -57,10 +60,12 @@ final class CommandLineBuilder {
|
||||||
|
|
||||||
CommandLineBuilder withSystemProperties(@Nullable Map<String, String> systemProperties) {
|
CommandLineBuilder withSystemProperties(@Nullable Map<String, String> systemProperties) {
|
||||||
if (systemProperties != null) {
|
if (systemProperties != null) {
|
||||||
systemProperties.entrySet()
|
for (Entry<String, String> systemProperty : systemProperties.entrySet()) {
|
||||||
.stream()
|
String option = SystemPropertyFormatter.format(systemProperty.getKey(), systemProperty.getValue());
|
||||||
.map((e) -> SystemPropertyFormatter.format(e.getKey(), e.getValue()))
|
if (StringUtils.hasText(option)) {
|
||||||
.forEach(this.options::add);
|
this.options.add(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -90,21 +95,4 @@ final class CommandLineBuilder {
|
||||||
return commandLine;
|
return commandLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Format System properties.
|
|
||||||
*/
|
|
||||||
private static final class SystemPropertyFormatter {
|
|
||||||
|
|
||||||
static String format(@Nullable String key, @Nullable String value) {
|
|
||||||
if (key == null) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if (value == null || value.isEmpty()) {
|
|
||||||
return String.format("-D%s", key);
|
|
||||||
}
|
|
||||||
return String.format("-D%s=\"%s\"", key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,11 @@
|
||||||
|
|
||||||
package org.springframework.boot.maven;
|
package org.springframework.boot.maven;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import org.apache.maven.artifact.Artifact;
|
import org.apache.maven.artifact.Artifact;
|
||||||
import org.apache.maven.shared.artifact.filter.collection.AbstractArtifactsFilter;
|
import org.apache.maven.shared.artifact.filter.collection.AbstractArtifactsFilter;
|
||||||
|
@ -81,4 +83,22 @@ public abstract class DependencyFilter extends AbstractArtifactsFilter {
|
||||||
return this.filters;
|
return this.filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new {@link DependencyFilter} the excludes artifacts based on the given
|
||||||
|
* predicate.
|
||||||
|
* @param filter the predicate used to filter the artifacts.
|
||||||
|
* @return a new {@link DependencyFilter} instance
|
||||||
|
* @since 3.5.7
|
||||||
|
*/
|
||||||
|
public static DependencyFilter exclude(Predicate<Artifact> filter) {
|
||||||
|
return new DependencyFilter(Collections.emptyList()) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean filter(Artifact artifact) {
|
||||||
|
return filter.test(artifact);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,8 @@ import org.apache.maven.artifact.Artifact;
|
||||||
*/
|
*/
|
||||||
class JarTypeFilter extends DependencyFilter {
|
class JarTypeFilter extends DependencyFilter {
|
||||||
|
|
||||||
private static final Set<String> EXCLUDED_JAR_TYPES = Collections
|
private static final Set<String> EXCLUDED_JAR_TYPES = Collections.unmodifiableSet(
|
||||||
.unmodifiableSet(new HashSet<>(Arrays.asList("annotation-processor", "dependencies-starter")));
|
new HashSet<>(Arrays.asList("annotation-processor", "dependencies-starter", "development-tool")));
|
||||||
|
|
||||||
JarTypeFilter() {
|
JarTypeFilter() {
|
||||||
super(Collections.emptyList());
|
super(Collections.emptyList());
|
||||||
|
|
|
@ -130,7 +130,7 @@ public class ProcessAotMojo extends AbstractAotMojo {
|
||||||
|
|
||||||
private URL[] getClassPath() throws Exception {
|
private URL[] getClassPath() throws Exception {
|
||||||
File[] directories = new File[] { this.classesDirectory, this.generatedClasses };
|
File[] directories = new File[] { this.classesDirectory, this.generatedClasses };
|
||||||
return getClassPath(directories, new ExcludeTestScopeArtifactFilter());
|
return getClassPath(directories, new ExcludeTestScopeArtifactFilter(), DEVTOOLS_EXCLUDE_FILTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RunArguments resolveArguments() {
|
private RunArguments resolveArguments() {
|
||||||
|
|
|
@ -154,7 +154,7 @@ public class ProcessTestAotMojo extends AbstractAotMojo {
|
||||||
protected URL[] getClassPath(boolean includeJUnitPlatformLauncher) throws Exception {
|
protected URL[] getClassPath(boolean includeJUnitPlatformLauncher) throws Exception {
|
||||||
File[] directories = new File[] { this.testClassesDirectory, this.generatedTestClasses, this.classesDirectory,
|
File[] directories = new File[] { this.testClassesDirectory, this.generatedTestClasses, this.classesDirectory,
|
||||||
this.generatedClasses };
|
this.generatedClasses };
|
||||||
URL[] classPath = getClassPath(directories);
|
URL[] classPath = getClassPath(directories, DEVTOOLS_EXCLUDE_FILTER);
|
||||||
if (!includeJUnitPlatformLauncher || this.project.getArtifactMap()
|
if (!includeJUnitPlatformLauncher || this.project.getArtifactMap()
|
||||||
.containsKey(JUNIT_PLATFORM_GROUP_ID + ":" + JUNIT_PLATFORM_LAUNCHER_ARTIFACT_ID)) {
|
.containsKey(JUNIT_PLATFORM_GROUP_ID + ":" + JUNIT_PLATFORM_LAUNCHER_ARTIFACT_ID)) {
|
||||||
return classPath;
|
return classPath;
|
||||||
|
|
|
@ -27,6 +27,8 @@ import org.apache.maven.plugins.shade.relocation.Relocator;
|
||||||
import org.apache.maven.plugins.shade.resource.ReproducibleResourceTransformer;
|
import org.apache.maven.plugins.shade.resource.ReproducibleResourceTransformer;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension for the <a href="https://maven.apache.org/plugins/maven-shade-plugin/">Maven
|
* Extension for the <a href="https://maven.apache.org/plugins/maven-shade-plugin/">Maven
|
||||||
* shade plugin</a> to allow properties files (e.g. {@literal META-INF/spring.factories})
|
* shade plugin</a> to allow properties files (e.g. {@literal META-INF/spring.factories})
|
||||||
|
@ -88,6 +90,7 @@ public class PropertiesMergingResourceTransformer implements ReproducibleResourc
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyOutputStream(JarOutputStream os) throws IOException {
|
public void modifyOutputStream(JarOutputStream os) throws IOException {
|
||||||
|
Assert.state(this.resource != null, "'resource' must not be null");
|
||||||
JarEntry jarEntry = new JarEntry(this.resource);
|
JarEntry jarEntry = new JarEntry(this.resource);
|
||||||
jarEntry.setTime(this.time);
|
jarEntry.setTime(this.time);
|
||||||
os.putNextEntry(jarEntry);
|
os.putNextEntry(jarEntry);
|
||||||
|
|
|
@ -40,7 +40,6 @@ import org.springframework.boot.loader.tools.DefaultLaunchScript;
|
||||||
import org.springframework.boot.loader.tools.LaunchScript;
|
import org.springframework.boot.loader.tools.LaunchScript;
|
||||||
import org.springframework.boot.loader.tools.LayoutFactory;
|
import org.springframework.boot.loader.tools.LayoutFactory;
|
||||||
import org.springframework.boot.loader.tools.Libraries;
|
import org.springframework.boot.loader.tools.Libraries;
|
||||||
import org.springframework.boot.loader.tools.LoaderImplementation;
|
|
||||||
import org.springframework.boot.loader.tools.Repackager;
|
import org.springframework.boot.loader.tools.Repackager;
|
||||||
import org.springframework.lang.Contract;
|
import org.springframework.lang.Contract;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
@ -170,13 +169,6 @@ public class RepackageMojo extends AbstractPackagerMojo {
|
||||||
@Parameter(property = "spring-boot.repackage.layout")
|
@Parameter(property = "spring-boot.repackage.layout")
|
||||||
private @Nullable LayoutType layout;
|
private @Nullable LayoutType layout;
|
||||||
|
|
||||||
/**
|
|
||||||
* The loader implementation that should be used.
|
|
||||||
* @since 3.2.0
|
|
||||||
*/
|
|
||||||
@Parameter
|
|
||||||
private @Nullable LoaderImplementation loaderImplementation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The layout factory that will be used to create the executable archive if no
|
* The layout factory that will be used to create the executable archive if no
|
||||||
* explicit layout is set. Alternative layouts implementations can be provided by 3rd
|
* explicit layout is set. Alternative layouts implementations can be provided by 3rd
|
||||||
|
@ -201,11 +193,6 @@ public class RepackageMojo extends AbstractPackagerMojo {
|
||||||
return this.layout;
|
return this.layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected @Nullable LoaderImplementation getLoaderImplementation() {
|
|
||||||
return this.loaderImplementation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the layout factory that will be used to determine the
|
* Return the layout factory that will be used to determine the
|
||||||
* {@link AbstractPackagerMojo.LayoutType} if no explicit layout is set.
|
* {@link AbstractPackagerMojo.LayoutType} if no explicit layout is set.
|
||||||
|
|
|
@ -19,7 +19,6 @@ package org.springframework.boot.maven;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import org.codehaus.plexus.util.cli.CommandLineUtils;
|
import org.codehaus.plexus.util.cli.CommandLineUtils;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
@ -39,9 +38,18 @@ class RunArguments {
|
||||||
this(parseArgs(arguments));
|
this(parseArgs(arguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
RunArguments(String[] args) {
|
@SuppressWarnings("NullAway") // Maven can't handle nullable arrays
|
||||||
|
RunArguments(@Nullable String[] args) {
|
||||||
|
this((args != null) ? Arrays.asList(args) : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
RunArguments(@Nullable Iterable<@Nullable String> args) {
|
||||||
if (args != null) {
|
if (args != null) {
|
||||||
Arrays.stream(args).filter(Objects::nonNull).forEach(this.args::add);
|
for (String arg : args) {
|
||||||
|
if (arg != null) {
|
||||||
|
this.args.add(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +61,7 @@ class RunArguments {
|
||||||
return this.args.toArray(new String[0]);
|
return this.args.toArray(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String[] parseArgs(@Nullable String arguments) {
|
static String[] parseArgs(@Nullable String arguments) {
|
||||||
if (arguments == null || arguments.trim().isEmpty()) {
|
if (arguments == null || arguments.trim().isEmpty()) {
|
||||||
return NO_ARGS;
|
return NO_ARGS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,12 +156,12 @@ public class StartMojo extends AbstractRunMojo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("NullAway") // Lambda isn't detected with the correct nullability
|
|
||||||
private void doWaitForSpringApplication(MBeanServerConnection connection)
|
private void doWaitForSpringApplication(MBeanServerConnection connection)
|
||||||
throws MojoExecutionException, MojoFailureException {
|
throws MojoExecutionException, MojoFailureException {
|
||||||
final SpringApplicationAdminClient client = new SpringApplicationAdminClient(connection, this.jmxName);
|
final SpringApplicationAdminClient client = new SpringApplicationAdminClient(connection, this.jmxName);
|
||||||
try {
|
try {
|
||||||
execute(this.wait, this.maxAttempts, () -> (client.isReady() ? true : null));
|
Callable<@Nullable Boolean> isReady = () -> (client.isReady() ? true : null);
|
||||||
|
execute(this.wait, this.maxAttempts, isReady);
|
||||||
}
|
}
|
||||||
catch (ReflectionException ex) {
|
catch (ReflectionException ex) {
|
||||||
throw new MojoExecutionException("Unable to retrieve 'ready' attribute", ex.getCause());
|
throw new MojoExecutionException("Unable to retrieve 'ready' attribute", ex.getCause());
|
||||||
|
|
|
@ -14,21 +14,29 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.loader.launch;
|
package org.springframework.boot.maven;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repackaged {@link org.springframework.boot.loader.PropertiesLauncher}.
|
* Format System properties.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @since 3.2.0
|
* @author Stephane Nicoll
|
||||||
*/
|
*/
|
||||||
public final class PropertiesLauncher {
|
final class SystemPropertyFormatter {
|
||||||
|
|
||||||
private PropertiesLauncher() {
|
private SystemPropertyFormatter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
static String format(@Nullable String key, @Nullable String value) {
|
||||||
org.springframework.boot.loader.PropertiesLauncher.main(args);
|
if (key == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (value == null || value.isEmpty()) {
|
||||||
|
return String.format("-D%s", key);
|
||||||
|
}
|
||||||
|
return String.format("-D%s=%s", key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -76,7 +76,7 @@ class CommandLineBuilderTests {
|
||||||
@Test
|
@Test
|
||||||
void buildWithSystemProperty() {
|
void buildWithSystemProperty() {
|
||||||
assertThat(CommandLineBuilder.forMainClass(CLASS_NAME).withSystemProperties(Map.of("flag", "enabled")).build())
|
assertThat(CommandLineBuilder.forMainClass(CLASS_NAME).withSystemProperties(Map.of("flag", "enabled")).build())
|
||||||
.containsExactly("-Dflag=\"enabled\"", CLASS_NAME);
|
.containsExactly("-Dflag=enabled", CLASS_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-present 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.boot.maven;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.maven.artifact.Artifact;
|
||||||
|
import org.apache.maven.artifact.DefaultArtifact;
|
||||||
|
import org.apache.maven.artifact.handler.ArtifactHandler;
|
||||||
|
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
|
||||||
|
import org.apache.maven.artifact.versioning.VersionRange;
|
||||||
|
import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link DependencyFilter}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class DependencyFilterTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void excludeFiltersBasedOnPredicate() throws ArtifactFilterException {
|
||||||
|
DependencyFilter filter = DependencyFilter.exclude(Artifact::isOptional);
|
||||||
|
ArtifactHandler ah = new DefaultArtifactHandler();
|
||||||
|
VersionRange v = VersionRange.createFromVersion("1.0.0");
|
||||||
|
DefaultArtifact a1 = new DefaultArtifact("com.example", "a1", v, "compile", "jar", null, ah, false);
|
||||||
|
DefaultArtifact a2 = new DefaultArtifact("com.example", "a2", v, "compile", "jar", null, ah, true);
|
||||||
|
DefaultArtifact a3 = new DefaultArtifact("com.example", "a3", v, "compile", "jar", null, ah, false);
|
||||||
|
Set<Artifact> filtered = filter.filter(Set.of(a1, a2, a3));
|
||||||
|
assertThat(filtered).containsExactlyInAnyOrder(a1, a3);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -31,8 +31,8 @@ import org.springframework.boot.buildpack.platform.build.BuildRequest;
|
||||||
import org.springframework.boot.buildpack.platform.build.BuildpackReference;
|
import org.springframework.boot.buildpack.platform.build.BuildpackReference;
|
||||||
import org.springframework.boot.buildpack.platform.build.Cache;
|
import org.springframework.boot.buildpack.platform.build.Cache;
|
||||||
import org.springframework.boot.buildpack.platform.build.PullPolicy;
|
import org.springframework.boot.buildpack.platform.build.PullPolicy;
|
||||||
|
import org.springframework.boot.buildpack.platform.docker.ImagePlatform;
|
||||||
import org.springframework.boot.buildpack.platform.docker.type.Binding;
|
import org.springframework.boot.buildpack.platform.docker.type.Binding;
|
||||||
import org.springframework.boot.buildpack.platform.docker.type.ImagePlatform;
|
|
||||||
import org.springframework.boot.buildpack.platform.docker.type.ImageReference;
|
import org.springframework.boot.buildpack.platform.docker.type.ImageReference;
|
||||||
import org.springframework.boot.buildpack.platform.io.Owner;
|
import org.springframework.boot.buildpack.platform.io.Owner;
|
||||||
import org.springframework.boot.buildpack.platform.io.TarArchive;
|
import org.springframework.boot.buildpack.platform.io.TarArchive;
|
||||||
|
|
|
@ -60,6 +60,11 @@ class JarTypeFilterTests {
|
||||||
assertThat(new JarTypeFilter().filter(createArtifact("annotation-processor"))).isTrue();
|
assertThat(new JarTypeFilter().filter(createArtifact("annotation-processor"))).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void whenArtifactHasDevelopmentToolJarTypeThenItIsExcluded() {
|
||||||
|
assertThat(new JarTypeFilter().filter(createArtifact("development-tool"))).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void whenArtifactHasNoManifestFileThenItIsIncluded() {
|
void whenArtifactHasNoManifestFileThenItIsIncluded() {
|
||||||
assertThat(new JarTypeFilter().filter(createArtifactWithNoManifest())).isFalse();
|
assertThat(new JarTypeFilter().filter(createArtifactWithNoManifest())).isFalse();
|
||||||
|
|
|
@ -18,12 +18,10 @@ package org.springframework.boot.maven;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.boot.maven.AbstractRunMojo.SystemPropertyFormatter;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link AbstractRunMojo.SystemPropertyFormatter}.
|
* Tests for {@link SystemPropertyFormatter}.
|
||||||
*/
|
*/
|
||||||
class SystemPropertyFormatterTests {
|
class SystemPropertyFormatterTests {
|
||||||
|
|
||||||
|
@ -39,7 +37,7 @@ class SystemPropertyFormatterTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void parseKeyWithValue() {
|
void parseKeyWithValue() {
|
||||||
assertThat(SystemPropertyFormatter.format("key1", "value1")).isEqualTo("-Dkey1=\"value1\"");
|
assertThat(SystemPropertyFormatter.format("key1", "value1")).isEqualTo("-Dkey1=value1");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -49,7 +47,7 @@ class SystemPropertyFormatterTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void parseKeyWithOnlySpaces() {
|
void parseKeyWithOnlySpaces() {
|
||||||
assertThat(SystemPropertyFormatter.format("key1", " ")).isEqualTo("-Dkey1=\" \"");
|
assertThat(SystemPropertyFormatter.format("key1", " ")).isEqualTo("-Dkey1= ");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,16 +43,16 @@ dependencies {
|
||||||
checkstyle("com.puppycrawl.tools:checkstyle:${checkstyle.toolVersion}")
|
checkstyle("com.puppycrawl.tools:checkstyle:${checkstyle.toolVersion}")
|
||||||
checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:${javaFormatVersion}")
|
checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:${javaFormatVersion}")
|
||||||
|
|
||||||
implementation(platform("com.fasterxml.jackson:jackson-bom:${jacksonVersion}"))
|
implementation(platform("com.fasterxml.jackson:jackson-bom:${jackson2Version}"))
|
||||||
|
implementation(platform("tools.jackson:jackson-bom:${jacksonVersion}"))
|
||||||
implementation(platform("org.springframework:spring-framework-bom:${springFrameworkVersion}"))
|
implementation(platform("org.springframework:spring-framework-bom:${springFrameworkVersion}"))
|
||||||
implementation("com.fasterxml.jackson.core:jackson-databind")
|
|
||||||
implementation("com.github.node-gradle:gradle-node-plugin:3.5.1")
|
implementation("com.github.node-gradle:gradle-node-plugin:3.5.1")
|
||||||
implementation("com.gradle:develocity-gradle-plugin:3.17.2")
|
implementation("com.gradle:develocity-gradle-plugin:3.17.2")
|
||||||
implementation("com.tngtech.archunit:archunit:1.4.1")
|
implementation("com.tngtech.archunit:archunit:1.4.1")
|
||||||
implementation("commons-codec:commons-codec:${commonsCodecVersion}")
|
implementation("commons-codec:commons-codec:${commonsCodecVersion}")
|
||||||
implementation("de.undercouch.download:de.undercouch.download.gradle.plugin:5.5.0")
|
implementation("de.undercouch.download:de.undercouch.download.gradle.plugin:5.5.0")
|
||||||
implementation("dev.adamko.dokkatoo:dokkatoo-plugin:2.3.1")
|
implementation("dev.adamko.dokkatoo:dokkatoo-plugin:2.3.1")
|
||||||
implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.23.8")
|
implementation("dev.detekt:detekt-gradle-plugin:2.0.0-alpha.0")
|
||||||
implementation("io.spring.gradle.antora:spring-antora-plugin:0.0.1")
|
implementation("io.spring.gradle.antora:spring-antora-plugin:0.0.1")
|
||||||
implementation("io.spring.javaformat:spring-javaformat-gradle-plugin:${javaFormatVersion}")
|
implementation("io.spring.javaformat:spring-javaformat-gradle-plugin:${javaFormatVersion}")
|
||||||
implementation("io.spring.nohttp:nohttp-gradle:0.0.11")
|
implementation("io.spring.nohttp:nohttp-gradle:0.0.11")
|
||||||
|
@ -65,6 +65,7 @@ dependencies {
|
||||||
implementation("org.springframework:spring-web")
|
implementation("org.springframework:spring-web")
|
||||||
implementation("org.yaml:snakeyaml:${snakeYamlVersion}")
|
implementation("org.yaml:snakeyaml:${snakeYamlVersion}")
|
||||||
implementation("io.spring.gradle.nullability:nullability-plugin:${nullabilityPluginVersion}")
|
implementation("io.spring.gradle.nullability:nullability-plugin:${nullabilityPluginVersion}")
|
||||||
|
implementation("tools.jackson.core:jackson-databind")
|
||||||
|
|
||||||
testImplementation(platform("org.junit:junit-bom:${junitJupiterVersion}"))
|
testImplementation(platform("org.junit:junit-bom:${junitJupiterVersion}"))
|
||||||
testImplementation("org.assertj:assertj-core:${assertjVersion}")
|
testImplementation("org.assertj:assertj-core:${assertjVersion}")
|
||||||
|
@ -132,10 +133,6 @@ gradlePlugin {
|
||||||
id = "org.springframework.boot.integration-test"
|
id = "org.springframework.boot.integration-test"
|
||||||
implementationClass = "org.springframework.boot.build.test.IntegrationTestPlugin"
|
implementationClass = "org.springframework.boot.build.test.IntegrationTestPlugin"
|
||||||
}
|
}
|
||||||
systemTestPlugin {
|
|
||||||
id = "org.springframework.boot.system-test"
|
|
||||||
implementationClass = "org.springframework.boot.build.test.SystemTestPlugin"
|
|
||||||
}
|
|
||||||
mavenPluginPlugin {
|
mavenPluginPlugin {
|
||||||
id = "org.springframework.boot.maven-plugin"
|
id = "org.springframework.boot.maven-plugin"
|
||||||
implementationClass = "org.springframework.boot.build.mavenplugin.MavenPluginPlugin"
|
implementationClass = "org.springframework.boot.build.mavenplugin.MavenPluginPlugin"
|
||||||
|
@ -152,10 +149,22 @@ gradlePlugin {
|
||||||
id = "org.springframework.boot.starter"
|
id = "org.springframework.boot.starter"
|
||||||
implementationClass = "org.springframework.boot.build.starters.StarterPlugin"
|
implementationClass = "org.springframework.boot.build.starters.StarterPlugin"
|
||||||
}
|
}
|
||||||
|
systemTestPlugin {
|
||||||
|
id = "org.springframework.boot.system-test"
|
||||||
|
implementationClass = "org.springframework.boot.build.test.SystemTestPlugin"
|
||||||
|
}
|
||||||
|
testAutoConfigurationPlugin {
|
||||||
|
id = "org.springframework.boot.test-auto-configuration"
|
||||||
|
implementationClass = "org.springframework.boot.build.test.autoconfigure.TestAutoConfigurationPlugin"
|
||||||
|
}
|
||||||
testFailuresPlugin {
|
testFailuresPlugin {
|
||||||
id = "org.springframework.boot.test-failures"
|
id = "org.springframework.boot.test-failures"
|
||||||
implementationClass = "org.springframework.boot.build.testing.TestFailuresPlugin"
|
implementationClass = "org.springframework.boot.build.testing.TestFailuresPlugin"
|
||||||
}
|
}
|
||||||
|
testSlicePlugin {
|
||||||
|
id = "org.springframework.boot.test-slice"
|
||||||
|
implementationClass = "org.springframework.boot.build.test.autoconfigure.TestSlicePlugin"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,11 @@
|
||||||
<module name="io.spring.javaformat.checkstyle.SpringChecks">
|
<module name="io.spring.javaformat.checkstyle.SpringChecks">
|
||||||
<property name="excludes" value="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocPackageCheck" />
|
<property name="excludes" value="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocPackageCheck" />
|
||||||
</module>
|
</module>
|
||||||
|
<module name="com.puppycrawl.tools.checkstyle.TreeWalker">
|
||||||
|
<module name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck">
|
||||||
|
<property name="regexp" value="true" />
|
||||||
|
<property name="illegalPkgs"
|
||||||
|
value="^com\.fasterxml\.jackson(?!\.annotation).*" />
|
||||||
|
</module>
|
||||||
|
</module>
|
||||||
</module>
|
</module>
|
|
@ -17,8 +17,6 @@
|
||||||
package org.springframework.boot.build;
|
package org.springframework.boot.build;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UncheckedIOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -26,7 +24,6 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.github.gradle.node.NodeExtension;
|
import com.github.gradle.node.NodeExtension;
|
||||||
import com.github.gradle.node.npm.task.NpmInstallTask;
|
import com.github.gradle.node.npm.task.NpmInstallTask;
|
||||||
import io.spring.gradle.antora.GenerateAntoraYmlPlugin;
|
import io.spring.gradle.antora.GenerateAntoraYmlPlugin;
|
||||||
|
@ -44,6 +41,7 @@ import org.gradle.api.provider.Provider;
|
||||||
import org.gradle.api.tasks.Copy;
|
import org.gradle.api.tasks.Copy;
|
||||||
import org.gradle.api.tasks.TaskContainer;
|
import org.gradle.api.tasks.TaskContainer;
|
||||||
import org.gradle.api.tasks.TaskProvider;
|
import org.gradle.api.tasks.TaskProvider;
|
||||||
|
import tools.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
import org.springframework.boot.build.antora.AntoraAsciidocAttributes;
|
import org.springframework.boot.build.antora.AntoraAsciidocAttributes;
|
||||||
import org.springframework.boot.build.antora.GenerateAntoraPlaybook;
|
import org.springframework.boot.build.antora.GenerateAntoraPlaybook;
|
||||||
|
@ -198,7 +196,6 @@ public class AntoraConventions {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getUiBundleUrl(Project project) {
|
private String getUiBundleUrl(Project project) {
|
||||||
try {
|
|
||||||
File packageJson = project.getRootProject().file("antora/package.json");
|
File packageJson = project.getRootProject().file("antora/package.json");
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
Map<?, ?> json = objectMapper.readerFor(Map.class).readValue(packageJson);
|
Map<?, ?> json = objectMapper.readerFor(Map.class).readValue(packageJson);
|
||||||
|
@ -207,10 +204,6 @@ public class AntoraConventions {
|
||||||
Assert.state(StringUtils.hasText(url.toString()), "package.json has not ui-bundle-url config");
|
Assert.state(StringUtils.hasText(url.toString()), "package.json has not ui-bundle-url config");
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
|
||||||
throw new UncheckedIOException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureNodeExtension(Project project, NodeExtension nodeExtension) {
|
private void configureNodeExtension(Project project, NodeExtension nodeExtension) {
|
||||||
nodeExtension.getWorkDir().set(project.getLayout().getBuildDirectory().dir(".gradle/nodejs"));
|
nodeExtension.getWorkDir().set(project.getLayout().getBuildDirectory().dir(".gradle/nodejs"));
|
||||||
|
|
|
@ -20,9 +20,9 @@ import java.net.URI;
|
||||||
|
|
||||||
import dev.adamko.dokkatoo.DokkatooExtension;
|
import dev.adamko.dokkatoo.DokkatooExtension;
|
||||||
import dev.adamko.dokkatoo.formats.DokkatooHtmlPlugin;
|
import dev.adamko.dokkatoo.formats.DokkatooHtmlPlugin;
|
||||||
import io.gitlab.arturbosch.detekt.Detekt;
|
import dev.detekt.gradle.Detekt;
|
||||||
import io.gitlab.arturbosch.detekt.DetektPlugin;
|
import dev.detekt.gradle.extensions.DetektExtension;
|
||||||
import io.gitlab.arturbosch.detekt.extensions.DetektExtension;
|
import dev.detekt.gradle.plugin.DetektPlugin;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.tasks.SourceSet;
|
import org.gradle.api.tasks.SourceSet;
|
||||||
import org.gradle.api.tasks.SourceSetContainer;
|
import org.gradle.api.tasks.SourceSetContainer;
|
||||||
|
@ -76,6 +76,7 @@ class KotlinConventions {
|
||||||
|
|
||||||
private void configureDokkatoo(Project project) {
|
private void configureDokkatoo(Project project) {
|
||||||
DokkatooExtension dokkatoo = project.getExtensions().getByType(DokkatooExtension.class);
|
DokkatooExtension dokkatoo = project.getExtensions().getByType(DokkatooExtension.class);
|
||||||
|
dokkatoo.getVersions().getJetbrainsDokka().set("2.1.0-Beta");
|
||||||
dokkatoo.getDokkatooSourceSets().configureEach((sourceSet) -> {
|
dokkatoo.getDokkatooSourceSets().configureEach((sourceSet) -> {
|
||||||
if (SourceSet.MAIN_SOURCE_SET_NAME.equals(sourceSet.getName())) {
|
if (SourceSet.MAIN_SOURCE_SET_NAME.equals(sourceSet.getName())) {
|
||||||
sourceSet.getSourceRoots().setFrom(project.file("src/main/kotlin"));
|
sourceSet.getSourceRoots().setFrom(project.file("src/main/kotlin"));
|
||||||
|
@ -103,7 +104,9 @@ class KotlinConventions {
|
||||||
project.getPlugins().apply(DetektPlugin.class);
|
project.getPlugins().apply(DetektPlugin.class);
|
||||||
DetektExtension detekt = project.getExtensions().getByType(DetektExtension.class);
|
DetektExtension detekt = project.getExtensions().getByType(DetektExtension.class);
|
||||||
detekt.getConfig().setFrom(project.getRootProject().file("config/detekt/config.yml"));
|
detekt.getConfig().setFrom(project.getRootProject().file("config/detekt/config.yml"));
|
||||||
project.getTasks().withType(Detekt.class).configureEach((task) -> task.setJvmTarget(JVM_TARGET.getTarget()));
|
project.getTasks()
|
||||||
|
.withType(Detekt.class)
|
||||||
|
.configureEach((task) -> task.getJvmTarget().set(JVM_TARGET.getTarget()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,10 +162,9 @@ public class AntoraAsciidocAttributes {
|
||||||
attributes.put("version-native-build-tools", (String) this.projectProperties.get("nativeBuildToolsVersion"));
|
attributes.put("version-native-build-tools", (String) this.projectProperties.get("nativeBuildToolsVersion"));
|
||||||
attributes.put("version-graal", (String) this.projectProperties.get("graalVersion"));
|
attributes.put("version-graal", (String) this.projectProperties.get("graalVersion"));
|
||||||
addDependencyVersion(attributes, "jackson-annotations", "com.fasterxml.jackson.core:jackson-annotations");
|
addDependencyVersion(attributes, "jackson-annotations", "com.fasterxml.jackson.core:jackson-annotations");
|
||||||
addDependencyVersion(attributes, "jackson-core", "com.fasterxml.jackson.core:jackson-core");
|
addDependencyVersion(attributes, "jackson-core", "tools.jackson.core:jackson-core");
|
||||||
addDependencyVersion(attributes, "jackson-databind", "com.fasterxml.jackson.core:jackson-databind");
|
addDependencyVersion(attributes, "jackson-databind", "tools.jackson.core:jackson-databind");
|
||||||
addDependencyVersion(attributes, "jackson-dataformat-xml",
|
addDependencyVersion(attributes, "jackson-dataformat-xml", "tools.jackson.dataformat:jackson-dataformat-xml");
|
||||||
"com.fasterxml.jackson.dataformat:jackson-dataformat-xml");
|
|
||||||
addSpringDataDependencyVersion(attributes, internal, "spring-data-commons");
|
addSpringDataDependencyVersion(attributes, internal, "spring-data-commons");
|
||||||
addSpringDataDependencyVersion(attributes, internal, "spring-data-couchbase");
|
addSpringDataDependencyVersion(attributes, internal, "spring-data-couchbase");
|
||||||
addSpringDataDependencyVersion(attributes, internal, "spring-data-cassandra");
|
addSpringDataDependencyVersion(attributes, internal, "spring-data-cassandra");
|
||||||
|
|
|
@ -80,6 +80,13 @@ final class ArchitectureRules {
|
||||||
|
|
||||||
private static final String AUTOCONFIGURATION_ANNOTATION = "org.springframework.boot.autoconfigure.AutoConfiguration";
|
private static final String AUTOCONFIGURATION_ANNOTATION = "org.springframework.boot.autoconfigure.AutoConfiguration";
|
||||||
|
|
||||||
|
private static final String TEST_AUTOCONFIGURATION_ANNOTATION = "org.springframework.boot.test.autoconfigure.TestAutoConfiguration";
|
||||||
|
|
||||||
|
private static final Predicate<JavaPackage> NULL_MARKED_PACKAGE_FILTER = (candidate) -> !List
|
||||||
|
.of("org.springframework.boot.cli.json", "org.springframework.boot.configurationmetadata.json",
|
||||||
|
"org.springframework.boot.configurationprocessor.json")
|
||||||
|
.contains(candidate.getName());
|
||||||
|
|
||||||
private ArchitectureRules() {
|
private ArchitectureRules() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +119,7 @@ final class ArchitectureRules {
|
||||||
rules.add(allConfigurationPropertiesBindingBeanMethodsShouldBeStatic());
|
rules.add(allConfigurationPropertiesBindingBeanMethodsShouldBeStatic());
|
||||||
rules.add(autoConfigurationClassesShouldBePublicAndFinal());
|
rules.add(autoConfigurationClassesShouldBePublicAndFinal());
|
||||||
rules.add(autoConfigurationClassesShouldHaveNoPublicMembers());
|
rules.add(autoConfigurationClassesShouldHaveNoPublicMembers());
|
||||||
|
rules.add(testAutoConfigurationClassesShouldBePackagePrivateAndFinal());
|
||||||
return List.copyOf(rules);
|
return List.copyOf(rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +138,12 @@ final class ArchitectureRules {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ArchRule allPackagesShouldBeFreeOfTangles() {
|
private static ArchRule allPackagesShouldBeFreeOfTangles() {
|
||||||
return SlicesRuleDefinition.slices().matching("(**)").should().beFreeOfCycles();
|
return SlicesRuleDefinition.slices()
|
||||||
|
.matching("(**)")
|
||||||
|
.should()
|
||||||
|
.beFreeOfCycles()
|
||||||
|
.ignoreDependency("org.springframework.boot.env.EnvironmentPostProcessor",
|
||||||
|
"org.springframework.boot.SpringApplication");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ArchRule allBeanPostProcessorBeanMethodsShouldBeStaticAndNotCausePrematureInitialization() {
|
private static ArchRule allBeanPostProcessorBeanMethodsShouldBeStaticAndNotCausePrematureInitialization() {
|
||||||
|
@ -250,7 +263,9 @@ final class ArchitectureRules {
|
||||||
}
|
}
|
||||||
|
|
||||||
static ArchRule packagesShouldBeAnnotatedWithNullMarked() {
|
static ArchRule packagesShouldBeAnnotatedWithNullMarked() {
|
||||||
return ArchRuleDefinition.all(packages()).should(beAnnotatedWithNullMarked()).allowEmptyShould(true);
|
return ArchRuleDefinition.all(packages(NULL_MARKED_PACKAGE_FILTER))
|
||||||
|
.should(beAnnotatedWithNullMarked())
|
||||||
|
.allowEmptyShould(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ArchCondition<? super JavaMethod> notSpecifyOnlyATypeThatIsTheSameAsTheMethodReturnType() {
|
private static ArchCondition<? super JavaMethod> notSpecifyOnlyATypeThatIsTheSameAsTheMethodReturnType() {
|
||||||
|
@ -353,8 +368,7 @@ final class ArchitectureRules {
|
||||||
|
|
||||||
private static ArchRule autoConfigurationClassesShouldBePublicAndFinal() {
|
private static ArchRule autoConfigurationClassesShouldBePublicAndFinal() {
|
||||||
return ArchRuleDefinition.classes()
|
return ArchRuleDefinition.classes()
|
||||||
.that()
|
.that(areRegularAutoConfiguration())
|
||||||
.areAnnotatedWith(AUTOCONFIGURATION_ANNOTATION)
|
|
||||||
.should()
|
.should()
|
||||||
.bePublic()
|
.bePublic()
|
||||||
.andShould()
|
.andShould()
|
||||||
|
@ -365,8 +379,7 @@ final class ArchitectureRules {
|
||||||
private static ArchRule autoConfigurationClassesShouldHaveNoPublicMembers() {
|
private static ArchRule autoConfigurationClassesShouldHaveNoPublicMembers() {
|
||||||
return ArchRuleDefinition.members()
|
return ArchRuleDefinition.members()
|
||||||
.that()
|
.that()
|
||||||
.areDeclaredInClassesThat()
|
.areDeclaredInClassesThat(areRegularAutoConfiguration())
|
||||||
.areAnnotatedWith(AUTOCONFIGURATION_ANNOTATION)
|
|
||||||
.and(areNotDefaultConstructors())
|
.and(areNotDefaultConstructors())
|
||||||
.and(areNotConstants())
|
.and(areNotConstants())
|
||||||
.and(dontOverridePublicMethods())
|
.and(dontOverridePublicMethods())
|
||||||
|
@ -375,6 +388,24 @@ final class ArchitectureRules {
|
||||||
.allowEmptyShould(true);
|
.allowEmptyShould(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ArchRule testAutoConfigurationClassesShouldBePackagePrivateAndFinal() {
|
||||||
|
return ArchRuleDefinition.classes()
|
||||||
|
.that()
|
||||||
|
.areAnnotatedWith(TEST_AUTOCONFIGURATION_ANNOTATION)
|
||||||
|
.should()
|
||||||
|
.bePackagePrivate()
|
||||||
|
.andShould()
|
||||||
|
.haveModifier(JavaModifier.FINAL)
|
||||||
|
.allowEmptyShould(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DescribedPredicate<JavaClass> areRegularAutoConfiguration() {
|
||||||
|
return DescribedPredicate.describe("Regular @AutoConfiguration",
|
||||||
|
(javaClass) -> javaClass.isMetaAnnotatedWith(AUTOCONFIGURATION_ANNOTATION)
|
||||||
|
&& !javaClass.isMetaAnnotatedWith(TEST_AUTOCONFIGURATION_ANNOTATION)
|
||||||
|
&& !javaClass.isAnnotation());
|
||||||
|
}
|
||||||
|
|
||||||
private static DescribedPredicate<? super JavaMember> dontOverridePublicMethods() {
|
private static DescribedPredicate<? super JavaMember> dontOverridePublicMethods() {
|
||||||
OverridesPublicMethod<JavaMember> predicate = new OverridesPublicMethod<>();
|
OverridesPublicMethod<JavaMember> predicate = new OverridesPublicMethod<>();
|
||||||
return DescribedPredicate.describe("don't override public methods", (member) -> !predicate.test(member));
|
return DescribedPredicate.describe("don't override public methods", (member) -> !predicate.test(member));
|
||||||
|
@ -480,11 +511,11 @@ final class ArchitectureRules {
|
||||||
return string + " should be used instead";
|
return string + " should be used instead";
|
||||||
}
|
}
|
||||||
|
|
||||||
static ClassesTransformer<JavaPackage> packages() {
|
static ClassesTransformer<JavaPackage> packages(Predicate<JavaPackage> filter) {
|
||||||
return new AbstractClassesTransformer<>("packages") {
|
return new AbstractClassesTransformer<>("packages") {
|
||||||
@Override
|
@Override
|
||||||
public Iterable<JavaPackage> doTransform(JavaClasses collection) {
|
public Iterable<JavaPackage> doTransform(JavaClasses collection) {
|
||||||
return collection.stream().map(JavaClass::getPackage).collect(Collectors.toSet());
|
return collection.stream().map(JavaClass::getPackage).filter(filter).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.springframework.boot.build.autoconfigure;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.UncheckedIOException;
|
import java.io.UncheckedIOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -54,8 +55,8 @@ public record AutoConfigurationClass(String name, List<String> before, List<Stri
|
||||||
attributes.getOrDefault("afterName", Collections.emptyList()));
|
attributes.getOrDefault("afterName", Collections.emptyList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static AutoConfigurationClass of(File classFile) {
|
public static AutoConfigurationClass of(InputStream input) {
|
||||||
try (FileInputStream input = new FileInputStream(classFile)) {
|
try {
|
||||||
ClassReader classReader = new ClassReader(input);
|
ClassReader classReader = new ClassReader(input);
|
||||||
AutoConfigurationClassVisitor visitor = new AutoConfigurationClassVisitor();
|
AutoConfigurationClassVisitor visitor = new AutoConfigurationClassVisitor();
|
||||||
classReader.accept(visitor, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES);
|
classReader.accept(visitor, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES);
|
||||||
|
@ -66,6 +67,15 @@ public record AutoConfigurationClass(String name, List<String> before, List<Stri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static AutoConfigurationClass of(File classFile) {
|
||||||
|
try (InputStream input = new FileInputStream(classFile)) {
|
||||||
|
return of(input);
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new UncheckedIOException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static final class AutoConfigurationClassVisitor extends ClassVisitor {
|
private static final class AutoConfigurationClassVisitor extends ClassVisitor {
|
||||||
|
|
||||||
private AutoConfigurationClass autoConfigurationClass;
|
private AutoConfigurationClass autoConfigurationClass;
|
||||||
|
|
|
@ -38,7 +38,10 @@ import org.gradle.api.tasks.SkipWhenEmpty;
|
||||||
*/
|
*/
|
||||||
public abstract class AutoConfigurationImportsTask extends DefaultTask {
|
public abstract class AutoConfigurationImportsTask extends DefaultTask {
|
||||||
|
|
||||||
static final String IMPORTS_FILE = "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports";
|
/**
|
||||||
|
* The path of the {@code AutoConfiguration.imports} file.
|
||||||
|
*/
|
||||||
|
public static final String IMPORTS_FILE = "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports";
|
||||||
|
|
||||||
private FileCollection sourceFiles = getProject().getObjects().fileCollection();
|
private FileCollection sourceFiles = getProject().getObjects().fileCollection();
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,7 @@ public abstract class CheckAutoConfigurationClasses extends AutoConfigurationImp
|
||||||
private List<File> classFiles() {
|
private List<File> classFiles() {
|
||||||
List<File> classFiles = new ArrayList<>();
|
List<File> classFiles = new ArrayList<>();
|
||||||
for (File root : this.classpath.getFiles()) {
|
for (File root : this.classpath.getFiles()) {
|
||||||
|
if (root.exists()) {
|
||||||
try (Stream<Path> files = Files.walk(root.toPath())) {
|
try (Stream<Path> files = Files.walk(root.toPath())) {
|
||||||
files.forEach((file) -> {
|
files.forEach((file) -> {
|
||||||
if (Files.isRegularFile(file) && file.getFileName().toString().endsWith(".class")) {
|
if (Files.isRegularFile(file) && file.getFileName().toString().endsWith(".class")) {
|
||||||
|
@ -147,6 +148,7 @@ public abstract class CheckAutoConfigurationClasses extends AutoConfigurationImp
|
||||||
throw new UncheckedIOException(ex);
|
throw new UncheckedIOException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return classFiles;
|
return classFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ import org.gradle.api.tasks.PathSensitive;
|
||||||
import org.gradle.api.tasks.PathSensitivity;
|
import org.gradle.api.tasks.PathSensitivity;
|
||||||
import org.gradle.api.tasks.TaskAction;
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
|
||||||
|
import org.springframework.util.FileSystemUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,6 +67,7 @@ public abstract class DocumentAutoConfigurationClasses extends DefaultTask {
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
void documentAutoConfigurationClasses() throws IOException {
|
void documentAutoConfigurationClasses() throws IOException {
|
||||||
|
FileSystemUtils.deleteRecursively(getOutputDir().getAsFile().get());
|
||||||
List<AutoConfiguration> autoConfigurations = load();
|
List<AutoConfiguration> autoConfigurations = load();
|
||||||
autoConfigurations.forEach(this::writeModuleAdoc);
|
autoConfigurations.forEach(this::writeModuleAdoc);
|
||||||
for (File metadataFile : this.autoConfiguration) {
|
for (File metadataFile : this.autoConfiguration) {
|
||||||
|
|
|
@ -25,10 +25,8 @@ import java.net.URI;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
import com.fasterxml.jackson.annotation.JsonSetter;
|
import tools.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.annotation.Nulls;
|
import tools.jackson.databind.json.JsonMapper;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A resolved bom.
|
* A resolved bom.
|
||||||
|
@ -42,10 +40,9 @@ public record ResolvedBom(Id id, List<ResolvedLibrary> libraries) {
|
||||||
private static final ObjectMapper objectMapper;
|
private static final ObjectMapper objectMapper;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT)
|
objectMapper = JsonMapper.builder()
|
||||||
.setDefaultPropertyInclusion(Include.NON_EMPTY);
|
.changeDefaultPropertyInclusion((value) -> value.withContentInclusion(Include.NON_EMPTY))
|
||||||
mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
|
.build();
|
||||||
objectMapper = mapper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ResolvedBom readFrom(File file) {
|
public static ResolvedBom readFrom(File file) {
|
||||||
|
@ -58,13 +55,8 @@ public record ResolvedBom(Id id, List<ResolvedLibrary> libraries) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(Writer writer) {
|
public void writeTo(Writer writer) {
|
||||||
try {
|
|
||||||
objectMapper.writeValue(writer, this);
|
objectMapper.writeValue(writer, this);
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
|
||||||
throw new UncheckedIOException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public record ResolvedLibrary(String name, String version, String versionProperty, List<Id> managedDependencies,
|
public record ResolvedLibrary(String name, String version, String versionProperty, List<Id> managedDependencies,
|
||||||
List<Bom> importedBoms, Links links) {
|
List<Bom> importedBoms, Links links) {
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.boot.build.bom.bomr;
|
package org.springframework.boot.build.bom.bomr;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import org.gradle.api.Task;
|
import org.gradle.api.Task;
|
||||||
|
@ -24,6 +26,7 @@ import org.gradle.api.artifacts.dsl.RepositoryHandler;
|
||||||
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
|
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
|
||||||
|
|
||||||
import org.springframework.boot.build.bom.BomExtension;
|
import org.springframework.boot.build.bom.BomExtension;
|
||||||
|
import org.springframework.boot.build.bom.Library;
|
||||||
import org.springframework.boot.build.properties.BuildProperties;
|
import org.springframework.boot.build.properties.BuildProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,4 +66,25 @@ public abstract class UpgradeBom extends UpgradeDependencies {
|
||||||
return issueTitle(upgrade) + "\n\nCloses gh-" + issueNumber;
|
return issueTitle(upgrade) + "\n\nCloses gh-" + issueNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void upgradesApplied(List<Upgrade> upgrades) {
|
||||||
|
if (upgrades.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("Upgrade release notes:");
|
||||||
|
System.out.println();
|
||||||
|
for (Upgrade upgrade : upgrades) {
|
||||||
|
Library library = upgrade.toRelease();
|
||||||
|
String releaseNotes = library.getLinkUrl("releaseNotes");
|
||||||
|
if (releaseNotes != null) {
|
||||||
|
System.out.println("* " + releaseNotes + "[" + library.getNameAndVersion() + "]");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.out.println("* " + library.getNameAndVersion());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,12 @@ public abstract class UpgradeDependencies extends DefaultTask {
|
||||||
@Option(option = "libraries", description = "Regular expression that identifies the libraries to upgrade")
|
@Option(option = "libraries", description = "Regular expression that identifies the libraries to upgrade")
|
||||||
public abstract Property<String> getLibraries();
|
public abstract Property<String> getLibraries();
|
||||||
|
|
||||||
|
@Input
|
||||||
|
@Optional
|
||||||
|
@Option(option = "dry-run-upgrades",
|
||||||
|
description = "Whether to perform a dry run that doesn't open issues or change the bom")
|
||||||
|
public abstract Property<Boolean> getDryRun();
|
||||||
|
|
||||||
@Input
|
@Input
|
||||||
abstract ListProperty<String> getRepositoryNames();
|
abstract ListProperty<String> getRepositoryNames();
|
||||||
|
|
||||||
|
@ -112,8 +118,15 @@ public abstract class UpgradeDependencies extends DefaultTask {
|
||||||
List<String> issueLabels = verifyLabels(repository);
|
List<String> issueLabels = verifyLabels(repository);
|
||||||
Milestone milestone = determineMilestone(repository);
|
Milestone milestone = determineMilestone(repository);
|
||||||
List<Upgrade> upgrades = resolveUpgrades(milestone);
|
List<Upgrade> upgrades = resolveUpgrades(milestone);
|
||||||
|
if (!getDryRun().getOrElse(false)) {
|
||||||
applyUpgrades(repository, issueLabels, milestone, upgrades);
|
applyUpgrades(repository, issueLabels, milestone, upgrades);
|
||||||
}
|
}
|
||||||
|
upgradesApplied(upgrades);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void upgradesApplied(List<Upgrade> upgrades) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void applyUpgrades(GitHubRepository repository, List<String> issueLabels, Milestone milestone,
|
private void applyUpgrades(GitHubRepository repository, List<String> issueLabels, Milestone milestone,
|
||||||
List<Upgrade> upgrades) {
|
List<Upgrade> upgrades) {
|
||||||
|
|
|
@ -19,10 +19,8 @@ package org.springframework.boot.build.bom.bomr.github;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
import org.springframework.web.util.DefaultUriBuilderFactory;
|
import org.springframework.web.util.DefaultUriBuilderFactory;
|
||||||
import org.springframework.web.util.UriTemplateHandler;
|
import org.springframework.web.util.UriTemplateHandler;
|
||||||
|
@ -60,9 +58,9 @@ final class StandardGitHub implements GitHub {
|
||||||
return new StandardGitHubRepository(restTemplate);
|
return new StandardGitHubRepository(restTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
@SuppressWarnings({ "deprecation", "removal" })
|
||||||
private RestTemplate createRestTemplate() {
|
private RestTemplate createRestTemplate() {
|
||||||
return new RestTemplate(Collections.singletonList(new MappingJackson2HttpMessageConverter(new ObjectMapper())));
|
return new RestTemplate(Collections.singletonList(new JacksonJsonHttpMessageConverter()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,6 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParseException;
|
|
||||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.gradle.api.file.FileTree;
|
import org.gradle.api.file.FileTree;
|
||||||
import org.gradle.api.file.RegularFileProperty;
|
import org.gradle.api.file.RegularFileProperty;
|
||||||
import org.gradle.api.tasks.InputFiles;
|
import org.gradle.api.tasks.InputFiles;
|
||||||
|
@ -40,6 +37,7 @@ import org.gradle.api.tasks.PathSensitivity;
|
||||||
import org.gradle.api.tasks.SourceTask;
|
import org.gradle.api.tasks.SourceTask;
|
||||||
import org.gradle.api.tasks.TaskAction;
|
import org.gradle.api.tasks.TaskAction;
|
||||||
import org.gradle.api.tasks.VerificationException;
|
import org.gradle.api.tasks.VerificationException;
|
||||||
|
import tools.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link SourceTask} that checks additional Spring configuration metadata files.
|
* {@link SourceTask} that checks additional Spring configuration metadata files.
|
||||||
|
@ -65,7 +63,7 @@ public abstract class CheckAdditionalSpringConfigurationMetadata extends SourceT
|
||||||
}
|
}
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
void check() throws JsonParseException, IOException {
|
void check() throws IOException {
|
||||||
Report report = createReport();
|
Report report = createReport();
|
||||||
File reportFile = getReportLocation().get().getAsFile();
|
File reportFile = getReportLocation().get().getAsFile();
|
||||||
Files.write(reportFile.toPath(), report, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
|
Files.write(reportFile.toPath(), report, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
|
||||||
|
@ -76,7 +74,7 @@ public abstract class CheckAdditionalSpringConfigurationMetadata extends SourceT
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Report createReport() throws IOException, JsonParseException, JsonMappingException {
|
private Report createReport() {
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
Report report = new Report();
|
Report report = new Report();
|
||||||
for (File file : getSource().getFiles()) {
|
for (File file : getSource().getFiles()) {
|
||||||
|
|
|
@ -26,9 +26,6 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParseException;
|
|
||||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.gradle.api.DefaultTask;
|
import org.gradle.api.DefaultTask;
|
||||||
import org.gradle.api.file.RegularFileProperty;
|
import org.gradle.api.file.RegularFileProperty;
|
||||||
import org.gradle.api.provider.ListProperty;
|
import org.gradle.api.provider.ListProperty;
|
||||||
|
@ -40,6 +37,7 @@ import org.gradle.api.tasks.PathSensitivity;
|
||||||
import org.gradle.api.tasks.SourceTask;
|
import org.gradle.api.tasks.SourceTask;
|
||||||
import org.gradle.api.tasks.TaskAction;
|
import org.gradle.api.tasks.TaskAction;
|
||||||
import org.gradle.api.tasks.VerificationException;
|
import org.gradle.api.tasks.VerificationException;
|
||||||
|
import tools.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link SourceTask} that checks {@code spring-configuration-metadata.json} files.
|
* {@link SourceTask} that checks {@code spring-configuration-metadata.json} files.
|
||||||
|
@ -65,7 +63,7 @@ public abstract class CheckSpringConfigurationMetadata extends DefaultTask {
|
||||||
public abstract ListProperty<String> getExclusions();
|
public abstract ListProperty<String> getExclusions();
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
void check() throws JsonParseException, IOException {
|
void check() throws IOException {
|
||||||
Report report = createReport();
|
Report report = createReport();
|
||||||
File reportFile = getReportLocation().get().getAsFile();
|
File reportFile = getReportLocation().get().getAsFile();
|
||||||
Files.write(reportFile.toPath(), report, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
|
Files.write(reportFile.toPath(), report, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
|
||||||
|
@ -76,7 +74,7 @@ public abstract class CheckSpringConfigurationMetadata extends DefaultTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Report createReport() throws IOException, JsonParseException, JsonMappingException {
|
private Report createReport() {
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
File file = getMetadataLocation().get().getAsFile();
|
File file = getMetadataLocation().get().getAsFile();
|
||||||
Report report = new Report(this.projectRoot.relativize(file.toPath()));
|
Report report = new Report(this.projectRoot.relativize(file.toPath()));
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package org.springframework.boot.build.context.properties;
|
package org.springframework.boot.build.context.properties;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
@ -25,7 +24,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import tools.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration properties read from one or more
|
* Configuration properties read from one or more
|
||||||
|
@ -56,7 +55,6 @@ final class ConfigurationProperties {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
static ConfigurationProperties fromFiles(Iterable<File> files) {
|
static ConfigurationProperties fromFiles(Iterable<File> files) {
|
||||||
try {
|
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
List<ConfigurationProperty> properties = new ArrayList<>();
|
List<ConfigurationProperty> properties = new ArrayList<>();
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
|
@ -67,9 +65,5 @@ final class ConfigurationProperties {
|
||||||
}
|
}
|
||||||
return new ConfigurationProperties(properties);
|
return new ConfigurationProperties(properties);
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
|
||||||
throw new RuntimeException("Failed to load configuration metadata", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ public class ConfigurationPropertiesPlugin implements Plugin<Project> {
|
||||||
public static final String CHECK_ADDITIONAL_SPRING_CONFIGURATION_METADATA_TASK_NAME = "checkAdditionalSpringConfigurationMetadata";
|
public static final String CHECK_ADDITIONAL_SPRING_CONFIGURATION_METADATA_TASK_NAME = "checkAdditionalSpringConfigurationMetadata";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the {@link CheckAdditionalSpringConfigurationMetadata} task.
|
* Name of the {@link CheckSpringConfigurationMetadata} task.
|
||||||
*/
|
*/
|
||||||
public static final String CHECK_SPRING_CONFIGURATION_METADATA_TASK_NAME = "checkSpringConfigurationMetadata";
|
public static final String CHECK_SPRING_CONFIGURATION_METADATA_TASK_NAME = "checkSpringConfigurationMetadata";
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,7 @@ public abstract class DocumentConfigurationProperties extends DefaultTask {
|
||||||
private void jsonPrefixes(Config config) {
|
private void jsonPrefixes(Config config) {
|
||||||
config.accept("spring.jackson");
|
config.accept("spring.jackson");
|
||||||
config.accept("spring.gson");
|
config.accept("spring.gson");
|
||||||
|
config.accept("spring.kotlin.serialization");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dataPrefixes(Config config) {
|
private void dataPrefixes(Config config) {
|
||||||
|
@ -129,7 +130,7 @@ public abstract class DocumentConfigurationProperties extends DefaultTask {
|
||||||
config.accept("spring.ldap");
|
config.accept("spring.ldap");
|
||||||
config.accept("spring.mongodb");
|
config.accept("spring.mongodb");
|
||||||
config.accept("spring.neo4j");
|
config.accept("spring.neo4j");
|
||||||
config.accept("spring.dao");
|
config.accept("spring.persistence");
|
||||||
config.accept("spring.data");
|
config.accept("spring.data");
|
||||||
config.accept("spring.datasource");
|
config.accept("spring.datasource");
|
||||||
config.accept("spring.jooq");
|
config.accept("spring.jooq");
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class OptionalDependenciesPlugin implements Plugin<Project> {
|
||||||
@Override
|
@Override
|
||||||
public void apply(Project project) {
|
public void apply(Project project) {
|
||||||
Configuration optional = project.getConfigurations().create("optional");
|
Configuration optional = project.getConfigurations().create("optional");
|
||||||
optional.setCanBeConsumed(false);
|
optional.setCanBeConsumed(true);
|
||||||
optional.setCanBeResolved(false);
|
optional.setCanBeResolved(false);
|
||||||
project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> {
|
project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> {
|
||||||
SourceSetContainer sourceSets = project.getExtensions()
|
SourceSetContainer sourceSets = project.getExtensions()
|
||||||
|
|
|
@ -0,0 +1,233 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025-present 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.boot.build.test.autoconfigure;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask;
|
||||||
|
import org.gradle.api.file.DirectoryProperty;
|
||||||
|
import org.gradle.api.file.FileCollection;
|
||||||
|
import org.gradle.api.file.FileTree;
|
||||||
|
import org.gradle.api.tasks.Classpath;
|
||||||
|
import org.gradle.api.tasks.InputFiles;
|
||||||
|
import org.gradle.api.tasks.OutputDirectory;
|
||||||
|
import org.gradle.api.tasks.PathSensitive;
|
||||||
|
import org.gradle.api.tasks.PathSensitivity;
|
||||||
|
import org.gradle.api.tasks.SkipWhenEmpty;
|
||||||
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
import org.gradle.api.tasks.VerificationException;
|
||||||
|
import org.gradle.language.base.plugins.LifecycleBasePlugin;
|
||||||
|
|
||||||
|
import org.springframework.boot.build.autoconfigure.AutoConfigurationClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task to check the contents of a project's
|
||||||
|
* {@code META-INF/spring/*.AutoConfigure*.imports} files.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public abstract class CheckAutoConfigureImports extends DefaultTask {
|
||||||
|
|
||||||
|
private FileCollection sourceFiles = getProject().getObjects().fileCollection();
|
||||||
|
|
||||||
|
private FileCollection classpath = getProject().getObjects().fileCollection();
|
||||||
|
|
||||||
|
public CheckAutoConfigureImports() {
|
||||||
|
getOutputDirectory().convention(getProject().getLayout().getBuildDirectory().dir(getName()));
|
||||||
|
setGroup(LifecycleBasePlugin.VERIFICATION_GROUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
@InputFiles
|
||||||
|
@SkipWhenEmpty
|
||||||
|
@PathSensitive(PathSensitivity.RELATIVE)
|
||||||
|
public FileTree getSource() {
|
||||||
|
return this.sourceFiles.getAsFileTree()
|
||||||
|
.matching((filter) -> filter.include("META-INF/spring/*.AutoConfigure*.imports"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSource(Object source) {
|
||||||
|
this.sourceFiles = getProject().getObjects().fileCollection().from(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Classpath
|
||||||
|
public FileCollection getClasspath() {
|
||||||
|
return this.classpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClasspath(Object classpath) {
|
||||||
|
this.classpath = getProject().getObjects().fileCollection().from(classpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OutputDirectory
|
||||||
|
public abstract DirectoryProperty getOutputDirectory();
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
void execute() {
|
||||||
|
Map<String, List<String>> allProblems = new TreeMap<>();
|
||||||
|
for (AutoConfigureImports autoConfigureImports : loadImports()) {
|
||||||
|
List<String> problems = new ArrayList<>();
|
||||||
|
if (!find(autoConfigureImports.annotationName)) {
|
||||||
|
problems.add("Annotation '%s' was not found".formatted(autoConfigureImports.annotationName));
|
||||||
|
}
|
||||||
|
for (String imported : autoConfigureImports.imports) {
|
||||||
|
String importedClassName = imported;
|
||||||
|
if (importedClassName.startsWith("optional:")) {
|
||||||
|
importedClassName = importedClassName.substring("optional:".length());
|
||||||
|
}
|
||||||
|
boolean found = find(importedClassName, (input) -> {
|
||||||
|
if (!correctlyAnnotated(input)) {
|
||||||
|
problems.add("Imported auto-configuration '%s' is not annotated with @AutoConfiguration"
|
||||||
|
.formatted(imported));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!found) {
|
||||||
|
problems.add("Imported auto-configuration '%s' was not found".formatted(importedClassName));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
List<String> sortedValues = new ArrayList<>(autoConfigureImports.imports);
|
||||||
|
Collections.sort(sortedValues, (i1, i2) -> {
|
||||||
|
boolean imported1 = i1.startsWith("optional:");
|
||||||
|
boolean imported2 = i2.startsWith("optional:");
|
||||||
|
int comparison = Boolean.compare(imported1, imported2);
|
||||||
|
if (comparison != 0) {
|
||||||
|
return comparison;
|
||||||
|
}
|
||||||
|
return i1.compareTo(i2);
|
||||||
|
});
|
||||||
|
if (!sortedValues.equals(autoConfigureImports.imports)) {
|
||||||
|
File sortedOutputFile = getOutputDirectory().file("sorted-" + autoConfigureImports.fileName)
|
||||||
|
.get()
|
||||||
|
.getAsFile();
|
||||||
|
writeString(sortedOutputFile, sortedValues.stream().collect(Collectors.joining(System.lineSeparator()))
|
||||||
|
+ System.lineSeparator());
|
||||||
|
problems.add(
|
||||||
|
"Entries should be required then optional, each sorted alphabetically (expected content written to '%s')"
|
||||||
|
.formatted(sortedOutputFile.getAbsolutePath()));
|
||||||
|
}
|
||||||
|
if (!problems.isEmpty()) {
|
||||||
|
allProblems.computeIfAbsent(autoConfigureImports.fileName, (unused) -> new ArrayList<>())
|
||||||
|
.addAll(problems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File outputFile = getOutputDirectory().file("failure-report.txt").get().getAsFile();
|
||||||
|
writeReport(allProblems, outputFile);
|
||||||
|
if (!allProblems.isEmpty()) {
|
||||||
|
throw new VerificationException(
|
||||||
|
"AutoConfigure….imports checks failed. See '%s' for details".formatted(outputFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<AutoConfigureImports> loadImports() {
|
||||||
|
return getSource().getFiles().stream().map((file) -> {
|
||||||
|
String fileName = file.getName();
|
||||||
|
String annotationName = fileName.substring(0, fileName.length() - ".imports".length());
|
||||||
|
return new AutoConfigureImports(annotationName, loadImports(file), fileName);
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> loadImports(File importsFile) {
|
||||||
|
try {
|
||||||
|
return Files.readAllLines(importsFile.toPath());
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new UncheckedIOException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean find(String className) {
|
||||||
|
return find(className, (input) -> {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean find(String className, Consumer<InputStream> handler) {
|
||||||
|
for (File root : this.classpath.getFiles()) {
|
||||||
|
String classFilePath = className.replace(".", "/") + ".class";
|
||||||
|
if (root.isDirectory()) {
|
||||||
|
File classFile = new File(root, classFilePath);
|
||||||
|
if (classFile.isFile()) {
|
||||||
|
try (InputStream input = new FileInputStream(classFile)) {
|
||||||
|
handler.accept(input);
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new UncheckedIOException(ex);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try (JarFile jar = new JarFile(root)) {
|
||||||
|
ZipEntry entry = jar.getEntry(classFilePath);
|
||||||
|
if (entry != null) {
|
||||||
|
try (InputStream input = jar.getInputStream(entry)) {
|
||||||
|
handler.accept(input);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new UncheckedIOException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean correctlyAnnotated(InputStream classFile) {
|
||||||
|
return AutoConfigurationClass.of(classFile) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeReport(Map<String, List<String>> allProblems, File outputFile) {
|
||||||
|
outputFile.getParentFile().mkdirs();
|
||||||
|
StringBuilder report = new StringBuilder();
|
||||||
|
if (!allProblems.isEmpty()) {
|
||||||
|
allProblems.forEach((fileName, problems) -> {
|
||||||
|
report.append("Found problems in '%s':%n".formatted(fileName));
|
||||||
|
problems.forEach((problem) -> report.append(" - %s%n".formatted(problem)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
writeString(outputFile, report.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeString(File file, String content) {
|
||||||
|
try {
|
||||||
|
Files.writeString(file.toPath(), content);
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new UncheckedIOException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record AutoConfigureImports(String annotationName, List<String> imports, String fileName) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,17 +17,14 @@
|
||||||
package org.springframework.boot.build.test.autoconfigure;
|
package org.springframework.boot.build.test.autoconfigure;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.Reader;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.TreeMap;
|
||||||
import java.util.SortedSet;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
|
|
||||||
import org.gradle.api.DefaultTask;
|
import org.gradle.api.DefaultTask;
|
||||||
import org.gradle.api.Task;
|
import org.gradle.api.Task;
|
||||||
|
@ -38,9 +35,9 @@ import org.gradle.api.tasks.OutputFile;
|
||||||
import org.gradle.api.tasks.PathSensitive;
|
import org.gradle.api.tasks.PathSensitive;
|
||||||
import org.gradle.api.tasks.PathSensitivity;
|
import org.gradle.api.tasks.PathSensitivity;
|
||||||
import org.gradle.api.tasks.TaskAction;
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
import tools.jackson.databind.json.JsonMapper;
|
||||||
|
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.boot.build.test.autoconfigure.TestSliceMetadata.TestSlice;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link Task} used to document test slices.
|
* {@link Task} used to document test slices.
|
||||||
|
@ -49,16 +46,16 @@ import org.springframework.util.StringUtils;
|
||||||
*/
|
*/
|
||||||
public abstract class DocumentTestSlices extends DefaultTask {
|
public abstract class DocumentTestSlices extends DefaultTask {
|
||||||
|
|
||||||
private FileCollection testSlices;
|
private FileCollection testSliceMetadata;
|
||||||
|
|
||||||
@InputFiles
|
@InputFiles
|
||||||
@PathSensitive(PathSensitivity.RELATIVE)
|
@PathSensitive(PathSensitivity.RELATIVE)
|
||||||
public FileCollection getTestSlices() {
|
public FileCollection getTestSlices() {
|
||||||
return this.testSlices;
|
return this.testSliceMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTestSlices(FileCollection testSlices) {
|
public void setTestSlices(FileCollection testSlices) {
|
||||||
this.testSlices = testSlices;
|
this.testSliceMetadata = testSlices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@OutputFile
|
@OutputFile
|
||||||
|
@ -66,61 +63,42 @@ public abstract class DocumentTestSlices extends DefaultTask {
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
void documentTestSlices() throws IOException {
|
void documentTestSlices() throws IOException {
|
||||||
Set<TestSlice> testSlices = readTestSlices();
|
Map<String, List<TestSlice>> testSlices = readTestSlices();
|
||||||
writeTable(testSlices);
|
writeTable(testSlices);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
private Map<String, List<TestSlice>> readTestSlices() {
|
||||||
private Set<TestSlice> readTestSlices() throws IOException {
|
Map<String, List<TestSlice>> testSlices = new TreeMap<>();
|
||||||
Set<TestSlice> testSlices = new TreeSet<>();
|
for (File metadataFile : this.testSliceMetadata) {
|
||||||
for (File metadataFile : this.testSlices) {
|
JsonMapper mapper = JsonMapper.builder().build();
|
||||||
Properties metadata = new Properties();
|
TestSliceMetadata metadata = mapper.readValue(metadataFile, TestSliceMetadata.class);
|
||||||
try (Reader reader = new FileReader(metadataFile)) {
|
List<TestSlice> slices = new ArrayList<>(metadata.testSlices());
|
||||||
metadata.load(reader);
|
Collections.sort(slices, (s1, s2) -> s1.annotation().compareTo(s2.annotation()));
|
||||||
}
|
testSlices.put(metadata.module(), slices);
|
||||||
for (String name : Collections.list((Enumeration<String>) metadata.propertyNames())) {
|
|
||||||
testSlices.add(new TestSlice(name,
|
|
||||||
new TreeSet<>(StringUtils.commaDelimitedListToSet(metadata.getProperty(name)))));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return testSlices;
|
return testSlices;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeTable(Set<TestSlice> testSlices) throws IOException {
|
private void writeTable(Map<String, List<TestSlice>> testSlicesByModule) throws IOException {
|
||||||
File outputFile = getOutputFile().getAsFile().get();
|
File outputFile = getOutputFile().getAsFile().get();
|
||||||
outputFile.getParentFile().mkdirs();
|
outputFile.getParentFile().mkdirs();
|
||||||
try (PrintWriter writer = new PrintWriter(new FileWriter(outputFile))) {
|
try (PrintWriter writer = new PrintWriter(new FileWriter(outputFile))) {
|
||||||
writer.println("[cols=\"d,a\"]");
|
writer.println("[cols=\"d,d,a\"]");
|
||||||
writer.println("|===");
|
writer.println("|===");
|
||||||
writer.println("| Test slice | Imported auto-configuration");
|
writer.println("|Module | Test slice | Imported auto-configuration");
|
||||||
for (TestSlice testSlice : testSlices) {
|
testSlicesByModule.forEach((module, testSlices) -> {
|
||||||
|
testSlices.forEach((testSlice) -> {
|
||||||
writer.println();
|
writer.println();
|
||||||
writer.printf("| `@%s`%n", testSlice.className);
|
writer.printf("| `%s`%n", module);
|
||||||
|
writer.printf("| javadoc:%s[format=annotation]%n", testSlice.annotation());
|
||||||
writer.println("| ");
|
writer.println("| ");
|
||||||
for (String importedAutoConfiguration : testSlice.importedAutoConfigurations) {
|
for (String importedAutoConfiguration : testSlice.importedAutoConfigurations()) {
|
||||||
writer.printf("`%s`%n", importedAutoConfiguration);
|
writer.printf("`%s`%n", importedAutoConfiguration);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
});
|
||||||
writer.println("|===");
|
writer.println("|===");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class TestSlice implements Comparable<TestSlice> {
|
|
||||||
|
|
||||||
private final String className;
|
|
||||||
|
|
||||||
private final SortedSet<String> importedAutoConfigurations;
|
|
||||||
|
|
||||||
private TestSlice(String className, SortedSet<String> importedAutoConfigurations) {
|
|
||||||
this.className = ClassUtils.getShortName(className);
|
|
||||||
this.importedAutoConfigurations = importedAutoConfigurations;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(TestSlice other) {
|
|
||||||
return this.className.compareTo(other.className);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,238 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-present 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.boot.build.test.autoconfigure;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask;
|
||||||
|
import org.gradle.api.Task;
|
||||||
|
import org.gradle.api.file.FileCollection;
|
||||||
|
import org.gradle.api.file.RegularFileProperty;
|
||||||
|
import org.gradle.api.model.ObjectFactory;
|
||||||
|
import org.gradle.api.tasks.Classpath;
|
||||||
|
import org.gradle.api.tasks.InputFiles;
|
||||||
|
import org.gradle.api.tasks.OutputFile;
|
||||||
|
import org.gradle.api.tasks.PathSensitive;
|
||||||
|
import org.gradle.api.tasks.PathSensitivity;
|
||||||
|
import org.gradle.api.tasks.SourceSet;
|
||||||
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
|
||||||
|
import org.springframework.boot.build.test.autoconfigure.TestSliceMetadata.TestSlice;
|
||||||
|
import org.springframework.core.io.FileSystemResource;
|
||||||
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReader;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||||
|
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link Task} for generating metadata describing a project's test slices.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public abstract class GenerateTestSliceMetadata extends DefaultTask {
|
||||||
|
|
||||||
|
private final ObjectFactory objectFactory;
|
||||||
|
|
||||||
|
private FileCollection classpath;
|
||||||
|
|
||||||
|
private FileCollection importsFiles;
|
||||||
|
|
||||||
|
private FileCollection classesDirs;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public GenerateTestSliceMetadata(ObjectFactory objectFactory) {
|
||||||
|
this.objectFactory = objectFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSourceSet(SourceSet sourceSet) {
|
||||||
|
this.classpath = sourceSet.getRuntimeClasspath();
|
||||||
|
this.importsFiles = this.objectFactory.fileTree()
|
||||||
|
.from(new File(sourceSet.getOutput().getResourcesDir(), "META-INF/spring"));
|
||||||
|
this.importsFiles.filter((file) -> file.getName().endsWith(".imports"));
|
||||||
|
getSpringFactories().set(new File(sourceSet.getOutput().getResourcesDir(), "META-INF/spring.factories"));
|
||||||
|
this.classesDirs = sourceSet.getOutput().getClassesDirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
@OutputFile
|
||||||
|
public abstract RegularFileProperty getOutputFile();
|
||||||
|
|
||||||
|
@InputFiles
|
||||||
|
@PathSensitive(PathSensitivity.RELATIVE)
|
||||||
|
abstract RegularFileProperty getSpringFactories();
|
||||||
|
|
||||||
|
@Classpath
|
||||||
|
FileCollection getClasspath() {
|
||||||
|
return this.classpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@InputFiles
|
||||||
|
@PathSensitive(PathSensitivity.RELATIVE)
|
||||||
|
FileCollection getImportFiles() {
|
||||||
|
return this.importsFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Classpath
|
||||||
|
FileCollection getClassesDirs() {
|
||||||
|
return this.classesDirs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
void generateTestSliceMetadata() throws IOException {
|
||||||
|
TestSliceMetadata metadata = readTestSlices();
|
||||||
|
File outputFile = getOutputFile().getAsFile().get();
|
||||||
|
outputFile.getParentFile().mkdirs();
|
||||||
|
metadata.writeTo(outputFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TestSliceMetadata readTestSlices() throws IOException {
|
||||||
|
List<TestSlice> testSlices = new ArrayList<>();
|
||||||
|
try (URLClassLoader classLoader = new URLClassLoader(
|
||||||
|
StreamSupport.stream(this.classpath.spliterator(), false).map(this::toURL).toArray(URL[]::new))) {
|
||||||
|
MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory(classLoader);
|
||||||
|
Properties springFactories = readSpringFactories(getSpringFactories().getAsFile().getOrNull());
|
||||||
|
readImportsFiles(springFactories, this.importsFiles);
|
||||||
|
for (File classesDir : this.classesDirs) {
|
||||||
|
testSlices.addAll(readTestSlices(classesDir, metadataReaderFactory, springFactories));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new TestSliceMetadata(getProject().getName(), testSlices);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the given imports files and puts them in springFactories. The key is the file
|
||||||
|
* name, the value is the file contents, split by line, delimited with a comma. This
|
||||||
|
* is done to mimic the spring.factories structure.
|
||||||
|
* @param springFactories spring.factories parsed as properties
|
||||||
|
* @param importsFiles the imports files to read
|
||||||
|
*/
|
||||||
|
private void readImportsFiles(Properties springFactories, FileCollection importsFiles) {
|
||||||
|
for (File file : importsFiles.getFiles()) {
|
||||||
|
try {
|
||||||
|
List<String> lines = removeComments(Files.readAllLines(file.toPath()));
|
||||||
|
String fileNameWithoutExtension = file.getName()
|
||||||
|
.substring(0, file.getName().length() - ".imports".length());
|
||||||
|
springFactories.setProperty(fileNameWithoutExtension,
|
||||||
|
StringUtils.collectionToCommaDelimitedString(lines));
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new UncheckedIOException("Failed to read file " + file, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> removeComments(List<String> lines) {
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
for (String line : lines) {
|
||||||
|
int commentIndex = line.indexOf('#');
|
||||||
|
if (commentIndex > -1) {
|
||||||
|
line = line.substring(0, commentIndex);
|
||||||
|
}
|
||||||
|
line = line.trim();
|
||||||
|
if (!line.isEmpty()) {
|
||||||
|
result.add(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private URL toURL(File file) {
|
||||||
|
try {
|
||||||
|
return file.toURI().toURL();
|
||||||
|
}
|
||||||
|
catch (MalformedURLException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Properties readSpringFactories(File file) throws IOException {
|
||||||
|
Properties springFactories = new Properties();
|
||||||
|
if (file.isFile()) {
|
||||||
|
try (Reader in = new FileReader(file)) {
|
||||||
|
springFactories.load(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return springFactories;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TestSlice> readTestSlices(File classesDir, MetadataReaderFactory metadataReaderFactory,
|
||||||
|
Properties springFactories) throws IOException {
|
||||||
|
try (Stream<Path> classes = Files.walk(classesDir.toPath())) {
|
||||||
|
return classes.filter((path) -> path.toString().endsWith("Test.class"))
|
||||||
|
.map((path) -> getMetadataReader(path, metadataReaderFactory))
|
||||||
|
.filter((metadataReader) -> metadataReader.getClassMetadata().isAnnotation())
|
||||||
|
.map((metadataReader) -> readTestSlice(metadataReader, springFactories))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private MetadataReader getMetadataReader(Path path, MetadataReaderFactory metadataReaderFactory) {
|
||||||
|
try {
|
||||||
|
return metadataReaderFactory.getMetadataReader(new FileSystemResource(path));
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TestSlice readTestSlice(MetadataReader metadataReader, Properties springFactories) {
|
||||||
|
String annotationName = metadataReader.getClassMetadata().getClassName();
|
||||||
|
List<String> importedAutoConfiguration = getImportedAutoConfiguration(springFactories,
|
||||||
|
metadataReader.getAnnotationMetadata());
|
||||||
|
return new TestSlice(annotationName, importedAutoConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getImportedAutoConfiguration(Properties springFactories,
|
||||||
|
AnnotationMetadata annotationMetadata) {
|
||||||
|
Stream<String> importers = findMetaImporters(annotationMetadata);
|
||||||
|
if (annotationMetadata.isAnnotated("org.springframework.boot.autoconfigure.ImportAutoConfiguration")) {
|
||||||
|
importers = Stream.concat(importers, Stream.of(annotationMetadata.getClassName()));
|
||||||
|
}
|
||||||
|
return importers
|
||||||
|
.flatMap((importer) -> StringUtils.commaDelimitedListToSet(springFactories.getProperty(importer)).stream())
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream<String> findMetaImporters(AnnotationMetadata annotationMetadata) {
|
||||||
|
return annotationMetadata.getAnnotationTypes()
|
||||||
|
.stream()
|
||||||
|
.filter((annotationType) -> isAutoConfigurationImporter(annotationType, annotationMetadata));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAutoConfigurationImporter(String annotationType, AnnotationMetadata metadata) {
|
||||||
|
return metadata.getMetaAnnotationTypes(annotationType)
|
||||||
|
.contains("org.springframework.boot.autoconfigure.ImportAutoConfiguration");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-present 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.boot.build.test.autoconfigure;
|
||||||
|
|
||||||
|
import org.gradle.api.Plugin;
|
||||||
|
import org.gradle.api.Project;
|
||||||
|
import org.gradle.api.file.ConfigurableFileCollection;
|
||||||
|
import org.gradle.api.plugins.JavaPlugin;
|
||||||
|
import org.gradle.api.plugins.JavaPluginExtension;
|
||||||
|
import org.gradle.api.tasks.SourceSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Plugin} for projects that define test auto-configuration. When the
|
||||||
|
* {@link JavaPlugin} is applied it:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>Add checks to ensure AutoConfigure*.import files and related annotations are
|
||||||
|
* correct</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class TestAutoConfigurationPlugin implements Plugin<Project> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(Project target) {
|
||||||
|
target.getPlugins().withType(JavaPlugin.class, (plugin) -> {
|
||||||
|
target.getTasks().register("checkAutoConfigureImports", CheckAutoConfigureImports.class, (task) -> {
|
||||||
|
SourceSet mainSourceSet = target.getExtensions()
|
||||||
|
.getByType(JavaPluginExtension.class)
|
||||||
|
.getSourceSets()
|
||||||
|
.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
|
||||||
|
task.setSource(mainSourceSet.getResources());
|
||||||
|
ConfigurableFileCollection classpath = target.files(mainSourceSet.getRuntimeClasspath(),
|
||||||
|
target.getConfigurations().getByName(mainSourceSet.getRuntimeClasspathConfigurationName()));
|
||||||
|
task.setClasspath(classpath);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,229 +17,30 @@
|
||||||
package org.springframework.boot.build.test.autoconfigure;
|
package org.springframework.boot.build.test.autoconfigure;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.io.UncheckedIOException;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.SortedSet;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import java.util.stream.StreamSupport;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import tools.jackson.databind.SerializationFeature;
|
||||||
|
import tools.jackson.databind.json.JsonMapper;
|
||||||
import org.gradle.api.DefaultTask;
|
|
||||||
import org.gradle.api.Task;
|
|
||||||
import org.gradle.api.artifacts.Configuration;
|
|
||||||
import org.gradle.api.file.FileCollection;
|
|
||||||
import org.gradle.api.file.RegularFileProperty;
|
|
||||||
import org.gradle.api.model.ObjectFactory;
|
|
||||||
import org.gradle.api.tasks.Classpath;
|
|
||||||
import org.gradle.api.tasks.InputFile;
|
|
||||||
import org.gradle.api.tasks.InputFiles;
|
|
||||||
import org.gradle.api.tasks.OutputFile;
|
|
||||||
import org.gradle.api.tasks.PathSensitive;
|
|
||||||
import org.gradle.api.tasks.PathSensitivity;
|
|
||||||
import org.gradle.api.tasks.SourceSet;
|
|
||||||
import org.gradle.api.tasks.TaskAction;
|
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
|
||||||
import org.springframework.core.io.FileSystemResource;
|
|
||||||
import org.springframework.core.type.AnnotationMetadata;
|
|
||||||
import org.springframework.core.type.classreading.MetadataReader;
|
|
||||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
|
||||||
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link Task} for generating metadata describing a project's test slices.
|
* Metadata describing a module's test slices.
|
||||||
*
|
*
|
||||||
|
* @param module the module's name
|
||||||
|
* @param testSlices the module's test slices
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
*/
|
*/
|
||||||
public abstract class TestSliceMetadata extends DefaultTask {
|
record TestSliceMetadata(String module, List<TestSlice> testSlices) {
|
||||||
|
|
||||||
private final ObjectFactory objectFactory;
|
static TestSliceMetadata readFrom(File file) {
|
||||||
|
return JsonMapper.builder().build().readValue(file, TestSliceMetadata.class);
|
||||||
private FileCollection classpath;
|
|
||||||
|
|
||||||
private FileCollection importsFiles;
|
|
||||||
|
|
||||||
private FileCollection classesDirs;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public TestSliceMetadata(ObjectFactory objectFactory) {
|
|
||||||
this.objectFactory = objectFactory;
|
|
||||||
Configuration testSliceMetadata = getProject().getConfigurations().maybeCreate("testSliceMetadata");
|
|
||||||
getProject().afterEvaluate((evaluated) -> evaluated.getArtifacts()
|
|
||||||
.add(testSliceMetadata.getName(), getOutputFile(), (artifact) -> artifact.builtBy(this)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSourceSet(SourceSet sourceSet) {
|
void writeTo(File file) {
|
||||||
this.classpath = sourceSet.getRuntimeClasspath();
|
JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).build().writeValue(file, this);
|
||||||
this.importsFiles = this.objectFactory.fileTree()
|
|
||||||
.from(new File(sourceSet.getOutput().getResourcesDir(), "META-INF/spring"));
|
|
||||||
this.importsFiles.filter((file) -> file.getName().endsWith(".imports"));
|
|
||||||
getSpringFactories().set(new File(sourceSet.getOutput().getResourcesDir(), "META-INF/spring.factories"));
|
|
||||||
this.classesDirs = sourceSet.getOutput().getClassesDirs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OutputFile
|
record TestSlice(String annotation, List<String> importedAutoConfigurations) {
|
||||||
public abstract RegularFileProperty getOutputFile();
|
|
||||||
|
|
||||||
@InputFile
|
|
||||||
@PathSensitive(PathSensitivity.RELATIVE)
|
|
||||||
abstract RegularFileProperty getSpringFactories();
|
|
||||||
|
|
||||||
@Classpath
|
|
||||||
FileCollection getClasspath() {
|
|
||||||
return this.classpath;
|
|
||||||
}
|
|
||||||
|
|
||||||
@InputFiles
|
|
||||||
@PathSensitive(PathSensitivity.RELATIVE)
|
|
||||||
FileCollection getImportFiles() {
|
|
||||||
return this.importsFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Classpath
|
|
||||||
FileCollection getClassesDirs() {
|
|
||||||
return this.classesDirs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@TaskAction
|
|
||||||
void documentTestSlices() throws IOException {
|
|
||||||
Properties testSlices = readTestSlices();
|
|
||||||
File outputFile = getOutputFile().getAsFile().get();
|
|
||||||
outputFile.getParentFile().mkdirs();
|
|
||||||
try (FileWriter writer = new FileWriter(outputFile)) {
|
|
||||||
testSlices.store(writer, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Properties readTestSlices() throws IOException {
|
|
||||||
Properties testSlices = CollectionFactory.createSortedProperties(true);
|
|
||||||
try (URLClassLoader classLoader = new URLClassLoader(
|
|
||||||
StreamSupport.stream(this.classpath.spliterator(), false).map(this::toURL).toArray(URL[]::new))) {
|
|
||||||
MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory(classLoader);
|
|
||||||
Properties springFactories = readSpringFactories(getSpringFactories().getAsFile().get());
|
|
||||||
readImportsFiles(springFactories, this.importsFiles);
|
|
||||||
for (File classesDir : this.classesDirs) {
|
|
||||||
addTestSlices(testSlices, classesDir, metadataReaderFactory, springFactories);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return testSlices;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the given imports files and puts them in springFactories. The key is the file
|
|
||||||
* name, the value is the file contents, split by line, delimited with a comma. This
|
|
||||||
* is done to mimic the spring.factories structure.
|
|
||||||
* @param springFactories spring.factories parsed as properties
|
|
||||||
* @param importsFiles the imports files to read
|
|
||||||
*/
|
|
||||||
private void readImportsFiles(Properties springFactories, FileCollection importsFiles) {
|
|
||||||
for (File file : importsFiles.getFiles()) {
|
|
||||||
try {
|
|
||||||
List<String> lines = removeComments(Files.readAllLines(file.toPath()));
|
|
||||||
String fileNameWithoutExtension = file.getName()
|
|
||||||
.substring(0, file.getName().length() - ".imports".length());
|
|
||||||
springFactories.setProperty(fileNameWithoutExtension,
|
|
||||||
StringUtils.collectionToCommaDelimitedString(lines));
|
|
||||||
}
|
|
||||||
catch (IOException ex) {
|
|
||||||
throw new UncheckedIOException("Failed to read file " + file, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> removeComments(List<String> lines) {
|
|
||||||
List<String> result = new ArrayList<>();
|
|
||||||
for (String line : lines) {
|
|
||||||
int commentIndex = line.indexOf('#');
|
|
||||||
if (commentIndex > -1) {
|
|
||||||
line = line.substring(0, commentIndex);
|
|
||||||
}
|
|
||||||
line = line.trim();
|
|
||||||
if (!line.isEmpty()) {
|
|
||||||
result.add(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private URL toURL(File file) {
|
|
||||||
try {
|
|
||||||
return file.toURI().toURL();
|
|
||||||
}
|
|
||||||
catch (MalformedURLException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Properties readSpringFactories(File file) throws IOException {
|
|
||||||
Properties springFactories = new Properties();
|
|
||||||
try (Reader in = new FileReader(file)) {
|
|
||||||
springFactories.load(in);
|
|
||||||
}
|
|
||||||
return springFactories;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addTestSlices(Properties testSlices, File classesDir, MetadataReaderFactory metadataReaderFactory,
|
|
||||||
Properties springFactories) throws IOException {
|
|
||||||
try (Stream<Path> classes = Files.walk(classesDir.toPath())) {
|
|
||||||
classes.filter((path) -> path.toString().endsWith("Test.class"))
|
|
||||||
.map((path) -> getMetadataReader(path, metadataReaderFactory))
|
|
||||||
.filter((metadataReader) -> metadataReader.getClassMetadata().isAnnotation())
|
|
||||||
.forEach((metadataReader) -> addTestSlice(testSlices, springFactories, metadataReader));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private MetadataReader getMetadataReader(Path path, MetadataReaderFactory metadataReaderFactory) {
|
|
||||||
try {
|
|
||||||
return metadataReaderFactory.getMetadataReader(new FileSystemResource(path));
|
|
||||||
}
|
|
||||||
catch (IOException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addTestSlice(Properties testSlices, Properties springFactories, MetadataReader metadataReader) {
|
|
||||||
testSlices.setProperty(metadataReader.getClassMetadata().getClassName(),
|
|
||||||
StringUtils.collectionToCommaDelimitedString(
|
|
||||||
getImportedAutoConfiguration(springFactories, metadataReader.getAnnotationMetadata())));
|
|
||||||
}
|
|
||||||
|
|
||||||
private SortedSet<String> getImportedAutoConfiguration(Properties springFactories,
|
|
||||||
AnnotationMetadata annotationMetadata) {
|
|
||||||
Stream<String> importers = findMetaImporters(annotationMetadata);
|
|
||||||
if (annotationMetadata.isAnnotated("org.springframework.boot.autoconfigure.ImportAutoConfiguration")) {
|
|
||||||
importers = Stream.concat(importers, Stream.of(annotationMetadata.getClassName()));
|
|
||||||
}
|
|
||||||
return importers
|
|
||||||
.flatMap((importer) -> StringUtils.commaDelimitedListToSet(springFactories.getProperty(importer)).stream())
|
|
||||||
.collect(Collectors.toCollection(TreeSet::new));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Stream<String> findMetaImporters(AnnotationMetadata annotationMetadata) {
|
|
||||||
return annotationMetadata.getAnnotationTypes()
|
|
||||||
.stream()
|
|
||||||
.filter((annotationType) -> isAutoConfigurationImporter(annotationType, annotationMetadata));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isAutoConfigurationImporter(String annotationType, AnnotationMetadata metadata) {
|
|
||||||
return metadata.getMetaAnnotationTypes(annotationType)
|
|
||||||
.contains("org.springframework.boot.autoconfigure.ImportAutoConfiguration");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-present 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.boot.build.test.autoconfigure;
|
||||||
|
|
||||||
|
import org.gradle.api.Plugin;
|
||||||
|
import org.gradle.api.Project;
|
||||||
|
import org.gradle.api.attributes.Category;
|
||||||
|
import org.gradle.api.attributes.Usage;
|
||||||
|
import org.gradle.api.plugins.JavaPlugin;
|
||||||
|
import org.gradle.api.plugins.JavaPluginExtension;
|
||||||
|
import org.gradle.api.plugins.PluginContainer;
|
||||||
|
import org.gradle.api.tasks.SourceSet;
|
||||||
|
import org.gradle.api.tasks.TaskProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Plugin} for projects that define one or more test slices. When applied, it:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>Applies the {@link TestAutoConfigurationPlugin}
|
||||||
|
* </ul>
|
||||||
|
* Additionally, when the {@link JavaPlugin} is applied it:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>Defines a task that produces metadata describing the test slices. The metadata is
|
||||||
|
* made available as an artifact in the {@code testSliceMetadata} configuration
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class TestSlicePlugin implements Plugin<Project> {
|
||||||
|
|
||||||
|
private static final String TEST_SLICE_METADATA_CONFIGURATION_NAME = "testSliceMetadata";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(Project target) {
|
||||||
|
PluginContainer plugins = target.getPlugins();
|
||||||
|
plugins.apply(TestAutoConfigurationPlugin.class);
|
||||||
|
plugins.withType(JavaPlugin.class, (plugin) -> {
|
||||||
|
TaskProvider<GenerateTestSliceMetadata> generateTestSliceMetadata = target.getTasks()
|
||||||
|
.register("generateTestSliceMetadata", GenerateTestSliceMetadata.class, (task) -> {
|
||||||
|
SourceSet mainSourceSet = target.getExtensions()
|
||||||
|
.getByType(JavaPluginExtension.class)
|
||||||
|
.getSourceSets()
|
||||||
|
.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
|
||||||
|
task.setSourceSet(mainSourceSet);
|
||||||
|
task.getOutputFile().set(target.getLayout().getBuildDirectory().file("test-slice-metadata.json"));
|
||||||
|
});
|
||||||
|
addMetadataArtifact(target, generateTestSliceMetadata);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMetadataArtifact(Project project, TaskProvider<GenerateTestSliceMetadata> task) {
|
||||||
|
project.getConfigurations().consumable(TEST_SLICE_METADATA_CONFIGURATION_NAME, (configuration) -> {
|
||||||
|
configuration.attributes((attributes) -> {
|
||||||
|
attributes.attribute(Category.CATEGORY_ATTRIBUTE,
|
||||||
|
project.getObjects().named(Category.class, Category.DOCUMENTATION));
|
||||||
|
attributes.attribute(Usage.USAGE_ATTRIBUTE,
|
||||||
|
project.getObjects().named(Usage.class, "test-slice-metadata"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
project.getArtifacts().add(TEST_SLICE_METADATA_CONFIGURATION_NAME, task);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -77,12 +77,13 @@ url-spring-data-rest-site=https://spring.io/projects/spring-data-rest
|
||||||
url-spring-data-rest-javadoc=https://docs.spring.io/spring-data/rest/docs/{dotxversion-spring-data-rest}/api
|
url-spring-data-rest-javadoc=https://docs.spring.io/spring-data/rest/docs/{dotxversion-spring-data-rest}/api
|
||||||
url-spring-data-site=https://spring.io/projects/spring-data
|
url-spring-data-site=https://spring.io/projects/spring-data
|
||||||
url-jackson-annotations-javadoc=https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-annotations/{version-jackson-annotations}
|
url-jackson-annotations-javadoc=https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-annotations/{version-jackson-annotations}
|
||||||
url-jackson-core-javadoc=https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-core/{version-jackson-core}
|
url-jackson-core-javadoc=https://javadoc.io/doc/tools.jackson.core/jackson-core/{version-jackson-core}
|
||||||
url-jackson-databind-javadoc=https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind/{version-jackson-databind}
|
url-jackson-databind-javadoc=https://javadoc.io/doc/tools.jackson.core/jackson-databind/{version-jackson-databind}
|
||||||
url-jackson-dataformat-xml-javadoc=https://javadoc.io/doc/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/{version-jackson-dataformat-xml}
|
url-jackson-dataformat-xml-javadoc=https://javadoc.io/doc/tools.jackson.dataformat/jackson-dataformat-xml/{version-jackson-dataformat-xml}
|
||||||
|
|
||||||
# === Javadoc Locations ===
|
# === Javadoc Locations ===
|
||||||
|
|
||||||
|
javadoc-location-com-fasterxml-jackson-annotation={url-jackson-annotations-javadoc}
|
||||||
javadoc-location-org-apache-pulsar-client-api={url-pulsar-client-api-javadoc}
|
javadoc-location-org-apache-pulsar-client-api={url-pulsar-client-api-javadoc}
|
||||||
javadoc-location-org-apache-pulsar-reactive-client-api={url-pulsar-client-reactive-api-javadoc}
|
javadoc-location-org-apache-pulsar-reactive-client-api={url-pulsar-client-reactive-api-javadoc}
|
||||||
javadoc-location-org-springframework-data-cassandra={url-spring-data-cassandra-javadoc}
|
javadoc-location-org-springframework-data-cassandra={url-spring-data-cassandra-javadoc}
|
||||||
|
@ -99,10 +100,9 @@ javadoc-location-org-springframework-data-neo4j={url-spring-data-neo4j-javadoc}
|
||||||
javadoc-location-org-springframework-data-r2dbc={url-spring-data-r2dbc-javadoc}
|
javadoc-location-org-springframework-data-r2dbc={url-spring-data-r2dbc-javadoc}
|
||||||
javadoc-location-org-springframework-data-redis={url-spring-data-redis-javadoc}
|
javadoc-location-org-springframework-data-redis={url-spring-data-redis-javadoc}
|
||||||
javadoc-location-org-springframework-data-rest={url-spring-data-rest-javadoc}
|
javadoc-location-org-springframework-data-rest={url-spring-data-rest-javadoc}
|
||||||
javadoc-location-com-fasterxml-jackson-annotation={url-jackson-annotations-javadoc}
|
javadoc-location-tools-jackson-core={url-jackson-core-javadoc}
|
||||||
javadoc-location-com-fasterxml-jackson-core={url-jackson-core-javadoc}
|
javadoc-location-tools-jackson-databind={url-jackson-databind-javadoc}
|
||||||
javadoc-location-com-fasterxml-jackson-databind={url-jackson-databind-javadoc}
|
javadoc-location-tools-jackson-dataformat-xml={url-jackson-dataformat-xml-javadoc}
|
||||||
javadoc-location-com-fasterxml-jackson-dataformat-xml={url-jackson-dataformat-xml-javadoc}
|
|
||||||
|
|
||||||
# === API References ===
|
# === API References ===
|
||||||
|
|
||||||
|
@ -116,6 +116,18 @@ apiref-openjdk=https://docs.oracle.com/en/java/javase/17/docs/api
|
||||||
# === Code Links ===
|
# === Code Links ===
|
||||||
|
|
||||||
code-spring-boot=https://github.com/{github-repo}/tree/{github-ref}
|
code-spring-boot=https://github.com/{github-repo}/tree/{github-ref}
|
||||||
code-spring-boot-autoconfigure-src={code-spring-boot}/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure
|
code-spring-boot-autoconfigure-src={code-spring-boot}/core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure
|
||||||
|
code-spring-boot-batch-jdbc-src={code-spring-boot}/module/spring-boot-batch-jdbc/src/main/java/org/springframework/boot/batch/jdbc
|
||||||
|
code-spring-boot-batch-src={code-spring-boot}/module/spring-boot-batch/src/main/java/org/springframework/boot/batch
|
||||||
|
code-spring-boot-freemarker-src={code-spring-boot}/module/spring-boot-freemarker/src/main/java/org/springframework/boot/freemarker
|
||||||
|
code-spring-boot-groovy-templates-src={code-spring-boot}/module/spring-boot-groovy-templates/src/main/java/org/springframework/boot/groovy/template
|
||||||
|
code-spring-boot-hibernate-src={code-spring-boot}/module/spring-boot-hibernate/src/main/java/org/springframework/boot/hibernate
|
||||||
|
code-spring-boot-integration-src={code-spring-boot}/module/spring-boot-integration/src/main/java/org/springframework/boot/integration
|
||||||
|
code-spring-boot-jdbc-src={code-spring-boot}/module/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc
|
||||||
|
code-spring-boot-jooq-src={code-spring-boot}/module/spring-boot-jooq/src/main/java/org/springframework/boot/jooq
|
||||||
|
code-spring-boot-jpa-src={code-spring-boot}/module/spring-boot-jpa/src/main/java/org/springframework/boot/jpa
|
||||||
code-spring-boot-latest=https://github.com/{github-repo}/tree/main
|
code-spring-boot-latest=https://github.com/{github-repo}/tree/main
|
||||||
|
code-spring-boot-servlet-src={code-spring-boot}/module/spring-boot-servlet/src/main/java/org/springframework/boot/servlet
|
||||||
|
code-spring-boot-thymeleaf-src={code-spring-boot}/module/spring-boot-thymeleaf/src/main/java/org/springframework/boot/thymeleaf
|
||||||
|
code-spring-boot-webmvc-src={code-spring-boot}/module/spring-boot-webmvc/src/main/java/org/springframework/boot/webmvc
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue