001/*
002 * Copyright (C) 2015-2021 KeepSafe Software
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package com.getkeepsafe.dexcount.treegen.workers;
017
018import com.getkeepsafe.dexcount.Deobfuscator;
019import com.getkeepsafe.dexcount.PackageTree;
020import com.getkeepsafe.dexcount.PrintOptions;
021import com.getkeepsafe.dexcount.source.SourceFile;
022import com.getkeepsafe.dexcount.source.SourceFiles;
023import org.apache.commons.io.IOUtils;
024import org.gradle.api.file.RegularFileProperty;
025import org.slf4j.Logger;
026import org.slf4j.LoggerFactory;
027
028import java.io.File;
029import java.io.IOException;
030import java.util.List;
031
032public abstract class LegacyWorker extends BaseWorker<LegacyWorker.Params> {
033    private static final Logger LOGGER = LoggerFactory.getLogger(LegacyWorker.class);
034
035    public interface Params extends BaseWorker.Params {
036        RegularFileProperty getInputFile();
037        RegularFileProperty getMappingFile();
038    }
039
040    @Override
041    protected PackageTree generatePackageTree() throws IOException {
042        PrintOptions options = getParameters().getPrintOptions().get();
043        Deobfuscator deobfuscator = Deobfuscator.create(getParameters().getMappingFile().getAsFile().getOrNull());
044        File inputFile = getParameters().getInputFile().getAsFile().get();
045        String fileName = inputFile.getName();
046
047        boolean isApk = fileName.endsWith(".apk");
048        boolean isAar = fileName.endsWith(".aar");
049        boolean isJar = fileName.endsWith(".jar");
050        boolean isAndroid = isApk || isAar;
051
052        if (!isApk && !isAar && !isJar) {
053            throw new IllegalStateException("File type is unclear: " + fileName);
054        }
055
056        PackageTree tree = new PackageTree(deobfuscator);
057
058        if (isAndroid) {
059            List<SourceFile> sourceFiles = SourceFiles.extractDexData(inputFile);
060            try {
061                sourceFiles.stream().flatMap(f -> f.getMethodRefs().stream()).forEach(tree::addMethodRef);
062                sourceFiles.stream().flatMap(f -> f.getFieldRefs().stream()).forEach(tree::addFieldRef);
063            } finally {
064                IOUtils.closeQuietly(sourceFiles.toArray(new SourceFile[0]));
065            }
066        }
067
068        SourceFile jar = null;
069        if (isAar && options.getPrintDeclarations()) {
070            jar = SourceFiles.extractJarFromAar(inputFile);
071        } else if (isJar && options.getPrintDeclarations()) {
072            jar = SourceFiles.extractJarFromJar(inputFile);
073        }
074
075        if (jar != null) {
076            try {
077                jar.getMethodRefs().forEach(tree::addDeclaredMethodRef);
078                jar.getFieldRefs().forEach(tree::addDeclaredFieldRef);
079            } finally {
080                IOUtils.closeQuietly(jar);
081            }
082        }
083
084        return tree;
085    }
086
087    @Override
088    protected String getInputRepresentation() {
089        return getParameters().getInputFile().getAsFile().get().getName();
090    }
091
092    @Override
093    protected Logger getLogger() {
094        return LOGGER;
095    }
096}