DictionarySingleThreadProxy.java

package edu.jiangxin.apktoolbox.file.password.recovery.category.dictionary.singlethread;

import edu.jiangxin.apktoolbox.file.core.EncoderDetector;
import edu.jiangxin.apktoolbox.file.password.recovery.RecoveryPanel;
import edu.jiangxin.apktoolbox.file.password.recovery.category.ICategory;
import edu.jiangxin.apktoolbox.utils.Utils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.swing.*;
import java.io.*;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class DictionarySingleThreadProxy implements ICategory {
    private static final Logger logger = LogManager.getLogger(DictionarySingleThreadProxy.class.getSimpleName());

    private boolean isCancelled;

    private static class DictionarySingleThreadProxyHolder {
        private static final DictionarySingleThreadProxy instance = new DictionarySingleThreadProxy();
    }

    private DictionarySingleThreadProxy() {
    }

    public static DictionarySingleThreadProxy getInstance() {
        return DictionarySingleThreadProxy.DictionarySingleThreadProxyHolder.instance;
    }

    private String startAndGet(String charsetName, RecoveryPanel panel) {
        isCancelled = false;
        Predicate<String> isRecoveringPredicate = password -> (!isCancelled);
        Function<String, Stream<String>> generator = password -> {
            panel.setCurrentPassword(password);
            panel.increaseProgressBarValue();
            return Stream.of(password.toLowerCase(), password.toUpperCase());
        };
        Predicate<String> verifier = panel.getCurrentFileChecker()::checkPassword;
        try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(panel.getDictionaryFile()), charsetName))) {
            // java.util.stream.BaseStream.parallel can not increase the speed in test
            Optional<String> password = br.lines().takeWhile(isRecoveringPredicate).flatMap(generator).filter(verifier).findFirst();
            return password.orElse(null);
        } catch (FileNotFoundException e) {
            logger.info("FileNotFoundException");
        } catch (IOException e) {
            logger.info("IOException");
        }
        return null;
    }

    @Override
    public void start(RecoveryPanel panel) {
        File dictionaryFile = panel.getDictionaryFile();
        if (!dictionaryFile.isFile()) {
            JOptionPane.showMessageDialog(panel, "Invalid dictionary file");
            return;
        }
        String charsetName = EncoderDetector.judgeFile(dictionaryFile.getAbsolutePath());
        logger.info("dictionary file: {}, charset: {}", dictionaryFile.getAbsolutePath(), charsetName);
        if (charsetName == null) {
            JOptionPane.showMessageDialog(panel, "Invalid charsetName");
            return;
        }
        panel.resetProgressMaxValue(Utils.getFileLineCount(dictionaryFile));
        String password = startAndGet(charsetName, panel);
        panel.showResultWithDialog(password);
    }

    @Override
    public void cancel() {
        isCancelled = true;
    }
}