Java tutorial
/* Copyright 2010 The Tor Project * See LICENSE for licensing information */ package org.torproject.ernie.db; import java.io.*; import java.text.*; import java.util.*; import java.util.logging.*; import org.apache.commons.codec.digest.*; public class BridgeDescriptorParser { private ConsensusStatsFileHandler csfh; private BridgeStatsFileHandler bsfh; private SanitizedBridgesWriter sbw; private Logger logger; public BridgeDescriptorParser(ConsensusStatsFileHandler csfh, BridgeStatsFileHandler bsfh, SanitizedBridgesWriter sbw) { this.csfh = csfh; this.bsfh = bsfh; this.sbw = sbw; this.logger = Logger.getLogger(BridgeDescriptorParser.class.getName()); } public void parse(byte[] allData, String dateTime, boolean sanitized) { try { BufferedReader br = new BufferedReader(new StringReader(new String(allData, "US-ASCII"))); SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); timeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); String hashedIdentity = null, platformLine = null, publishedLine = null, geoipStartTimeLine = null, bridgeStatsEndLine = null; boolean skip = false; String line = null; while ((line = br.readLine()) != null) { if (line.startsWith("r ")) { if (this.sbw != null) { if (sanitized) { this.sbw.storeSanitizedNetworkStatus(allData, dateTime); } else { this.sbw.sanitizeAndStoreNetworkStatus(allData, dateTime); } } int runningBridges = 0; while ((line = br.readLine()) != null) { if (line.startsWith("s ") && line.contains(" Running")) { runningBridges++; } } if (this.csfh != null) { this.csfh.addBridgeConsensusResults(dateTime, runningBridges); } } else if (line.startsWith("router ")) { if (this.sbw != null) { if (sanitized) { this.sbw.storeSanitizedServerDescriptor(allData); } else { this.sbw.sanitizeAndStoreServerDescriptor(allData); } } } else if (line.startsWith("extra-info ")) { if (this.sbw != null) { if (sanitized) { this.sbw.storeSanitizedExtraInfoDescriptor(allData); } else { this.sbw.sanitizeAndStoreExtraInfoDescriptor(allData); } } hashedIdentity = sanitized ? line.split(" ")[2] : DigestUtils.shaHex(line.split(" ")[2]).toUpperCase(); if (this.bsfh != null) { skip = this.bsfh.isKnownRelay(hashedIdentity); } } else if (!skip && line.startsWith("platform ")) { platformLine = line; } else if (!skip && line.startsWith("published ")) { publishedLine = line; } else if (line.startsWith("opt fingerprint") || line.startsWith("fingerprint")) { String identity = line .substring( line.startsWith("opt ") ? "opt fingerprint".length() : "fingerprint".length()) .replaceAll(" ", "").toLowerCase(); hashedIdentity = sanitized ? identity : DigestUtils.shaHex(identity).toUpperCase(); } else if (!skip && line.startsWith("geoip-start-time ")) { geoipStartTimeLine = line; } else if (!skip && line.startsWith("geoip-client-origins") && line.split(" ").length > 1) { if (publishedLine == null || geoipStartTimeLine == null) { this.logger.warning("Either published line or " + "geoip-start-time line is not present in " + (sanitized ? "sanitized" : "non-sanitized") + " bridge descriptors from " + dateTime + "."); break; } long published = timeFormat.parse(publishedLine.substring("published ".length())).getTime(); long started = timeFormat.parse(geoipStartTimeLine.substring("geoip-start-time ".length())) .getTime(); long seconds = (published - started) / 1000L; double allUsers = 0.0D; Map<String, String> obs = new HashMap<String, String>(); String[] parts = line.split(" ")[1].split(","); for (String p : parts) { String country = p.substring(0, 2); double users = ((double) Long.parseLong(p.substring(3)) - 4L) * 86400.0D / ((double) seconds); allUsers += users; obs.put(country, String.format("%.2f", users)); } obs.put("zy", String.format("%.2f", allUsers)); String date = publishedLine.split(" ")[1]; String time = publishedLine.split(" ")[2]; if (this.bsfh != null) { this.bsfh.addObs(hashedIdentity, date, time, obs); } } else if (!skip && line.startsWith("bridge-stats-end ")) { bridgeStatsEndLine = line; } else if (!skip && line.startsWith("bridge-ips") && line.split(" ").length > 1) { if (bridgeStatsEndLine == null) { this.logger.warning("bridge-ips line without preceding " + "bridge-stats-end line in " + (sanitized ? "sanitized" : "non-sanitized") + " bridge descriptor."); break; } double allUsers = 0.0D; Map<String, String> obs = new HashMap<String, String>(); String[] parts = line.split(" ")[1].split(","); for (String p : parts) { String country = p.substring(0, 2); double users = (double) Long.parseLong(p.substring(3)) - 4L; allUsers += users; obs.put(country, String.format("%.2f", users)); } obs.put("zy", String.format("%.2f", allUsers)); String date = bridgeStatsEndLine.split(" ")[1]; String time = bridgeStatsEndLine.split(" ")[2]; if (this.bsfh != null) { this.bsfh.addObs(hashedIdentity, date, time, obs); } } } if (this.bsfh != null && platformLine != null && platformLine.startsWith("platform Tor 0.2.2")) { String date = publishedLine.split(" ")[1]; String time = publishedLine.split(" ")[2]; this.bsfh.addZeroTwoTwoDescriptor(hashedIdentity, date, time); } } catch (IOException e) { this.logger.log(Level.WARNING, "Could not parse bridge descriptor.", e); return; } catch (ParseException e) { this.logger.log(Level.WARNING, "Could not parse bridge descriptor.", e); return; } } }