1
+ package org .springframework .sbm .project .parser ;
2
+
3
+ import org .apache .maven .execution .MavenExecutionRequest ;
4
+ import org .apache .maven .execution .MavenSession ;
5
+ import org .apache .maven .model .*;
6
+ import org .apache .maven .plugin .logging .Log ;
7
+ import org .apache .maven .rtinfo .RuntimeInformation ;
8
+ import org .apache .maven .settings .Mirror ;
9
+ import org .apache .maven .settings .Server ;
10
+ import org .apache .maven .settings .crypto .*;
11
+ import org .intellij .lang .annotations .Language ;
12
+ import org .junit .jupiter .api .BeforeEach ;
13
+ import org .junit .jupiter .api .Test ;
14
+ import org .junit .jupiter .api .io .TempDir ;
15
+ import org .openrewrite .ExecutionContext ;
16
+ import org .openrewrite .InMemoryExecutionContext ;
17
+ import org .openrewrite .internal .lang .Nullable ;
18
+ import org .openrewrite .maven .MavenMojoProjectParser ;
19
+ import org .openrewrite .maven .MavenSettings ;
20
+ import org .openrewrite .maven .tree .MavenRepository ;
21
+ import org .sonatype .plexus .components .cipher .DefaultPlexusCipher ;
22
+ import org .sonatype .plexus .components .cipher .PlexusCipherException ;
23
+ import org .sonatype .plexus .components .sec .dispatcher .DefaultSecDispatcher ;
24
+ import org .springframework .core .io .Resource ;
25
+ import org .springframework .sbm .project .TestDummyResource ;
26
+ import org .springframework .test .util .ReflectionTestUtils ;
27
+
28
+ import java .io .IOException ;
29
+ import java .nio .file .Files ;
30
+ import java .nio .file .Path ;
31
+ import java .util .Arrays ;
32
+ import java .util .Collection ;
33
+ import java .util .List ;
34
+
35
+ import static org .assertj .core .api .Assertions .assertThat ;
36
+ import static org .mockito .Mockito .*;
37
+
38
+ /**
39
+ * Test feature parity between OpenRewrite Maven plugin settings initialization and |@link {@link RewriteMavenSettingsInitializer}.
40
+ *
41
+ * - {@link #initializeMavenSettings_withOpenRewriteMavenPlugin()} uses OpenRewrite Maven plugin to create {@link MavenSettings}.
42
+ * - {@link #initializeMavenSettings_withRewriteMavenSettingsInitializer()} uses SBM {@link RewriteMavenSettingsInitializer} to initialize {@link MavenSettings}.
43
+ *
44
+ * The tests verify {@link #verifyMavenSettings(MavenSettings)} that both approaches yield the same results given same input.
45
+ *
46
+ * @author Fabian Krüger
47
+ */
48
+ class RewriteMavenSettingsInitialierTest {
49
+
50
+ private final String profile1_id = "profile1" ;
51
+ private static final Path mavenHome = Path .of ("./target/.m2" ).toAbsolutePath ().normalize ();
52
+ private static final Path mavenRepository = mavenHome .resolve ("repository-changed" );
53
+ private static final String mirror1_id = "mirror1" ;
54
+ private static final String mirror1_url = "mirror1_url" ;
55
+ private static final String mirror1_mirrorOf = "mirror1_mirrorOf" ;
56
+ private static final String server1_id = "server1_id" ;
57
+ private static final String server1_username = "server1_username" ;
58
+ private static final String server1_password = "{gY56I8DPBrwHu3dWkh+EGDqp+ppuTnBaWe9fNpdTPIw=}" ;
59
+ private static final String server1_privateKey = "server1_privateKey" ;
60
+ private static final String server1_passphrase = "server1_passphrase" ;
61
+ private static final String server1_filePermissions = "server1_filePermissions" ;
62
+ private static final String server1_directoryPermissions = "server1_directoryPermissions" ;
63
+ private MavenSession mavenSession = mock (MavenSession .class );
64
+ private SettingsDecrypter settingsDecrypter ;
65
+ private static final String decryptedPassword = "xxx" ;
66
+
67
+ private static final String MAVEN_SECURITY_FILE = """
68
+ <settingsSecurity>
69
+ <!-- Password: XXX -->
70
+ <master>{H39p2LFBhRQHqKIsRiu0R/zhfke3/B4k0Wt+BZlC8mc=}</master>
71
+ </settingsSecurity>
72
+ """ ;
73
+
74
+ @ Language ("xml" )
75
+ private static final String MAVEN_SETTINGS_FILE = """
76
+ <?xml version="1.0" encoding="UTF-8"?>
77
+ <settings xsi:schemaLocation='http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd'
78
+ xmlns='http://maven.apache.org/SETTINGS/1.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
79
+ <localRepository>%s</localRepository>
80
+ <interactiveMode/>
81
+ <offline/>
82
+ <pluginGroups/>
83
+ <servers>
84
+ <server>
85
+ <id>%s</id>
86
+ <username>%s</username>
87
+ <password>%s</password>
88
+ <privateKey>%s</privateKey>
89
+ <passphrase>%s</passphrase>
90
+ <filePermissions>%s</filePermissions>
91
+ <directoryPermissions>%s</directoryPermissions>
92
+ <configuration></configuration>
93
+ </server>
94
+ </servers>
95
+ <mirrors>
96
+ <mirror>
97
+ <id>%s</id>
98
+ <url>%s</url>
99
+ <mirrorOf>%s</mirrorOf>
100
+ </mirror>
101
+ </mirrors>
102
+ <proxies/>
103
+ <profiles>
104
+ <profile>
105
+ <id>profile1</id>
106
+ <activation>
107
+ <activeByDefault>true</activeByDefault>
108
+ <jdk>17</jdk>
109
+ </activation>
110
+ </profile>
111
+ </profiles>
112
+ <activeProfiles>
113
+ <activeProfile>profile1</activeProfile>
114
+ </activeProfiles>
115
+ </settings>
116
+ """ .formatted (
117
+ mavenRepository ,
118
+ server1_id ,
119
+ server1_username ,
120
+ server1_password ,
121
+ server1_privateKey ,
122
+ server1_passphrase ,
123
+ server1_filePermissions ,
124
+ server1_directoryPermissions ,
125
+ mirror1_id ,
126
+ mirror1_url ,
127
+ mirror1_mirrorOf );
128
+ private Path mavenSecurityFilePath ;
129
+ private Path mavenSettingsFilePath ;
130
+
131
+ @ BeforeEach
132
+ void beforeEach (@ TempDir Path tmpDir ) {
133
+ // Prepare internal classes to decrypt Server password
134
+ try {
135
+ // DefaultSecDispatcher reads file with security settings
136
+ mavenSecurityFilePath = tmpDir .resolve ("settings-security.xml" );
137
+ Files .writeString (mavenSecurityFilePath , MAVEN_SECURITY_FILE );
138
+ mavenSettingsFilePath = tmpDir .resolve ("settings.xml" );
139
+ Files .writeString (mavenSettingsFilePath , MAVEN_SETTINGS_FILE );
140
+
141
+ } catch (IOException e ) {
142
+ throw new RuntimeException (e );
143
+ }
144
+ }
145
+
146
+ /*
147
+ * Use OpenRewrite Maven Plugin (@link MavenMojoProjectParser} to initialize settings.
148
+ */
149
+ @ Test
150
+ void initializeMavenSettings_withOpenRewriteMavenPlugin () throws PlexusCipherException {
151
+ MavenMojoProjectParser comparingParser = createMavenMojoProjectParser ();
152
+
153
+ MavenExecutionRequest mavenExecutionRequest = mock (MavenExecutionRequest .class );
154
+ when (mavenSession .getRequest ()).thenReturn (mavenExecutionRequest );
155
+ // Maven profiles
156
+ Profile profile1 = mock (Profile .class );
157
+ when (profile1 .getId ()).thenReturn (profile1_id );
158
+
159
+ Activation profile1_activation = mock (Activation .class );
160
+ when (profile1_activation .isActiveByDefault ()).thenReturn (true );
161
+ when (profile1_activation .getJdk ()).thenReturn ("profile1_jdk" );
162
+ when (profile1 .getActivation ()).thenReturn (profile1_activation );
163
+
164
+ ActivationProperty profile1_property = mock (ActivationProperty .class );
165
+ when (profile1_activation .getProperty ()).thenReturn (profile1_property );
166
+ when (profile1_property .getName ()).thenReturn ("profile1_property_name" );
167
+ when (profile1_property .getValue ()).thenReturn ("profile1_property_value" );
168
+
169
+ Repository profile1_repository1 = mock (Repository .class );
170
+ List <Repository > profile1_repositories = List .of (profile1_repository1 );
171
+ when (profile1 .getRepositories ()).thenReturn (profile1_repositories );
172
+
173
+ SettingsDecryptionResult decryptionResult = mock (SettingsDecryptionResult .class );
174
+ Server decryptionResultServer = mock (Server .class );
175
+ when (decryptionResult .getServer ()).thenReturn (decryptionResultServer );
176
+ when (decryptionResultServer .getPassword ()).thenReturn (decryptedPassword );
177
+
178
+ when (mavenExecutionRequest .getProfiles ()).thenReturn (List .of (profile1 )); // with profiles
179
+ // Active profiles
180
+ when (mavenExecutionRequest .getActiveProfiles ()).thenReturn (List .of (profile1_id )); // with active profiles
181
+ // Mirrors
182
+ Mirror mirror1 = mock (Mirror .class );
183
+ when (mirror1 .getId ()).thenReturn (mirror1_id );
184
+ when (mirror1 .getMirrorOf ()).thenReturn (mirror1_mirrorOf );
185
+ when (mirror1 .getUrl ()).thenReturn (mirror1_url );
186
+ verify (mirror1 , never ()).getLayout ();
187
+
188
+ Mirror mirror2 = mock (Mirror .class );
189
+ List <Mirror > mirrors = List .of (mirror1 );
190
+
191
+ when (mavenExecutionRequest .getMirrors ()).thenReturn (mirrors ); // with mirrors
192
+ // Servers
193
+
194
+ Server server1 = new Server ();
195
+ server1 .setPassword (server1_password );
196
+ server1 .setId (server1_id );
197
+ server1 .setUsername (server1_username );
198
+ server1 .setFilePermissions (server1_filePermissions );
199
+ server1 .setDirectoryPermissions (server1_directoryPermissions );
200
+ server1 .setPassphrase (server1_passphrase );
201
+ server1 .setPrivateKey (server1_privateKey );
202
+ List <Server > servers = List .of (server1 );
203
+ when (mavenExecutionRequest .getServers ()).thenReturn (servers ); // with Servers
204
+ // repository path
205
+ when (mavenExecutionRequest .getLocalRepositoryPath ()).thenReturn (mavenRepository .toFile ());
206
+
207
+ MavenSettings mavenSettings = comparingParser .buildSettings ();
208
+
209
+ verifyMavenSettings (mavenSettings );
210
+ }
211
+
212
+ @ Test
213
+ void initializeMavenSettings_withRewriteMavenSettingsInitializer () {
214
+ ExecutionContext executionContext = new InMemoryExecutionContext ();
215
+ Resource securitySettingsFile = new TestDummyResource (mavenSecurityFilePath , MAVEN_SECURITY_FILE );
216
+ Resource mavenSettingsFile = new TestDummyResource (mavenSettingsFilePath , MAVEN_SETTINGS_FILE );
217
+
218
+ RewriteMavenSettingsInitializer sut = new RewriteMavenSettingsInitializer (new MavenPasswordDecrypter ());
219
+ MavenSettings mavenSettings = sut .initializeMavenSettings (executionContext , mavenSettingsFile , mavenSecurityFilePath );
220
+
221
+ verifyMavenSettings (mavenSettings );
222
+ }
223
+
224
+ private void verifyMavenSettings (MavenSettings mavenSettings ) {
225
+ assertThat (mavenSettings ).isNotNull ();
226
+
227
+ MavenSettings .ActiveProfiles activeProfiles = mavenSettings .getActiveProfiles ();
228
+ assertThat (activeProfiles .getActiveProfiles ().get (0 )).isEqualTo (profile1_id );
229
+
230
+ MavenRepository mavenLocal = mavenSettings .getMavenLocal ();
231
+ assertThat (mavenLocal .isKnownToExist ()).isTrue ();
232
+ assertThat (mavenLocal .getUsername ()).isNull ();
233
+ assertThat (mavenLocal .getPassword ()).isNull ();
234
+ assertThat (mavenLocal .getSnapshots ()).isNull ();
235
+ assertThat (mavenLocal .getReleases ()).isNull ();
236
+ assertThat (mavenLocal .getUri ()).isEqualTo ("file://" + mavenRepository );
237
+ assertThat (mavenLocal .getId ()).isEqualTo ("local" );
238
+ assertThat (mavenLocal .getDeriveMetadataIfMissing ()).isNull ();
239
+
240
+ MavenSettings .Profiles profiles = mavenSettings .getProfiles ();
241
+ assertThat (profiles .getProfiles ()).hasSize (1 );
242
+
243
+ assertThat (mavenSettings .getMirrors ()).isNotNull ();
244
+ assertThat (mavenSettings .getMirrors ().getMirrors ()).hasSize (1 );
245
+ MavenSettings .Mirror mirror1 = mavenSettings .getMirrors ().getMirrors ().get (0 );
246
+ assertThat (mirror1 .getId ()).isEqualTo (mirror1_id );
247
+ assertThat (mirror1 .getUrl ()).isEqualTo (mirror1_url );
248
+ assertThat (mirror1 .getMirrorOf ()).isEqualTo (mirror1_mirrorOf );
249
+ assertThat (mirror1 .getReleases ()).isNull ();
250
+ assertThat (mirror1 .getSnapshots ()).isNull ();
251
+ assertThat (countGetter (MavenSettings .Mirror .class )).isEqualTo (5 );
252
+
253
+
254
+ MavenSettings .Servers servers = mavenSettings .getServers ();
255
+ assertThat (servers .getServers ()).hasSize (1 );
256
+ MavenSettings .Server server = servers .getServers ().get (0 );
257
+ assertThat (server .getId ()).isEqualTo (server1_id );
258
+ assertThat (server .getUsername ()).isEqualTo (server1_username );
259
+ assertThat (server .getPassword ()).isEqualTo (decryptedPassword );
260
+ assertThat (countGetter (server .getClass ())).isEqualTo (3 );
261
+ }
262
+
263
+ private long countGetter (Class <?> clazz ) {
264
+ long allGetter = internalGetGetter (clazz );
265
+ long objectGetter = internalGetGetter (Object .class );
266
+ return allGetter - objectGetter ;
267
+ }
268
+
269
+ private long internalGetGetter (Class <?> clazz ) {
270
+ return Arrays
271
+ .stream (clazz .getMethods ())
272
+ .filter (m -> m .getName ().startsWith ("get" ))
273
+ .filter (m -> m .getParameterCount () == 0 )
274
+ .count ();
275
+ }
276
+
277
+ private MavenMojoProjectParser createMavenMojoProjectParser () throws PlexusCipherException {
278
+ DefaultSecDispatcher securityDispatcher = new DefaultSecDispatcher ();
279
+ // hack, the cipher is required but can't be set from outside
280
+ ReflectionTestUtils .setField (securityDispatcher , "_cipher" , new DefaultPlexusCipher ());
281
+ settingsDecrypter = new DefaultSettingsDecrypter (securityDispatcher );
282
+ // The file location is retrieved from env, default is ~/${user.home}/.settings-security.xml
283
+ System .setProperty ("settings.security" , mavenSecurityFilePath .toString ());
284
+
285
+ Log logger = mock (Log .class );
286
+ Path baseDir = Path .of ("./src/test/resources/rewrite-maven-plugin" );
287
+ boolean pomCacheEnabled = false ;
288
+ @ Nullable String pomCacheDirectory = null ;
289
+ RuntimeInformation runtime = mock (RuntimeInformation .class );
290
+ boolean skipMavenParsing = false ;
291
+ Collection <String > exclusions = List .of ();
292
+ Collection <String > plainTextMasks = List .of ();
293
+ int sizeThresholdMb = 1_000_000 ;
294
+
295
+ return new MavenMojoProjectParser (logger , baseDir , pomCacheEnabled , pomCacheDirectory , runtime ,
296
+ skipMavenParsing , exclusions , plainTextMasks , sizeThresholdMb , mavenSession ,
297
+ settingsDecrypter );
298
+ }
299
+
300
+ }
0 commit comments