1 /* 2 * Copyright (C) 2025 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.xts.apimapper.config 18 19 import javax.xml.parsers.DocumentBuilderFactory 20 import org.w3c.dom.Document 21 import org.w3c.dom.Element 22 23 /** 24 * Data class representing the configuration for a single injection rule. 25 * 26 * @property pattern The pattern to match the module name. 27 * @property apiPrefixes The list of API prefixes to be logged. 28 * @property callerPrefixes The list of caller class prefixes to be processed. 29 */ 30 data class InjectRule( 31 val pattern: Regex, 32 val apiPrefixes: List<String>, 33 val callerPrefixes: List<String> 34 ) 35 36 /** 37 * A class responsible for parsing the XML configuration file. 38 */ 39 class Configuration(configFile: String) { 40 41 private var doc: Document 42 43 init { 44 val inputStream = this::class.java.classLoader.getResourceAsStream(configFile) 45 doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream) 46 } 47 48 /** 49 * Parses the XML configuration file and returns a list of [InjectRule] objects. 50 * 51 * @param configFile The path to the XML configuration file. 52 * @return A list of [InjectRule] objects representing the parsed rules. 53 */ getInjectRulesnull54 fun getInjectRules(): List<InjectRule> { 55 val rules = mutableListOf<InjectRule>() 56 val ruleElements = doc.getElementsByTagName("inject-rules") 57 58 for (i in 0 until ruleElements.length) { 59 val ruleElement = ruleElements.item(i) as Element 60 rules.add(parseRule(ruleElement)) 61 } 62 63 return rules 64 } 65 66 /** 67 * Parses a single `<rule>` element and extracts its configuration. 68 * 69 * @param ruleElement The `<rule>` element to parse. 70 * @return A [InjectRule] object representing the parsed rule. 71 */ parseRulenull72 private fun parseRule(ruleElement: Element): InjectRule { 73 val pattern = ruleElement.getElementsByTagName("pattern").item(0).textContent 74 val apiPrefixes = parsePrefixes(ruleElement, "apiPrefixes") 75 val callerPrefixes = parsePrefixes(ruleElement, "callerPrefixes") 76 return InjectRule(Regex(pattern), apiPrefixes, callerPrefixes) 77 } 78 79 /** 80 * Parses the `<apiPrefixes>` or `<callerPrefixes>` element and extracts the individual prefixes. 81 * 82 * @param ruleElement The `<rule>` element containing the prefixes. 83 * @param tagName The name of the tag to parse ("apiPrefixes" or "callerPrefixes"). 84 * @return A list of prefixes. 85 */ parsePrefixesnull86 private fun parsePrefixes(ruleElement: Element, tagName: String): List<String> { 87 val prefixes = mutableListOf<String>() 88 val prefixesElement = ruleElement.getElementsByTagName(tagName).item(0) as Element 89 val prefixElements = prefixesElement.getElementsByTagName("prefix") 90 for (j in 0 until prefixElements.length) { 91 prefixes.add(prefixElements.item(j).textContent) 92 } 93 return prefixes 94 } 95 } 96