commit f3e72d2f6581712c28cbd35541ffbf9bcb59dea6 Author: Karsten Loesing karsten.loesing@gmx.net Date: Fri Dec 16 12:57:45 2011 +0100
Implement a minimal relay descriptor reader. --- .../descriptor/impl/DescriptorFileImpl.java | 44 ++++++++ .../descriptor/impl/RelayDescriptorReaderImpl.java | 110 +++++++++++++++++++- 2 files changed, 150 insertions(+), 4 deletions(-)
diff --git a/src/org/torproject/descriptor/impl/DescriptorFileImpl.java b/src/org/torproject/descriptor/impl/DescriptorFileImpl.java new file mode 100644 index 0000000..0dd984d --- /dev/null +++ b/src/org/torproject/descriptor/impl/DescriptorFileImpl.java @@ -0,0 +1,44 @@ +/* Copyright 2011 The Tor Project + * See LICENSE for licensing information */ +package org.torproject.descriptor.impl; + +import java.io.File; +import java.util.List; +import org.torproject.descriptor.Descriptor; +import org.torproject.descriptor.DescriptorFile; + +public class DescriptorFileImpl implements DescriptorFile { + + private File directory; + protected void setDirectory(File directory) { + this.directory = directory; + } + public File getDirectory() { + return this.file; + } + + private File file; + protected void setFile(File file) { + this.file = file; + } + public File getFile() { + return this.file; + } + + private long lastModified; + protected void setLastModified(long lastModified) { + this.lastModified = lastModified; + } + public long getLastModified() { + return this.lastModified; + } + + private List<Descriptor> descriptors; + protected void setDescriptors(List<Descriptor> descriptors) { + this.descriptors = descriptors; + } + public List<Descriptor> getDescriptors() { + return this.descriptors; + } +} + diff --git a/src/org/torproject/descriptor/impl/RelayDescriptorReaderImpl.java b/src/org/torproject/descriptor/impl/RelayDescriptorReaderImpl.java index 8421f80..064983e 100644 --- a/src/org/torproject/descriptor/impl/RelayDescriptorReaderImpl.java +++ b/src/org/torproject/descriptor/impl/RelayDescriptorReaderImpl.java @@ -2,38 +2,140 @@ * See LICENSE for licensing information */ package org.torproject.descriptor.impl;
+import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; +import java.util.Stack; +import org.torproject.descriptor.Descriptor; import org.torproject.descriptor.DescriptorFile; import org.torproject.descriptor.RelayDescriptorReader; +import org.torproject.descriptor.RelayNetworkStatusConsensus; +import org.torproject.descriptor.RelayNetworkStatusVote;
public class RelayDescriptorReaderImpl implements RelayDescriptorReader {
+ private List<File> directories = new ArrayList<File>(); public void addDirectory(File directory) { - /* TODO Implement me. */ + this.directories.add(directory); }
public void setExcludeFile(File fileToExclude) { + throw new UnsupportedOperationException("Not implemented yet."); /* TODO Implement me. */ }
public void setExcludeFiles(Set<File> filesToExclude) { + throw new UnsupportedOperationException("Not implemented yet."); /* TODO Implement me. */ }
- public void setExcludeFile(File fileToExclude, long lastModifiedMillis) { + public void setExcludeFile(File fileToExclude, + long lastModifiedMillis) { + throw new UnsupportedOperationException("Not implemented yet."); /* TODO Implement me. */ }
public void setExcludeFiles(Map<File, Long> filesToExclude) { + throw new UnsupportedOperationException("Not implemented yet."); /* TODO Implement me. */ }
public Iterator<DescriptorFile> readDescriptors() { - /* TODO Implement me. */ - return new BlockingIteratorImpl<DescriptorFile>(); + BlockingIteratorImpl<DescriptorFile> descriptorQueue = + new BlockingIteratorImpl<DescriptorFile>(); + DescriptorReader reader = new DescriptorReader(this.directories, + descriptorQueue); + new Thread(reader).start(); + return descriptorQueue; + } + + private static class DescriptorReader implements Runnable { + private List<File> directories; + private BlockingIteratorImpl<DescriptorFile> descriptorQueue; + private DescriptorReader(List<File> directories, + BlockingIteratorImpl<DescriptorFile> descriptorQueue) { + this.directories = directories; + this.descriptorQueue = descriptorQueue; + } + public void run() { + for (File directory : this.directories) { + try { + Stack<File> files = new Stack<File>(); + files.add(directory); + while (!files.isEmpty()) { + File file = files.pop(); + if (file.isDirectory()) { + files.addAll(Arrays.asList(file.listFiles())); + } else { + try { + List<Descriptor> parsedDescriptors = this.readFile(file); + DescriptorFileImpl descriptorFile = + new DescriptorFileImpl(); + descriptorFile.setDirectory(directory); + descriptorFile.setFile(file); + descriptorFile.setLastModified(file.lastModified()); + descriptorFile.setDescriptors(parsedDescriptors); + this.descriptorQueue.add(descriptorFile); + } catch (DescriptorParseException e) { + /* TODO Handle me. */ + } + } + } + } catch (IOException e) { + System.err.println("Error while reading descriptors in '" + + directory.getAbsolutePath() + "'."); + /* TODO Handle this exception somehow. */ + } finally { + this.descriptorQueue.setOutOfDescriptors(); + } + } + } + private List<Descriptor> readFile(File file) throws IOException, + DescriptorParseException { + FileInputStream fis = new FileInputStream(file); + BufferedInputStream bis = new BufferedInputStream(fis); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int len; + byte[] data = new byte[1024]; + while ((len = bis.read(data, 0, 1024)) >= 0) { + baos.write(data, 0, len); + } + bis.close(); + byte[] rawDescriptorBytes = baos.toByteArray(); + /* TODO This consensus/vote detection is a hack. */ + boolean isConsensus = false; + if (file.getName().contains("consensus")) { + isConsensus = true; + } else if (file.getName().contains("vote")) { + } else { + throw new RuntimeException("Unknown descriptor type in '" + + file.getAbsolutePath() + "."); + } + return this.parseDescriptors(rawDescriptorBytes, isConsensus); + } + private List<Descriptor> parseDescriptors(byte[] rawDescriptorBytes, + boolean isConsensus) throws DescriptorParseException { + List<Descriptor> parsedDescriptors = new ArrayList<Descriptor>(); + if (isConsensus) { + List<RelayNetworkStatusConsensus> parsedConsensuses = + RelayNetworkStatusConsensusImpl.parseConsensuses( + rawDescriptorBytes); + parsedDescriptors.addAll(parsedConsensuses); + } else { + List<RelayNetworkStatusVote> parsedVotes = + RelayNetworkStatusVoteImpl.parseVotes(rawDescriptorBytes); + parsedDescriptors.addAll(parsedVotes); + } + return parsedDescriptors; + } } }