All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.reandroid.dex.model.DexTry Maven / Gradle / Ivy

/*
 *  Copyright (C) 2022 github.com/REAndroid
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.reandroid.dex.model;

import com.reandroid.dex.base.DexException;
import com.reandroid.dex.data.InstructionList;
import com.reandroid.dex.ins.ExceptionHandler;
import com.reandroid.dex.ins.ExceptionLabel;
import com.reandroid.dex.ins.Ins;
import com.reandroid.dex.ins.TryItem;
import com.reandroid.dex.key.Key;
import com.reandroid.dex.key.TypeKey;
import com.reandroid.dex.smali.SmaliWriter;
import com.reandroid.utils.collection.CollectionUtil;
import com.reandroid.utils.collection.ComputeIterator;
import com.reandroid.utils.collection.EmptyIterator;
import com.reandroid.utils.collection.FilterIterator;

import java.io.IOException;
import java.util.Iterator;

public class DexTry extends DexCode {

    private final DexMethod dexMethod;
    private final TryItem tryItem;

    public DexTry(DexMethod dexMethod, TryItem tryItem) {
        super();
        this.dexMethod = dexMethod;
        this.tryItem = tryItem;
    }

    public DexInstruction getFirst(){
        return CollectionUtil.getFirst(getInstructions());
    }
    public void setFirst(DexInstruction instruction){
        setStartAddress(instruction.getAddress());
    }
    public DexInstruction getLast(){
        return CollectionUtil.getLast(getInstructions());
    }
    public void setLast(DexInstruction instruction){
        setEndAddress(instruction.getAddress() + instruction.getCodeUnits());
    }

    public Iterator getInstructions(){
        InstructionList instructionList = getDexMethod()
                .getDefinition()
                .getInstructionList();
        if(instructionList == null){
            return EmptyIterator.of();
        }
        Iterator iterator = FilterIterator.of(instructionList.iterator(),
                ins -> {
                    int address = ins.getAddress();
                    return address >= getStartAddress() && address < getEndAddress();
                });
        return DexInstruction.create(getDexMethod(), iterator);
    }
    public int getStartAddress(){
        return getTryItem().getStartAddress();
    }
    public void setStartAddress(int address){
        getTryItem().setStartAddress(address);
    }
    public int getEndAddress(){
        TryItem tryItem = getTryItem();
        return tryItem.getStartAddress() + tryItem.getCatchCodeUnit();
    }
    public void setEndAddress(int address){
        TryItem tryItem = getTryItem();
        int start = tryItem.getStartAddress();
        if(address < start){
            throw new DexException("Invalid try end address "
                    + address + "<" + start);
        }
        getTryItem().setCatchCodeUnit(address - start);
    }
    public DexCatch getCatchAll(){
        return create(getTryItem().getCatchAllHandler());
    }
    public DexCatch getOrCreateCatchAll() {
        TryItem tryItem = getTryItem();
        boolean hasCatchAll = tryItem.hasCatchAllHandler();
        DexCatch dexCatch = create(getTryItem().getOrCreateCatchAll());
        if(!hasCatchAll){
            dexCatch.setCatchAddress(getEndAddress());
        }
        return dexCatch;
    }
    public DexCatch getCatch(TypeKey typeKey) {
        return create(getTryItem().getExceptionHandler(typeKey));
    }
    public int getCatchCount() {
        TryItem tryItem = getTryItem();
        int count = 0;
        if(tryItem.hasCatchAllHandler()){
            count = 1;
        }
        count += tryItem.getCatchTypedHandlersCount();
        return count;
    }
    public Iterator getCatches(){
        return ComputeIterator.of(getTryItem().getExceptionHandlers(),
                this::create);
    }
    DexCatch create(ExceptionHandler handler){
        if(handler != null){
            return new DexCatch(this, handler);
        }
        return null;
    }
    @Override
    public void removeSelf(){
        getTryItem().removeSelf();
    }
    public TryItem getTryItem() {
        return tryItem;
    }

    @Override
    public boolean uses(Key key) {
        Iterator iterator = getCatches();
        while (iterator.hasNext()){
            DexCatch dexCatch = iterator.next();
            if(dexCatch.uses(key)){
                return true;
            }
        }
        return false;
    }

    @Override
    public DexMethod getDexMethod() {
        return dexMethod;
    }
    @Override
    public void append(SmaliWriter writer) throws IOException {
        TryItem tryItem = getTryItem();
        Iterator handlers = tryItem.getExceptionHandlers();
        if(!handlers.hasNext()){
            writer.appendComment("Empty try-catch");
            writer.newLine();
            return;
        }
        Object previous = null;
        while (handlers.hasNext()){
            ExceptionLabel label = handlers.next().getStartLabel();
            if(label.isEqualExtraLine(previous)){
                continue;
            }
            previous = label;
            writer.newLine();
            label.appendExtra(writer);
        }
        writer.indentPlus();
        Iterator instructions = getInstructions();
        writer.appendAll(instructions, true);
        writer.indentMinus();
        handlers = tryItem.getExceptionHandlers();
        previous = null;
        while (handlers.hasNext()){
            ExceptionLabel label = handlers.next().getEndLabel();
            if(label.isEqualExtraLine(previous)){
                continue;
            }
            previous = label;
            writer.newLine();
            label.appendExtra(writer);
        }
        handlers = tryItem.getExceptionHandlers();
        while (handlers.hasNext()){
            ExceptionLabel label = handlers.next().getHandlerLabel();
            writer.newLine();
            label.appendExtra(writer);
        }
    }

    public static Iterator create(DexMethod dexMethod, Iterator iterator){
        if(dexMethod == null){
            return EmptyIterator.of();
        }
        return ComputeIterator.of(iterator, tryItem -> create(dexMethod, tryItem));
    }
    public static DexTry create(DexMethod dexMethod, TryItem tryItem) {
        if(dexMethod == null || tryItem == null){
            return null;
        }
        return new DexTry(dexMethod, tryItem);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy