• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 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.asm
18 
19 import java.io.BufferedInputStream
20 import java.util.HashMap
21 import java.util.zip.ZipFile
22 import org.objectweb.asm.ClassReader
23 import org.objectweb.asm.tree.ClassNode
24 import org.objectweb.asm.tree.MethodNode
25 
26 /** Load all classes from a .jar file. */
27 fun loadClassStructure(inJar: String): ClassNodes {
28     val allClasses = ClassNodes(inJar)
29 
30     ZipFile(inJar).use { inZip ->
31         val inEntries = inZip.entries()
32         while (inEntries.hasMoreElements()) {
33             val entry = inEntries.nextElement()
34             if (!entry.name.endsWith(".class")) {
35                 continue
36             }
37             val bis = BufferedInputStream(inZip.getInputStream(entry))
38             val cr = ClassReader(bis)
39             val cn = ClassNode()
40             cr.accept(
41                 cn,
42                 ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES
43             )
44             allClasses.addClass(cn)
45         }
46     }
47     return allClasses
48 }
49 
50 /** Store all classes loaded from a jar file. */
51 class ClassNodes(val sourceJarFile: String) {
52 
53     private val mClasses: MutableMap<String, ClassNode> = HashMap()
54 
55     /** Add a class node. */
addClassnull56     fun addClass(node: ClassNode) {
57         mClasses.putIfAbsent(node.name.toJvmClassName(), node)
58     }
59 
60     /** Find the ClassNode with the given class name. */
findClassnull61     fun findClass(className: String): ClassNode? {
62         return mClasses[className.toJvmClassName()]
63     }
64 
65     /** Check whether the given class exists or not. */
hasClassnull66     fun hasClass(className: String): Boolean {
67         return mClasses.containsKey(className.toJvmClassName())
68     }
69 
70     /** Find the method member of a class. Returns null if it doesn't exist. */
findMethodnull71     fun findMethod(className: String, methodName: String, desc: String): MethodNode? {
72         return findClass(className)?.methods?.firstOrNull {
73             it.name == methodName && it.desc == desc }?.let { node -> return node }
74     }
75 
76     /** @return true if a class has a class initializer. */
hasClassInitializernull77     fun hasClassInitializer(className: String): Boolean {
78         return findMethod(className, CLASS_INITIALIZER_NAME, CLASS_INITIALIZER_DESC) != null
79     }
80 }
81