@@ -52,6 +52,21 @@ private TestContainers() {
52
52
53
53
}
54
54
55
+ private static <B > B withLock (String description , Supplier <B > supplier ) {
56
+ LOCK .lock ();
57
+ if (LOGGER .isTraceEnabled ()) {
58
+ LOGGER .trace ("Locked for {}" , description );
59
+ }
60
+ try {
61
+ return supplier .get ();
62
+ } finally {
63
+ if (LOGGER .isTraceEnabled ()) {
64
+ LOGGER .trace ("Unlocked for {}" , description );
65
+ }
66
+ LOCK .unlock ();
67
+ }
68
+ }
69
+
55
70
/**
56
71
* Returns a test container and caches it, so that if the same owner
57
72
* and properties are requested, we can return an existing container.
@@ -71,19 +86,18 @@ static <T extends GenericContainer<? extends T>> T getOrCreate(String requestedP
71
86
Map <String , Object > query ,
72
87
Supplier <T > creator ) {
73
88
Key key = Key .of (owner , name , Scope .from (query ), query );
74
- LOCK .lock ();
75
- @ SuppressWarnings ("unchecked" )
76
- T container = (T ) CONTAINERS_BY_KEY .get (key );
77
- if (container == null ) {
78
- container = creator .get ();
79
- LOGGER .info ("Starting test container {}" , name );
80
- container .start ();
81
- CONTAINERS_BY_KEY .put (key , container );
82
- }
83
- CONTAINERS_BY_PROPERTY .computeIfAbsent (requestedProperty , e -> new LinkedHashSet <>())
84
- .add (container );
85
- LOCK .unlock ();
86
- return container ;
89
+ return withLock ("getOrCreate" , () -> {
90
+ T container = (T ) CONTAINERS_BY_KEY .get (key );
91
+ if (container == null ) {
92
+ container = creator .get ();
93
+ LOGGER .info ("Starting test container {}" , name );
94
+ container .start ();
95
+ CONTAINERS_BY_KEY .put (key , container );
96
+ }
97
+ CONTAINERS_BY_PROPERTY .computeIfAbsent (requestedProperty , e -> new LinkedHashSet <>())
98
+ .add (container );
99
+ return container ;
100
+ });
87
101
}
88
102
89
103
/**
@@ -101,9 +115,8 @@ public static Map<Scope, List<GenericContainer<?>>> listByScope(String id) {
101
115
}
102
116
103
117
private static Map <Scope , List <GenericContainer <?>>> listByScope (Scope scope ) {
104
- LOCK .lock ();
105
- try {
106
- return CONTAINERS_BY_KEY .entrySet ()
118
+ return withLock ("listByScope" , () ->
119
+ CONTAINERS_BY_KEY .entrySet ()
107
120
.stream ()
108
121
.filter (entry -> scope .includes (entry .getKey ().scope ))
109
122
.collect (Collectors .groupingBy (
@@ -112,45 +125,41 @@ private static Map<Scope, List<GenericContainer<?>>> listByScope(Scope scope) {
112
125
Map .Entry ::getValue ,
113
126
Collectors .toList ()
114
127
)
115
- ));
116
- } finally {
117
- LOCK .unlock ();
118
- }
128
+ ))
129
+ );
119
130
}
120
131
132
+ @ SuppressWarnings ("java:S6204" ) // toList() breaks the return type
121
133
private static List <GenericContainer <?>> filterByScope (Scope scope , Set <GenericContainer <?>> containers ) {
122
134
if (containers .isEmpty ()) {
123
135
return Collections .emptyList ();
124
136
}
125
- LOCK .lock ();
126
- try {
127
- return CONTAINERS_BY_KEY .entrySet ()
137
+ return withLock ("filterByScope" , () ->
138
+ CONTAINERS_BY_KEY .entrySet ()
128
139
.stream ()
129
140
.filter (entry -> containers .contains (entry .getValue ()) && scope .includes (entry .getKey ().scope ))
130
141
.map (Map .Entry ::getValue )
131
- .collect (Collectors .toList ());
132
- } finally {
133
- LOCK .unlock ();
134
- }
142
+ .collect (Collectors .toList ())
143
+ );
135
144
}
136
145
137
146
public static Network network (String name ) {
138
147
return NETWORKS_BY_KEY .computeIfAbsent (name , k -> Network .newNetwork ());
139
148
}
140
149
141
150
public static boolean closeAll () {
142
- LOCK . lock ();
143
- boolean closed = false ;
144
- for (GenericContainer <?> container : CONTAINERS_BY_KEY .values ()) {
145
- container .close ();
146
- closed = true ;
147
- }
148
- CONTAINERS_BY_KEY .clear ();
149
- CONTAINERS_BY_PROPERTY .clear ();
150
- NETWORKS_BY_KEY .values ().forEach (Network ::close );
151
- NETWORKS_BY_KEY .clear ();
152
- LOCK . unlock () ;
153
- return closed ;
151
+ return withLock ( "closeAll" , () -> {
152
+ boolean closed = false ;
153
+ for (GenericContainer <?> container : CONTAINERS_BY_KEY .values ()) {
154
+ container .close ();
155
+ closed = true ;
156
+ }
157
+ CONTAINERS_BY_KEY .clear ();
158
+ CONTAINERS_BY_PROPERTY .clear ();
159
+ NETWORKS_BY_KEY .values ().forEach (Network ::close );
160
+ NETWORKS_BY_KEY .clear ();
161
+ return closed ;
162
+ }) ;
154
163
}
155
164
156
165
public static Map <String , Network > getNetworks () {
@@ -159,44 +168,41 @@ public static Map<String, Network> getNetworks() {
159
168
160
169
public static boolean closeScope (String id ) {
161
170
Scope scope = Scope .of (id );
162
- LOCK .lock ();
163
- boolean closed = false ;
164
- Iterator <Map .Entry <Key , GenericContainer <?>>> iterator = CONTAINERS_BY_KEY .entrySet ().iterator ();
165
- while (iterator .hasNext ()) {
166
- Map .Entry <Key , GenericContainer <?>> entry = iterator .next ();
167
- var existingScope = entry .getKey ().scope ;
168
- if (scope .includes (existingScope )) {
169
- iterator .remove ();
170
- GenericContainer <?> container = entry .getValue ();
171
- LOGGER .debug ("Stopping container {}" , container .getContainerId ());
172
- container .close ();
173
- closed = true ;
174
- for (Set <GenericContainer <?>> value : CONTAINERS_BY_PROPERTY .values ()) {
175
- value .remove (container );
171
+ return withLock ("closeScope" , () -> {
172
+ boolean closed = false ;
173
+ Iterator <Map .Entry <Key , GenericContainer <?>>> iterator = CONTAINERS_BY_KEY .entrySet ().iterator ();
174
+ while (iterator .hasNext ()) {
175
+ Map .Entry <Key , GenericContainer <?>> entry = iterator .next ();
176
+ var existingScope = entry .getKey ().scope ;
177
+ if (scope .includes (existingScope )) {
178
+ iterator .remove ();
179
+ GenericContainer <?> container = entry .getValue ();
180
+ LOGGER .debug ("Stopping container {}" , container .getContainerId ());
181
+ container .close ();
182
+ closed = true ;
183
+ for (Set <GenericContainer <?>> value : CONTAINERS_BY_PROPERTY .values ()) {
184
+ value .remove (container );
185
+ }
176
186
}
177
187
}
178
- }
179
- LOCK .unlock ();
180
- return closed ;
188
+ return closed ;
189
+ });
181
190
}
182
191
183
192
public static List <GenericContainer <?>> findByRequestedProperty (Scope scope , String property ) {
184
- LOCK .lock ();
185
- try {
193
+ return withLock ("findByRequestedProperty" , () -> {
186
194
Set <GenericContainer <?>> byProperty = CONTAINERS_BY_PROPERTY .getOrDefault (property , Collections .emptySet ());
187
195
LOGGER .debug ("Found {} containers for property {}. All properties: {}" , byProperty .size (), property , CONTAINERS_BY_PROPERTY .keySet ());
188
196
return filterByScope (scope , byProperty );
189
- } finally {
190
- LOCK .unlock ();
191
- }
197
+ });
192
198
}
193
199
194
200
private static final class Key {
195
201
private final Class <?> type ;
196
202
private final String name ;
197
- private final Scope scope ;
198
203
private final Map <String , String > properties ;
199
204
private final int hashCode ;
205
+ final Scope scope ;
200
206
201
207
private Key (Class <?> type , String name , Scope scope , Map <String , String > properties ) {
202
208
this .type = type ;
0 commit comments