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 package com.android.dependencymapper; 17 18 import com.android.dependencymapper.DependencyProto; 19 20 import com.google.gson.Gson; 21 import com.google.gson.GsonBuilder; 22 23 import java.io.FileWriter; 24 import java.io.IOException; 25 import java.io.OutputStream; 26 import java.nio.file.Files; 27 import java.nio.file.Path; 28 import java.util.Enumeration; 29 import java.util.HashMap; 30 import java.util.HashSet; 31 import java.util.Map; 32 import java.util.Set; 33 import java.util.jar.JarEntry; 34 import java.util.jar.JarFile; 35 36 public class Utils { 37 trimAndConvertToPackageBasedPath(String fileBasedPath)38 public static String trimAndConvertToPackageBasedPath(String fileBasedPath) { 39 // Remove ".class" from the fileBasedPath, then replace "/" with "." 40 return fileBasedPath.replaceAll("\\..*", "").replaceAll("/", "."); 41 } 42 buildPackagePrependedClassSource(String qualifiedClassPath, String classSource)43 public static String buildPackagePrependedClassSource(String qualifiedClassPath, 44 String classSource) { 45 // Find the location of the start of classname in the qualifiedClassPath 46 int classNameSt = qualifiedClassPath.lastIndexOf(".") + 1; 47 // Replace the classname in qualifiedClassPath with classSource 48 return qualifiedClassPath.substring(0, classNameSt) + classSource; 49 } 50 writeContentsToJson(DependencyProto.FileDependencyList contents, Path jsonOut)51 public static void writeContentsToJson(DependencyProto.FileDependencyList contents, Path jsonOut) { 52 Gson gson = new GsonBuilder().setPrettyPrinting().create(); 53 Map<String, Set<String>> jsonMap = new HashMap<>(); 54 for (DependencyProto.FileDependency fileDependency : contents.getFileDependencyList()) { 55 jsonMap.putIfAbsent(fileDependency.getFilePath(), 56 Set.copyOf(fileDependency.getFileDependenciesList())); 57 } 58 String json = gson.toJson(jsonMap); 59 try (FileWriter file = new FileWriter(jsonOut.toFile())) { 60 file.write(json); 61 } catch (IOException e) { 62 System.err.println("Error writing json output to: " + jsonOut); 63 throw new RuntimeException(e); 64 } 65 } 66 writeContentsToProto(DependencyProto.FileDependencyList usages, Path protoOut)67 public static void writeContentsToProto(DependencyProto.FileDependencyList usages, Path protoOut) { 68 try { 69 OutputStream outputStream = Files.newOutputStream(protoOut); 70 usages.writeDelimitedTo(outputStream); 71 } catch (IOException e) { 72 System.err.println("Error writing proto output to: " + protoOut); 73 throw new RuntimeException(e); 74 } 75 } 76 listClassesInJar(Path classesJarPath)77 public static Set<String> listClassesInJar(Path classesJarPath) { 78 Set<String> classes = new HashSet<>(); 79 try (JarFile jarFile = new JarFile(classesJarPath.toFile())) { 80 Enumeration<JarEntry> entries = jarFile.entries(); 81 while (entries.hasMoreElements()) { 82 JarEntry entry = entries.nextElement(); 83 if (entry.getName().endsWith(".class")) { 84 String name = Utils.trimAndConvertToPackageBasedPath(entry.getName()); 85 classes.add(name); 86 } 87 } 88 } catch (IOException e) { 89 System.err.println("Error reading the jar file at: " + classesJarPath); 90 throw new RuntimeException(e); 91 } 92 return classes; 93 } 94 } 95