package be.shouldit.proxy.lib; import android.os.Parcel; import android.os.Parcelable; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.sql.Array; import java.text.DateFormat; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import be.shouldit.proxy.lib.enums.CheckStatusValues; import be.shouldit.proxy.lib.enums.ProxyStatusProperties; import timber.log.Timber; public class ProxyStatus implements Parcelable { SortedMap<ProxyStatusProperties, ProxyStatusItem> properties; public Date checkedDate; public String getCheckedDateString() { if (checkedDate != null) { DateFormat df = DateFormat.getDateTimeInstance(); return df.format(checkedDate); } else return null; } public CheckStatusValues getCheckingStatus() { synchronized (this) { for (ProxyStatusItem prop : properties.values()) { if (prop.effective) { if (prop.status == CheckStatusValues.NOT_CHECKED) return CheckStatusValues.NOT_CHECKED; } } for (ProxyStatusItem prop : properties.values()) { if (prop.effective) { if (prop.status == CheckStatusValues.CHECKING) return CheckStatusValues.CHECKING; } } return CheckStatusValues.CHECKED; } } public ProxyStatusItem getProperty(ProxyStatusProperties property) { synchronized (this) { return properties.get(property); } } public ProxyStatus() { clear(); } public void clear() { synchronized (this) { checkedDate = null; properties = Collections.synchronizedSortedMap(new TreeMap<ProxyStatusProperties, ProxyStatusItem>(new ProxyStatusPropertiesComparator())); properties.put(ProxyStatusProperties.WIFI_ENABLED, new ProxyStatusItem(ProxyStatusProperties.WIFI_ENABLED)); properties.put(ProxyStatusProperties.WIFI_SELECTED, new ProxyStatusItem(ProxyStatusProperties.WIFI_SELECTED)); properties.put(ProxyStatusProperties.WEB_REACHABLE, new ProxyStatusItem(ProxyStatusProperties.WEB_REACHABLE)); properties.put(ProxyStatusProperties.PROXY_ENABLED, new ProxyStatusItem(ProxyStatusProperties.PROXY_ENABLED)); properties.put(ProxyStatusProperties.PROXY_VALID_HOSTNAME, new ProxyStatusItem(ProxyStatusProperties.PROXY_VALID_HOSTNAME)); properties.put(ProxyStatusProperties.PROXY_VALID_PORT, new ProxyStatusItem(ProxyStatusProperties.PROXY_VALID_PORT)); properties.put(ProxyStatusProperties.PROXY_REACHABLE, new ProxyStatusItem(ProxyStatusProperties.PROXY_REACHABLE)); properties.put(ProxyStatusProperties.PAC_VALID_URI, new ProxyStatusItem(ProxyStatusProperties.PAC_VALID_URI)); } } public void startchecking() { synchronized (this) { checkedDate = new Date(); for (ProxyStatusItem prop : properties.values()) { prop.status = CheckStatusValues.CHECKING; } } } public void set(ProxyStatusItem item) { set(item.statusCode, item.status, item.result, item.effective, item.message, new Date()); } public void set(ProxyStatusProperties psp, CheckStatusValues stat, Boolean res, String msg, Date checkDate) { set(psp, stat, res, true, msg, checkDate); } public void set(ProxyStatusProperties psp, CheckStatusValues stat, boolean res, boolean effect) { set(psp, stat, res, effect, "", new Date()); } public void set(ProxyStatusProperties psp, CheckStatusValues stat, Boolean res, Boolean effect, String msg, Date checkDate) { synchronized (this) { if (properties.containsKey(psp)) { properties.get(psp).status = stat; properties.get(psp).result = res; properties.get(psp).effective = effect; properties.get(psp).message = msg; properties.get(psp).checkedDate = checkDate; } else { Timber.e("Cannot find status code: " + psp); } } } public ProxyStatusItem getMostRelevantErrorProxyStatusItem() { synchronized (this) { for (ProxyStatusItem prop : properties.values()) { if (prop.effective) { if (prop.result == false) { return prop; } } } return null; } } public Integer getErrorCount() { synchronized (this) { int count = 0; for (ProxyStatusItem prop : properties.values()) { if (prop.effective) { if (prop.result == false) { count++; } } } return count; } } @Override public String toString() { synchronized (this) { StringBuilder sb = new StringBuilder(); if (checkedDate != null) { DateFormat df = DateFormat.getDateTimeInstance(); sb.append("Start checking at: " + df.format(checkedDate) + "\n"); } else { sb.append("Not checked"); } for (ProxyStatusItem prop : properties.values()) { sb.append(prop.toString() + "\n"); } return sb.toString(); } } public JSONObject toJSON() { JSONObject jsonObject = new JSONObject(); try { if (checkedDate != null) { DateFormat df = DateFormat.getDateTimeInstance(); jsonObject.put("checked_date",df.format(checkedDate)); } else { jsonObject.put("checked_date", null); } JSONArray propertiesArray = new JSONArray(); for (ProxyStatusItem prop : properties.values()) { propertiesArray.put(prop.toJSON()); } jsonObject.put("check_properties", propertiesArray); } catch (JSONException e) { Timber.e(e, "Exception converting to JSON object ProxyStatus"); } return jsonObject; } public String toShortString() { synchronized (this) { StringBuilder sb = new StringBuilder(); for (ProxyStatusItem prop : properties.values()) { if (prop.effective) // Print only effective status items { sb.append(prop.toShortString() + " - "); } } return sb.toString(); } } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(this.properties.size()); for (final Map.Entry<ProxyStatusProperties, ProxyStatusItem> entry : this.properties.entrySet()) { dest.writeInt(entry.getKey() == null ? -1 : entry.getKey().ordinal()); dest.writeParcelable(entry.getValue(),flags); } dest.writeLong(checkedDate != null ? checkedDate.getTime() : -1); } private ProxyStatus(Parcel in) { final int size = in.readInt(); this.properties = Collections.synchronizedSortedMap(new TreeMap<ProxyStatusProperties, ProxyStatusItem>(new ProxyStatusPropertiesComparator())); for (int i=0; i<size; i++) { final int tmpStatusCode = in.readInt(); ProxyStatusProperties statusProperty = tmpStatusCode == -1 ? null : ProxyStatusProperties.values()[tmpStatusCode]; ProxyStatusItem item = in.readParcelable(ProxyStatusItem.class.getClassLoader()); this.properties.put(statusProperty, item); } long tmpCheckedDate = in.readLong(); this.checkedDate = tmpCheckedDate == -1 ? null : new Date(tmpCheckedDate); } public static final Creator<ProxyStatus> CREATOR = new Creator<ProxyStatus>() { public ProxyStatus createFromParcel(Parcel source) {return new ProxyStatus(source);} public ProxyStatus[] newArray(int size) {return new ProxyStatus[size];} }; @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof ProxyStatus)) return false; ProxyStatus that = (ProxyStatus) o; if (checkedDate != null ? !checkedDate.equals(that.checkedDate) : that.checkedDate != null) return false; if (properties != null) { if (!Arrays.equals(properties.keySet().toArray(), that.properties.keySet().toArray())) return false; if (!Arrays.equals(properties.values().toArray(), that.properties.values().toArray())) return false; } else if (that.properties != null) { return false; } return true; } }