org.comixwall.pffw.InfoRules.java Source code

Java tutorial

Introduction

Here is the source code for org.comixwall.pffw.InfoRules.java

Source

/*
 * Copyright (C) 2017-2018 Soner Tari
 *
 * This file is part of PFFW.
 *
 * PFFW is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PFFW is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PFFW.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.comixwall.pffw;

import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

import static org.comixwall.pffw.MainActivity.cache;
import static org.comixwall.pffw.MainActivity.controller;
import static org.comixwall.pffw.MainActivity.fragment;
import static org.comixwall.pffw.MainActivity.logger;
import static org.comixwall.pffw.Utils.processException;
import static org.comixwall.pffw.Utils.showMessage;

public class InfoRules extends Fragment
        implements SwipeRefreshLayout.OnRefreshListener, RefreshTimer.OnTimeoutListener,
        RecyclerTouchListener.OnItemClickListener, ControllerTask.ControllerTaskListener {

    private InfoRulesCache mModuleCache;

    private RefreshTimer mTimer;
    private int mRefreshTimeout = 10;

    private SwipeRefreshLayout swipeRefresh;

    private JSONArray mRulesJsonArray;
    private final List<Rule> mRulesList = new ArrayList<>();
    private RuleRecyclerAdapter mRulesAdapter;

    private String mLastError;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.info_rules, container, false);

        swipeRefresh = view.findViewById(R.id.swipeRefresh);
        swipeRefresh.setOnRefreshListener(this);

        RecyclerView rvRules = view.findViewById(R.id.recyclerViewRules);

        rvRules.setLayoutManager(new LinearLayoutManager(getActivity()));
        rvRules.setItemAnimator(new DefaultItemAnimator());
        rvRules.addItemDecoration(new RecyclerDivider(getActivity(), LinearLayoutManager.VERTICAL));
        mRulesAdapter = new RuleRecyclerAdapter(mRulesList);
        rvRules.setAdapter(mRulesAdapter);
        rvRules.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), this));

        if (cache.infoRules == null) {
            cache.infoRules = new InfoRulesCache();
        }
        mModuleCache = cache.infoRules;

        return view;
    }

    @Override
    public void onPause() {
        super.onPause();

        mModuleCache.mRulesJsonArray = mRulesJsonArray;

        // ATTENTION: It is very important to cancel the timer
        mTimer.cancel();
    }

    @Override
    public void onResume() {
        super.onResume();

        fragment = this;

        mRulesJsonArray = mModuleCache.mRulesJsonArray;

        if (mRulesJsonArray == null) {
            getInfo();
        } else {
            updateInfo();
        }

        // Schedule the timer here, not in onCreateView(), because mRefreshTimeout may be updated in getInfo()
        mTimer = new RefreshTimer((MainActivity) getActivity(), this);
        mTimer.start(mRefreshTimeout);
    }

    @Override
    public void onTimeout() {
        getInfo();
    }

    @Override
    public void executePreTask() {
    }

    @Override
    public void preExecute() {
        swipeRefresh.setRefreshing(true);
    }

    @Override
    public boolean executeTask() {
        Boolean retval = true;
        try {
            String output = controller.execute("pf", "GetPfRulesInfo");

            JSONArray jsonArray = new JSONArray(output);
            mRulesJsonArray = new JSONArray(jsonArray.get(0).toString());

            output = controller.execute("pf", "GetReloadRate");

            int timeout = Integer.parseInt(new JSONArray(output).get(0).toString());
            mRefreshTimeout = timeout < 10 ? 10 : timeout;

        } catch (Exception e) {
            mLastError = processException(e);
            retval = false;
        }
        return retval;
    }

    @Override
    public void postExecute(boolean result) {
        if (result) {
            updateInfo();
        } else {
            showMessage(this, "Error: " + mLastError);
        }

        swipeRefresh.setRefreshing(false);
    }

    @Override
    public void executeOnCancelled() {
        swipeRefresh.setRefreshing(false);
    }

    private void getInfo() {
        ControllerTask.run(this, this);
    }

    private void updateInfo() {
        updateRuleList(mRulesJsonArray, mRulesList);
        mRulesAdapter.notifyDataSetChanged();
    }

    private void updateRuleList(JSONArray jsonArray, List<Rule> list) {
        try {
            list.clear();

            int i = 0;
            while (i < jsonArray.length()) {
                list.add(Rule.newInstance(jsonArray.getJSONObject(i++)));
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.warning("updateRuleList exception= " + e.toString());
        }
    }

    @Override
    public void onRefresh() {
        getInfo();
    }

    @Override
    public void onItemClick(View view) {

        TextView tvRule = view.findViewById(R.id.rule);
        TextView tvEvalsStates = view.findViewById(R.id.evalsStates);

        int lines = 10;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            if (tvRule.getMaxLines() != 1) {
                lines = 1;
            }
        }

        tvRule.setMaxLines(lines);
        tvEvalsStates.setMaxLines(lines);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.menuRefresh) {
            getInfo();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

class Rule {
    String num;
    String rule;
    String evaluations;
    String packets;
    String bytes;
    String states;
    String inserted;
    String stateCreations;

    static Rule newInstance(JSONObject ruleEntry) {
        Rule rule = new Rule();
        try {
            rule.num = ruleEntry.getString("number");
            rule.rule = ruleEntry.getString("rule");
            rule.evaluations = ruleEntry.getString("evaluations");
            rule.packets = ruleEntry.getString("packets");
            rule.bytes = ruleEntry.getString("bytes");
            rule.states = ruleEntry.getString("states");
            rule.inserted = ruleEntry.getString("inserted");
            rule.stateCreations = ruleEntry.getString("stateCreations");
        } catch (Exception e) {
            e.printStackTrace();
            logger.warning("Rule newInstance exception= " + e.toString());
        }
        return rule;
    }
}

class RuleRecyclerAdapter extends RecyclerView.Adapter<RuleRecyclerAdapter.RuleViewHolder> {

    private final List<Rule> ruleList;

    class RuleViewHolder extends RecyclerView.ViewHolder {
        final TextView packetsBytes;
        final TextView rule;
        final TextView evalsStates;
        final TextView number;
        final TextView inserted;
        final TextView image;

        RuleViewHolder(View view) {
            super(view);
            packetsBytes = view.findViewById(R.id.packetsBytes);
            rule = view.findViewById(R.id.rule);
            evalsStates = view.findViewById(R.id.evalsStates);
            number = view.findViewById(R.id.number);
            inserted = view.findViewById(R.id.inserted);
            image = view.findViewById(R.id.image);
        }
    }

    RuleRecyclerAdapter(List<Rule> list) {
        this.ruleList = list;
    }

    @Override
    public RuleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.rule, parent, false);

        return new RuleViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(RuleViewHolder holder, int position) {

        Rule rule = ruleList.get(position);

        holder.packetsBytes.setText(String.format(
                holder.packetsBytes.getResources().getString(R.string.packets_bytes), rule.packets, rule.bytes));
        holder.rule.setText(rule.rule);
        holder.number.setText(rule.num);
        holder.inserted.setText(rule.inserted);
        holder.evalsStates.setText(
                String.format(holder.evalsStates.getResources().getString(R.string.evals_states_statecreats),
                        rule.evaluations, rule.states, rule.stateCreations));

        int image;
        String caption;

        if (rule.rule.matches("^block\\s+.*")) {
            image = R.drawable.block;
            caption = "B";
        } else if (rule.rule.matches("^pass\\s+.*")) {
            image = R.drawable.pass;
            caption = "P";
        } else {
            image = R.drawable.match;
            caption = "M";
        }

        holder.image.setBackgroundResource(image);
        holder.image.setText(caption);
    }

    @Override
    public int getItemCount() {
        return ruleList.size();
    }
}

class InfoRulesCache {
    JSONArray mRulesJsonArray;
}