Skip to content

Commit 1204474

Browse files
committed
Added support for multiple configuration files of the same type.
1 parent ebc9cef commit 1204474

12 files changed

+172
-60
lines changed

utbot-spring-analyzer/src/main/kotlin/ApplicationRunner.kt

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,23 @@ import analyzers.SpringApplicationAnalyzer
44

55
fun main(args: Array<String>) {
66
/*
7-
val arg0 = "D:/Projects/spring-starter-lesson-28/build/classes/java/main";
8-
val arg1 = "com.dmdev.spring.config.ApplicationConfiguration";
9-
val arg2 = "D:/Projects/spring-starter-lesson-28/src/main/resources/application.properties";
10-
val arg3 = "D:/Projects/spring-starter-lesson-28/src/main/resources/application.xml";
11-
val springApplicationAnalyzer = SpringApplicationAnalyzer(arg0, arg1, arg2, arg3)
7+
arg2 contains .properties files, arg3 contains .xml files.
8+
If there are several files, they are transmitted via ";".
9+
If there are no files, then an empty string "" is passed
10+
*/
11+
12+
/* FOR EXAMPLE
13+
val arg0 = "/Users/kirillshishin/IdeaProjects/spring-starter-lesson-28/build/classes/java/main"
14+
val arg1 = "com.dmdev.spring.config.ApplicationConfiguration"
15+
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"
16+
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"
1217
*/
1318

1419
val springApplicationAnalyzer = SpringApplicationAnalyzer(
1520
applicationPath = args[0],
1621
configurationClassFqn = args[1],
17-
propertyFilePath = args[2],
18-
xmlConfigurationPath = args[3],
22+
propertyFilesPaths = args[2].split(";"),
23+
xmlConfigurationPaths = args[3].split(";"),
1924
)
2025

2126
springApplicationAnalyzer.analyze()

utbot-spring-analyzer/src/main/kotlin/analyzers/PropertiesAnalyzer.kt

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package analyzers
22

3+
import application.utils.FakeFileManager
4+
import application.configurators.PropertiesConfigurator
5+
import application.configurators.XmlFilesConfigurator
36
import config.TestApplicationConfiguration
47
import org.springframework.boot.builder.SpringApplicationBuilder
58
import org.springframework.context.ApplicationContextException
@@ -12,29 +15,30 @@ import java.nio.file.Path
1215
class SpringApplicationAnalyzer(
1316
private val applicationPath: String,
1417
private val configurationClassFqn: String,
15-
private val propertyFilePath: String,
16-
private val xmlConfigurationPath: String,
18+
private val propertyFilesPaths: List<String>,
19+
private val xmlConfigurationPaths: List<String>,
1720
) {
1821

1922
private val applicationUrl: URL
2023
get() = Path.of(applicationPath).toUri().toURL()
2124

2225
fun analyze() {
26+
val fakeFileManager = FakeFileManager(propertyFilesPaths + xmlConfigurationPaths)
27+
fakeFileManager.createFakeFiles()
28+
2329
val classLoader: ClassLoader = URLClassLoader(arrayOf(applicationUrl))
2430
val userConfigurationClass = classLoader.loadClass(configurationClassFqn)
2531

2632
val configurationManager = ConfigurationManager(classLoader, userConfigurationClass)
27-
val propertiesAnalyzer = PropertiesAnalyzer(propertyFilePath)
28-
val xmlConfigurationAnalyzer = XmlConfigurationAnalyzer(xmlConfigurationPath)
29-
30-
xmlConfigurationAnalyzer.fillFakeApplicationXml()
33+
val propertiesConfigurator = PropertiesConfigurator(propertyFilesPaths, configurationManager)
34+
val xmlFilesConfigurator = XmlFilesConfigurator(xmlConfigurationPaths, configurationManager, fakeFileManager)
3135

32-
configurationManager.patchPropertySourceAnnotation()
33-
configurationManager.patchImportResourceAnnotation()
36+
propertiesConfigurator.configure()
37+
xmlFilesConfigurator.configure()
3438

3539
val app = SpringApplicationBuilder(SpringApplicationAnalyzer::class.java)
3640
app.sources(TestApplicationConfiguration::class.java, userConfigurationClass)
37-
for (prop in propertiesAnalyzer.readProperties()) {
41+
for (prop in propertiesConfigurator.readProperties()) {
3842
app.properties(prop)
3943
}
4044

@@ -43,6 +47,8 @@ class SpringApplicationAnalyzer(
4347
app.run()
4448
} catch (e: ApplicationContextException) {
4549
println("Bean analysis finished successfully")
50+
}finally {
51+
fakeFileManager.deleteFakeFiles()
4652
}
4753
}
4854
}

utbot-spring-analyzer/src/main/kotlin/analyzers/XmlConfigurationAnalyzer.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,12 @@ package analyzers
22

33
import org.w3c.dom.Document
44
import org.w3c.dom.Element
5-
import utils.ResourceNames
65
import javax.xml.parsers.DocumentBuilderFactory
76
import javax.xml.transform.TransformerFactory
87
import javax.xml.transform.dom.DOMSource
98
import javax.xml.transform.stream.StreamResult
109

11-
class XmlConfigurationAnalyzer(private val userXmlFilePath: String) {
12-
private val fakeXmlFilePath = this.javaClass.classLoader.getResource(ResourceNames.fakeApplicationXmlFileName)?.path
13-
?: error("The path must exist")
10+
class XmlConfigurationAnalyzer(private val userXmlFilePath: String, private val fakeXmlFilePath: String) {
1411

1512
fun fillFakeApplicationXml() {
1613
val builder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package application.configurators
2+
3+
import utils.ConfigurationManager
4+
import utils.Paths
5+
import java.io.BufferedReader
6+
import java.io.FileReader
7+
import kotlin.io.path.Path
8+
9+
class PropertiesConfigurator(
10+
private val propertiesFilesPaths: List<String>,
11+
private val configurationManager: ConfigurationManager
12+
) {
13+
14+
fun configure(){
15+
configurationManager.clearPropertySourceAnnotation()
16+
17+
for(propertiesFilePath in propertiesFilesPaths) {
18+
if(propertiesFilePath == Paths.EMPTY_PATH)continue
19+
20+
configurationManager.patchPropertySourceAnnotation(Path(propertiesFilePath).fileName)
21+
}
22+
}
23+
24+
fun readProperties(): ArrayList<String> {
25+
val props = ArrayList<String>()
26+
27+
for(propertiesFilePath in propertiesFilesPaths) {
28+
if(propertiesFilePath == Paths.EMPTY_PATH)continue
29+
30+
val reader = BufferedReader(FileReader(propertiesFilePath))
31+
var line = reader.readLine()
32+
while (line != null) {
33+
props.add(line)
34+
line = reader.readLine()
35+
}
36+
37+
reader.close()
38+
}
39+
40+
return props
41+
}
42+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package application.configurators
2+
3+
import analyzers.XmlConfigurationAnalyzer
4+
import application.utils.FakeFileManager
5+
import utils.ConfigurationManager
6+
import utils.Paths
7+
import kotlin.io.path.Path
8+
9+
class XmlFilesConfigurator(
10+
private val userXmlFilePaths: List<String>,
11+
private val configurationManager: ConfigurationManager,
12+
private val fakeFileManager: FakeFileManager
13+
) {
14+
15+
fun configure() {
16+
configurationManager.clearImportResourceAnnotation()
17+
18+
for (userXmlFilePath in userXmlFilePaths) {
19+
if(userXmlFilePath == Paths.EMPTY_PATH)continue
20+
21+
val xmlConfigurationAnalyzer =
22+
XmlConfigurationAnalyzer(userXmlFilePath, fakeFileManager.getFakeFilePath(userXmlFilePath))
23+
24+
xmlConfigurationAnalyzer.fillFakeApplicationXml()
25+
configurationManager.patchImportResourceAnnotation(Path(userXmlFilePath).fileName)
26+
}
27+
}
28+
}

utbot-spring-analyzer/src/main/kotlin/utils/ConfigurationManager.kt

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,40 @@ package utils
33
import org.springframework.context.annotation.ImportResource
44
import org.springframework.context.annotation.PropertySource
55
import java.lang.reflect.InvocationHandler
6+
import java.nio.file.Path
67
import java.util.Arrays
78
import kotlin.reflect.KClass
89

910
class ConfigurationManager(private val classLoader: ClassLoader, private val userConfigurationClass: Class<*>) {
1011

11-
fun patchPropertySourceAnnotation() =
12-
patchAnnotation(PropertySource::class, String.format("classpath:%s", ResourceNames.fakePropertiesFileName))
12+
fun clearPropertySourceAnnotation(){
13+
patchAnnotation(
14+
PropertySource::class, null
15+
)
16+
}
17+
18+
fun clearImportResourceAnnotation(){
19+
patchAnnotation(
20+
ImportResource::class, null
21+
)
22+
}
1323

14-
fun patchImportResourceAnnotation() =
24+
fun patchPropertySourceAnnotation(userPropertiesFileName: Path) =
25+
patchAnnotation(
26+
PropertySource::class, String.format(
27+
"classpath:%s", "fake_$userPropertiesFileName"
28+
)
29+
)
30+
31+
fun patchImportResourceAnnotation(userXmlFilePath: Path) =
1532
patchAnnotation(
1633
ImportResource::class,
17-
String.format("classpath:%s", ResourceNames.fakeApplicationXmlFileName)
34+
String.format(
35+
"classpath:%s", "fake_$userXmlFilePath"
36+
)
1837
)
1938

20-
private fun patchAnnotation(annotationClass: KClass<*>, newValue: String) {
39+
private fun patchAnnotation(annotationClass: KClass<*>, newValue: String?) {
2140
val proxyClass = classLoader.loadClass("java.lang.reflect.Proxy")
2241
val hField = proxyClass.getDeclaredField("h")
2342
hField.isAccessible = true
@@ -37,7 +56,18 @@ class ConfigurationManager(private val classLoader: ClassLoader, private val use
3756
memberValuesField.isAccessible = true
3857

3958
val memberValues = memberValuesField[annotationInvocationHandler] as MutableMap<String, Any>
40-
memberValues["value"] = newValue
59+
addNewValue(memberValues, newValue)
60+
}
61+
}
62+
63+
private fun addNewValue(memberValues: MutableMap<String, Any>, newValue: String?){
64+
if(newValue == null){
65+
memberValues["value"] = Array(0){""}
66+
}
67+
else {
68+
val list: MutableList<String> = (memberValues["value"] as Array<String>).toMutableList()
69+
list.add(newValue)
70+
memberValues["value"] = list.toTypedArray()
4171
}
4272
}
4373
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package application.utils
2+
3+
import utils.Paths
4+
import java.io.File
5+
import kotlin.io.path.Path
6+
7+
class FakeFileManager(private val fakeFilesList: List<String>) {
8+
9+
private val buildResourcesPath =
10+
Path(this.javaClass.classLoader.getResource(Paths.GAG_FILE)!!.path).parent.toString()
11+
12+
fun createFakeFiles() {
13+
for (fileName in fakeFilesList) {
14+
if(fileName == Paths.EMPTY_FILENAME)continue
15+
val fakeXmlFileAbsolutePath = getFakeFilePath(fileName)
16+
File(fakeXmlFileAbsolutePath).createNewFile()
17+
}
18+
}
19+
20+
fun deleteFakeFiles() {
21+
for (fileName in fakeFilesList) {
22+
if(fileName == Paths.EMPTY_FILENAME)continue
23+
val fakeXmlFileAbsolutePath = getFakeFilePath(fileName)
24+
File(fakeXmlFileAbsolutePath).delete()
25+
}
26+
}
27+
28+
fun getFakeFilePath(fileName: String): String {
29+
return Path(buildResourcesPath, "fake_${Path(fileName).fileName}").toString()
30+
}
31+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package utils
2+
3+
object Paths {
4+
const val GAG_FILE = "gag_file.txt"
5+
const val EMPTY_PATH = ""
6+
const val EMPTY_FILENAME = ""
7+
}

utbot-spring-analyzer/src/main/kotlin/utils/ResourceNames.kt

Lines changed: 0 additions & 6 deletions
This file was deleted.

utbot-spring-analyzer/src/main/resources/fake_application.properties

Whitespace-only changes.

utbot-spring-analyzer/src/main/resources/fake_application.xml

Lines changed: 0 additions & 6 deletions
This file was deleted.

0 commit comments

Comments
 (0)