Skip to content

Commit 6a1e3c3

Browse files
authored
Support Spring projects with main xml config in utbot-spring-analyzer (#2087)
1 parent 35cca4f commit 6a1e3c3

File tree

8 files changed

+116
-40
lines changed

8 files changed

+116
-40
lines changed
Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package org.utbot.spring
22

33
import org.utbot.spring.analyzers.SpringApplicationAnalyzer
4+
import org.utbot.spring.data.ApplicationData
45
import org.utbot.spring.utils.PathsUtils
5-
import java.nio.file.Path
6+
import java.io.File
7+
import java.net.URL
68

79
/**
810
* To run this app, arguments must be passed in the following way:
911
* args[0] - classpath of current project
10-
* args[1] - fully qualified name of configuration class
12+
* args[1] - fully qualified name of configuration class or main .xml configuration file path
1113
* args[2] - `.properties` file paths, separated via `;`, empty string if no files exist
1214
* args[3] - `.xml` configuration file paths
1315
*
@@ -18,17 +20,29 @@ fun main(args: Array<String>) {
1820

1921
/* FOR EXAMPLE
2022
val arg0 = "/Users/kirillshishin/IdeaProjects/spring-starter-lesson-28/build/classes/java/main"
23+
2124
val arg1 = "com.dmdev.spring.config.ApplicationConfiguration"
25+
or
26+
val arg1 = "/Users/kirillshishin/IdeaProjects/spring-starter-lesson-28/src/main/resources/application.xml"
27+
2228
val arg2 = "/Users/kirillshishin/IdeaProjects/spring-starter-lesson-28/src/main/resources/application.properties;/Users/kirillshishin/IdeaProjects/spring-starter-lesson-28/src/main/resources/application-web.properties"
2329
val arg3 = "/Users/kirillshishin/IdeaProjects/spring-starter-lesson-28/src/main/resources/application.xml;/Users/kirillshishin/IdeaProjects/spring-starter-lesson-28/src/main/resources/application2.xml"
2430
*/
2531

26-
val springApplicationAnalyzer = SpringApplicationAnalyzer(
27-
applicationUrl = Path.of(args[0]).toUri().toURL(),
28-
configurationClassFqn = args[1],
29-
propertyFilesPaths = args[2].split(";").filter { it != PathsUtils.EMPTY_PATH },
30-
xmlConfigurationPaths = args[3].split(";").filter { it != PathsUtils.EMPTY_PATH },
31-
)
32+
val applicationData =
33+
ApplicationData(
34+
applicationUrlArray = parseApplicationUrls(args[0]),
35+
configurationFile = args[1],
36+
propertyFilesPaths = args[2].split(";").filter { it != PathsUtils.EMPTY_PATH },
37+
xmlConfigurationPaths = args[3].split(";").filter { it != PathsUtils.EMPTY_PATH },
38+
)
39+
40+
SpringApplicationAnalyzer(applicationData).analyze()
41+
}
3242

33-
springApplicationAnalyzer.analyze()
34-
}
43+
fun parseApplicationUrls(urlString: String): Array<URL> =
44+
urlString
45+
.split(';')
46+
.filter { it != PathsUtils.EMPTY_PATH }
47+
.map { File(it).toURI().toURL() }
48+
.toTypedArray()
Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,35 @@
11
package org.utbot.spring.analyzers
22

3-
import org.utbot.spring.utils.FakeFileManager
4-
import org.utbot.spring.configurators.PropertiesConfigurator
5-
import org.utbot.spring.configurators.XmlFilesConfigurator
6-
import org.utbot.spring.config.TestApplicationConfiguration
73
import org.springframework.boot.builder.SpringApplicationBuilder
84
import org.springframework.context.ApplicationContextException
9-
import org.utbot.spring.utils.ConfigurationManager
10-
import java.net.URL
11-
import java.net.URLClassLoader
12-
5+
import org.utbot.spring.configurators.ApplicationConfigurationType
6+
import org.utbot.spring.configurators.ApplicationConfigurationType.JavaConfiguration
7+
import org.utbot.spring.configurators.ApplicationConfigurationType.XmlConfiguration
8+
import org.utbot.spring.configurators.ApplicationConfigurator
9+
import org.utbot.spring.data.ApplicationData
10+
import org.utbot.spring.utils.FakeFileManager
11+
import java.io.File
1312

1413
class SpringApplicationAnalyzer(
15-
private val applicationUrl: URL,
16-
private val configurationClassFqn: String,
17-
private val propertyFilesPaths: List<String>,
18-
private val xmlConfigurationPaths: List<String>,
14+
private val applicationData: ApplicationData
1915
) {
2016

2117
fun analyze() {
22-
val fakeFileManager = FakeFileManager(propertyFilesPaths + xmlConfigurationPaths)
18+
val fakeFileManager =
19+
FakeFileManager(applicationData.propertyFilesPaths + applicationData.xmlConfigurationPaths)
2320
fakeFileManager.createTempFiles()
2421

25-
val classLoader: ClassLoader = URLClassLoader(arrayOf(applicationUrl))
26-
val userConfigurationClass = classLoader.loadClass(configurationClassFqn)
27-
28-
val configurationManager = ConfigurationManager(classLoader, userConfigurationClass)
29-
val propertiesConfigurator = PropertiesConfigurator(propertyFilesPaths, configurationManager)
30-
val xmlFilesConfigurator = XmlFilesConfigurator(xmlConfigurationPaths, configurationManager)
22+
val applicationBuilder = SpringApplicationBuilder(SpringApplicationAnalyzer::class.java)
23+
val applicationConfigurator = ApplicationConfigurator(applicationBuilder, applicationData)
3124

32-
propertiesConfigurator.configure()
33-
xmlFilesConfigurator.configure()
34-
35-
val app = SpringApplicationBuilder(SpringApplicationAnalyzer::class.java)
36-
app.sources(TestApplicationConfiguration::class.java, userConfigurationClass)
37-
for (prop in propertiesConfigurator.readProperties()) {
38-
app.properties(prop)
25+
when (findConfigurationType(applicationData)) {
26+
XmlConfiguration -> applicationConfigurator.configureXmlBasedApplication()
27+
else -> applicationConfigurator.configureJavaBasedApplication()
3928
}
4029

4130
try {
42-
app.build()
43-
app.run()
31+
applicationBuilder.build()
32+
applicationBuilder.run()
4433
} catch (e: ApplicationContextException) {
4534
// UtBotBeanFactoryPostProcessor destroys bean definitions
4635
// to prevent Spring application from actually starting and
@@ -50,4 +39,13 @@ class SpringApplicationAnalyzer(
5039
fakeFileManager.deleteTempFiles()
5140
}
5241
}
42+
43+
private fun findConfigurationType(applicationData: ApplicationData): ApplicationConfigurationType {
44+
//TODO: support Spring Boot Applications here.
45+
val fileExtension = File(applicationData.configurationFile).extension
46+
return when (fileExtension) {
47+
"xml" -> XmlConfiguration
48+
else -> JavaConfiguration
49+
}
50+
}
5351
}

utbot-spring-analyzer/src/main/kotlin/org/utbot/spring/config/TestApplicationConfiguration.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ package org.utbot.spring.config
33
import org.springframework.beans.factory.config.BeanFactoryPostProcessor
44
import org.springframework.context.annotation.Bean
55
import org.springframework.context.annotation.Configuration
6+
import org.springframework.context.annotation.ImportResource
67
import org.utbot.spring.postProcessors.UtBotBeanFactoryPostProcessor
78

89
@Configuration
10+
@ImportResource
911
open class TestApplicationConfiguration {
1012

1113
@Bean
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package org.utbot.spring.configurators
2+
3+
import org.springframework.boot.builder.SpringApplicationBuilder
4+
import org.utbot.spring.config.TestApplicationConfiguration
5+
import org.utbot.spring.data.ApplicationData
6+
import org.utbot.spring.utils.ConfigurationManager
7+
import java.net.URLClassLoader
8+
9+
open class ApplicationConfigurator(
10+
private val applicationBuilder: SpringApplicationBuilder,
11+
private val applicationData: ApplicationData
12+
) {
13+
private val classLoader: ClassLoader = URLClassLoader(applicationData.applicationUrlArray)
14+
15+
fun configureJavaBasedApplication() {
16+
configureApplication(
17+
configurationClass = classLoader.loadClass(applicationData.configurationFile),
18+
xmlConfigurationPaths = applicationData.xmlConfigurationPaths
19+
)
20+
}
21+
22+
fun configureXmlBasedApplication() {
23+
configureApplication(
24+
configurationClass = TestApplicationConfiguration::class.java,
25+
xmlConfigurationPaths = listOf(applicationData.configurationFile)
26+
)
27+
}
28+
29+
private fun configureApplication(configurationClass: Class<*>, xmlConfigurationPaths: List<String>) {
30+
31+
val configurationManager = ConfigurationManager(classLoader, configurationClass)
32+
33+
val xmlFilesConfigurator = XmlFilesConfigurator(xmlConfigurationPaths, configurationManager)
34+
val propertiesConfigurator = PropertiesConfigurator(applicationData.propertyFilesPaths, configurationManager)
35+
36+
propertiesConfigurator.configure()
37+
xmlFilesConfigurator.configure()
38+
39+
for (prop in propertiesConfigurator.readProperties()) {
40+
applicationBuilder.properties(prop)
41+
}
42+
applicationBuilder.sources(TestApplicationConfiguration::class.java, configurationClass)
43+
}
44+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.utbot.spring.configurators
2+
3+
enum class ApplicationConfigurationType {
4+
5+
XmlConfiguration,
6+
7+
JavaConfiguration,
8+
9+
SpringBootConfiguration
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.utbot.spring.data
2+
3+
import java.net.URL
4+
5+
data class ApplicationData(
6+
val applicationUrlArray: Array<URL>,
7+
val configurationFile: String,
8+
val propertyFilesPaths: List<String>,
9+
val xmlConfigurationPaths: List<String>,
10+
)

utbot-spring-analyzer/src/main/kotlin/org/utbot/spring/utils/FakeFileManager.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.utbot.spring.utils
22

3-
import org.utbot.spring.utils.PathsUtils
43
import java.io.File
54
import java.io.IOException
65

utbot-spring-analyzer/src/main/kotlin/org/utbot/spring/utils/PathsUtils.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.utbot.spring.utils
22

3-
import java.io.File
43
import kotlin.io.path.Path
54

65
object PathsUtils {

0 commit comments

Comments
 (0)