Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
The Tor Project
Network Health
Metrics
Library
Commits
df6bdc8d
Commit
df6bdc8d
authored
May 26, 2017
by
iwakeh
Committed by
Karsten Loesing
May 26, 2017
Browse files
Implements task-19607.
Use enums for keywords as well as enum sets and maps. Use constants for repeated strings.
parent
bd52bcae
Changes
21
Hide whitespace changes
Inline
Side-by-side
CHANGELOG.md
View file @
df6bdc8d
...
...
@@ -18,6 +18,11 @@
descriptor lines, as permitted by dir-spec.txt.
-
Streamline digest method names.
*
Minor changes
-
Turn keyword strings into enums and use the appropriate enum sets
and maps to avoid repeating string literals and to use more speedy
collection types.
# Changes in version 1.6.0 - 2017-02-17
...
...
src/main/java/org/torproject/descriptor/impl/BridgeExtraInfoDescriptorImpl.java
View file @
df6bdc8d
...
...
@@ -19,7 +19,7 @@ public class BridgeExtraInfoDescriptorImpl
List
<
ExtraInfoDescriptor
>
parsedDescriptors
=
new
ArrayList
<>();
List
<
byte
[]>
splitDescriptorsBytes
=
DescriptorImpl
.
splitRawDescriptorBytes
(
descriptorsBytes
,
"extra-info "
);
Key
.
EXTRA_INFO
.
keyword
+
SP
);
for
(
byte
[]
descriptorBytes
:
splitDescriptorsBytes
)
{
ExtraInfoDescriptor
parsedDescriptor
=
new
BridgeExtraInfoDescriptorImpl
(
descriptorBytes
,
...
...
src/main/java/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java
View file @
df6bdc8d
...
...
@@ -71,16 +71,16 @@ public class BridgeNetworkStatusImpl extends NetworkStatusImpl
this
.
enoughMtbfInfo
=
-
1
;
this
.
ignoringAdvertisedBws
=
-
1
;
Scanner
scanner
=
new
Scanner
(
new
String
(
headerBytes
)).
useDelimiter
(
"\n"
);
Scanner
scanner
=
new
Scanner
(
new
String
(
headerBytes
)).
useDelimiter
(
NL
);
while
(
scanner
.
hasNext
())
{
String
line
=
scanner
.
next
();
String
[]
parts
=
line
.
split
(
"[ \t]+"
);
String
keyword
=
parts
[
0
];
switch
(
key
word
)
{
case
"published"
:
Key
key
=
Key
.
get
(
parts
[
0
]
)
;
switch
(
key
)
{
case
PUBLISHED
:
this
.
parsePublishedLine
(
line
,
parts
);
break
;
case
"flag-thresholds"
:
case
FLAG_THRESHOLDS
:
this
.
parseFlagThresholdsLine
(
line
,
parts
);
break
;
default
:
...
...
src/main/java/org/torproject/descriptor/impl/BridgePoolAssignmentImpl.java
View file @
df6bdc8d
...
...
@@ -7,11 +7,9 @@ import org.torproject.descriptor.BridgePoolAssignment;
import
org.torproject.descriptor.DescriptorParseException
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.HashSet
;
import
java.util.EnumSet
;
import
java.util.List
;
import
java.util.Scanner
;
import
java.util.Set
;
import
java.util.SortedMap
;
import
java.util.TreeMap
;
...
...
@@ -24,7 +22,7 @@ public class BridgePoolAssignmentImpl extends DescriptorImpl
List
<
BridgePoolAssignment
>
parsedDescriptors
=
new
ArrayList
<>();
List
<
byte
[]>
splitDescriptorsBytes
=
DescriptorImpl
.
splitRawDescriptorBytes
(
descriptorsBytes
,
"bridge-pool-assignment "
);
Key
.
BRIDGE_POOL_ASSIGNMENT
.
keyword
+
SP
);
for
(
byte
[]
descriptorBytes
:
splitDescriptorsBytes
)
{
BridgePoolAssignment
parsedDescriptor
=
new
BridgePoolAssignmentImpl
(
descriptorBytes
,
...
...
@@ -39,20 +37,18 @@ public class BridgePoolAssignmentImpl extends DescriptorImpl
throws
DescriptorParseException
{
super
(
descriptorBytes
,
failUnrecognizedDescriptorLines
,
false
);
this
.
parseDescriptorBytes
();
Set
<
String
>
exactlyOnceKeywords
=
new
HashSet
<>(
Arrays
.
asList
(
new
String
[]
{
"bridge-pool-assignment"
}));
this
.
checkExactlyOnceKeywords
(
exactlyOnceKeywords
);
this
.
checkFirstKeyword
(
"bridge-pool-assignment"
);
this
.
clearParsedKeywords
();
this
.
checkExactlyOnceKeys
(
EnumSet
.
of
(
Key
.
BRIDGE_POOL_ASSIGNMENT
));
this
.
checkFirstKey
(
Key
.
BRIDGE_POOL_ASSIGNMENT
);
this
.
clearParsedKeys
();
return
;
}
private
void
parseDescriptorBytes
()
throws
DescriptorParseException
{
Scanner
scanner
=
new
Scanner
(
new
String
(
this
.
rawDescriptorBytes
))
.
useDelimiter
(
"\n"
);
.
useDelimiter
(
NL
);
while
(
scanner
.
hasNext
())
{
String
line
=
scanner
.
next
();
if
(
line
.
startsWith
(
"bridge-pool-assignment "
))
{
if
(
line
.
startsWith
(
Key
.
BRIDGE_POOL_ASSIGNMENT
.
keyword
+
SP
))
{
this
.
parseBridgePoolAssignmentLine
(
line
);
}
else
{
this
.
parseBridgeLine
(
line
);
...
...
@@ -80,7 +76,7 @@ public class BridgePoolAssignmentImpl extends DescriptorImpl
}
String
fingerprint
=
ParseHelper
.
parseTwentyByteHexString
(
line
,
parts
[
0
]);
String
poolAndDetails
=
line
.
substring
(
line
.
indexOf
(
" "
)
+
1
);
String
poolAndDetails
=
line
.
substring
(
line
.
indexOf
(
SP
)
+
1
);
this
.
entries
.
put
(
fingerprint
,
poolAndDetails
);
}
...
...
src/main/java/org/torproject/descriptor/impl/BridgeServerDescriptorImpl.java
View file @
df6bdc8d
...
...
@@ -19,7 +19,7 @@ public class BridgeServerDescriptorImpl extends ServerDescriptorImpl
List
<
ServerDescriptor
>
parsedDescriptors
=
new
ArrayList
<>();
List
<
byte
[]>
splitDescriptorsBytes
=
DescriptorImpl
.
splitRawDescriptorBytes
(
descriptorsBytes
,
"router "
);
Key
.
ROUTER
.
keyword
+
SP
);
for
(
byte
[]
descriptorBytes
:
splitDescriptorsBytes
)
{
ServerDescriptor
parsedDescriptor
=
new
BridgeServerDescriptorImpl
(
descriptorBytes
,
...
...
src/main/java/org/torproject/descriptor/impl/DescriptorImpl.java
View file @
df6bdc8d
...
...
@@ -8,7 +8,7 @@ import org.torproject.descriptor.DescriptorParseException;
import
java.io.UnsupportedEncodingException
;
import
java.util.ArrayList
;
import
java.util.
Hash
Map
;
import
java.util.
Enum
Map
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Scanner
;
...
...
@@ -16,6 +16,10 @@ import java.util.Set;
public
abstract
class
DescriptorImpl
implements
Descriptor
{
public
static
final
String
NL
=
"\n"
;
public
static
final
String
SP
=
" "
;
protected
static
List
<
Descriptor
>
parseDescriptors
(
byte
[]
rawDescriptorBytes
,
String
fileName
,
boolean
failUnrecognizedDescriptorLines
)
...
...
@@ -30,33 +34,38 @@ public abstract class DescriptorImpl implements Descriptor {
first100Chars
.
length
);
String
firstLines
=
new
String
(
first100Chars
);
if
(
firstLines
.
startsWith
(
"@type network-status-consensus-3 1."
)
||
firstLines
.
startsWith
(
"@type network-status-microdesc-"
+
"consensus-3 1."
)
||
((
firstLines
.
startsWith
(
"network-status-version 3"
)
||
firstLines
.
contains
(
"\nnetwork-status-version 3"
))
&&
firstLines
.
contains
(
"\nvote-status consensus\n"
)))
{
||
firstLines
.
startsWith
(
"@type network-status-microdesc-consensus-3 1."
)
||
((
firstLines
.
startsWith
(
Key
.
NETWORK_STATUS_VERSION
.
keyword
+
SP
+
"3"
)
||
firstLines
.
contains
(
NL
+
Key
.
NETWORK_STATUS_VERSION
.
keyword
+
SP
+
"3"
))
&&
firstLines
.
contains
(
NL
+
Key
.
VOTE_STATUS
.
keyword
+
SP
+
"consensus"
+
NL
)))
{
parsedDescriptors
.
addAll
(
RelayNetworkStatusConsensusImpl
.
parseConsensuses
(
rawDescriptorBytes
,
failUnrecognizedDescriptorLines
));
}
else
if
(
firstLines
.
startsWith
(
"@type network-status-vote-3 1."
)
||
((
firstLines
.
startsWith
(
"network-status-version 3\n"
)
||
firstLines
.
contains
(
"\nnetwork-status-version 3\n"
))
&&
firstLines
.
contains
(
"\nvote-status vote\n"
)))
{
||
((
firstLines
.
startsWith
(
Key
.
NETWORK_STATUS_VERSION
.
keyword
+
SP
+
"3"
+
NL
)
||
firstLines
.
contains
(
NL
+
Key
.
NETWORK_STATUS_VERSION
.
keyword
+
SP
+
"3"
+
NL
))
&&
firstLines
.
contains
(
NL
+
Key
.
VOTE_STATUS
.
keyword
+
SP
+
"vote"
+
NL
)))
{
parsedDescriptors
.
addAll
(
RelayNetworkStatusVoteImpl
.
parseVotes
(
rawDescriptorBytes
,
failUnrecognizedDescriptorLines
));
}
else
if
(
firstLines
.
startsWith
(
"@type bridge-network-status 1."
)
||
firstLines
.
startsWith
(
"r "
))
{
||
firstLines
.
startsWith
(
Key
.
R
.
keyword
+
SP
))
{
parsedDescriptors
.
add
(
new
BridgeNetworkStatusImpl
(
rawDescriptorBytes
,
fileName
,
failUnrecognizedDescriptorLines
));
}
else
if
(
firstLines
.
startsWith
(
"@type bridge-server-descriptor 1."
))
{
}
else
if
(
firstLines
.
startsWith
(
"@type bridge-server-descriptor 1."
))
{
parsedDescriptors
.
addAll
(
BridgeServerDescriptorImpl
.
parseDescriptors
(
rawDescriptorBytes
,
failUnrecognizedDescriptorLines
));
}
else
if
(
firstLines
.
startsWith
(
"@type server-descriptor 1."
)
||
firstLines
.
startsWith
(
"router "
)
||
firstLines
.
contains
(
"\nrouter "
))
{
||
firstLines
.
startsWith
(
Key
.
ROUTER
.
keyword
+
SP
)
||
firstLines
.
contains
(
NL
+
Key
.
ROUTER
.
keyword
+
SP
))
{
parsedDescriptors
.
addAll
(
RelayServerDescriptorImpl
.
parseDescriptors
(
rawDescriptorBytes
,
failUnrecognizedDescriptorLines
));
...
...
@@ -65,42 +74,45 @@ public abstract class DescriptorImpl implements Descriptor {
.
parseDescriptors
(
rawDescriptorBytes
,
failUnrecognizedDescriptorLines
));
}
else
if
(
firstLines
.
startsWith
(
"@type extra-info 1."
)
||
firstLines
.
startsWith
(
"extra-info "
)
||
firstLines
.
contains
(
"\nextra-info "
))
{
||
firstLines
.
startsWith
(
Key
.
EXTRA_INFO
.
keyword
+
SP
)
||
firstLines
.
contains
(
NL
+
Key
.
EXTRA_INFO
.
keyword
+
SP
))
{
parsedDescriptors
.
addAll
(
RelayExtraInfoDescriptorImpl
.
parseDescriptors
(
rawDescriptorBytes
,
failUnrecognizedDescriptorLines
));
}
else
if
(
firstLines
.
startsWith
(
"@type microdescriptor 1."
)
||
firstLines
.
startsWith
(
"onion-key\n"
)
||
firstLines
.
contains
(
"\nonion-key\n"
))
{
||
firstLines
.
startsWith
(
Key
.
ONION_KEY
.
keyword
+
NL
)
||
firstLines
.
contains
(
NL
+
Key
.
ONION_KEY
.
keyword
+
NL
))
{
parsedDescriptors
.
addAll
(
MicrodescriptorImpl
.
parseDescriptors
(
rawDescriptorBytes
,
failUnrecognizedDescriptorLines
));
}
else
if
(
firstLines
.
startsWith
(
"@type bridge-pool-assignment 1."
)
||
firstLines
.
startsWith
(
"bridge-pool-assignment "
)
||
firstLines
.
contains
(
"\nbridge-pool-assignment "
))
{
||
firstLines
.
startsWith
(
Key
.
BRIDGE_POOL_ASSIGNMENT
.
keyword
+
SP
)
||
firstLines
.
contains
(
NL
+
Key
.
BRIDGE_POOL_ASSIGNMENT
.
keyword
+
SP
))
{
parsedDescriptors
.
addAll
(
BridgePoolAssignmentImpl
.
parseDescriptors
(
rawDescriptorBytes
,
failUnrecognizedDescriptorLines
));
}
else
if
(
firstLines
.
startsWith
(
"@type dir-key-certificate-3 1."
)
||
firstLines
.
startsWith
(
"dir-key-certificate-version "
)
||
firstLines
.
contains
(
"\ndir-key-certificate-version "
))
{
||
firstLines
.
startsWith
(
Key
.
DIR_KEY_CERTIFICATE_VERSION
.
keyword
+
SP
)
||
firstLines
.
contains
(
NL
+
Key
.
DIR_KEY_CERTIFICATE_VERSION
.
keyword
+
SP
))
{
parsedDescriptors
.
addAll
(
DirectoryKeyCertificateImpl
.
parseDescriptors
(
rawDescriptorBytes
,
failUnrecognizedDescriptorLines
));
}
else
if
(
firstLines
.
startsWith
(
"@type tordnsel 1."
)
||
firstLines
.
startsWith
(
"ExitNode
"
)
||
firstLines
.
contains
(
"\n
ExitNode
"
))
{
||
firstLines
.
startsWith
(
"ExitNode"
+
SP
)
||
firstLines
.
contains
(
NL
+
"
ExitNode"
+
SP
))
{
parsedDescriptors
.
add
(
new
ExitListImpl
(
rawDescriptorBytes
,
fileName
,
failUnrecognizedDescriptorLines
));
}
else
if
(
firstLines
.
startsWith
(
"@type network-status-2 1."
)
||
firstLines
.
startsWith
(
"network-status-version 2\n"
)
||
firstLines
.
contains
(
"\nnetwork-status-version 2\n"
))
{
||
firstLines
.
startsWith
(
Key
.
NETWORK_STATUS_VERSION
.
keyword
+
SP
+
"2"
+
NL
)
||
firstLines
.
contains
(
NL
+
Key
.
NETWORK_STATUS_VERSION
.
keyword
+
SP
+
"2"
+
NL
))
{
parsedDescriptors
.
add
(
new
RelayNetworkStatusImpl
(
rawDescriptorBytes
,
failUnrecognizedDescriptorLines
));
}
else
if
(
firstLines
.
startsWith
(
"@type directory 1."
)
||
firstLines
.
startsWith
(
"signed-directory\n"
)
||
firstLines
.
contains
(
"\nsigned-directory\n"
))
{
||
firstLines
.
startsWith
(
Key
.
SIGNED_DIRECTORY
.
keyword
+
NL
)
||
firstLines
.
contains
(
NL
+
Key
.
SIGNED_DIRECTORY
.
keyword
+
NL
))
{
parsedDescriptors
.
add
(
new
RelayDirectoryImpl
(
rawDescriptorBytes
,
failUnrecognizedDescriptorLines
));
}
else
if
(
firstLines
.
startsWith
(
"@type torperf 1."
))
{
...
...
@@ -116,7 +128,7 @@ public abstract class DescriptorImpl implements Descriptor {
protected
static
List
<
byte
[]>
splitRawDescriptorBytes
(
byte
[]
rawDescriptorBytes
,
String
startToken
)
{
List
<
byte
[]>
rawDescriptors
=
new
ArrayList
<>();
String
splitToken
=
"\n"
+
startToken
;
String
splitToken
=
NL
+
startToken
;
String
ascii
;
try
{
ascii
=
new
String
(
rawDescriptorBytes
,
"US-ASCII"
);
...
...
@@ -126,7 +138,7 @@ public abstract class DescriptorImpl implements Descriptor {
int
endAllDescriptors
=
rawDescriptorBytes
.
length
;
int
startAnnotations
=
0
;
boolean
containsAnnotations
=
ascii
.
startsWith
(
"@"
)
||
ascii
.
contains
(
"\n
@"
);
||
ascii
.
contains
(
NL
+
"
@"
);
while
(
startAnnotations
<
endAllDescriptors
)
{
int
startDescriptor
;
if
(
ascii
.
indexOf
(
startToken
,
startAnnotations
)
==
0
)
{
...
...
@@ -141,7 +153,7 @@ public abstract class DescriptorImpl implements Descriptor {
}
int
endDescriptor
=
-
1
;
if
(
containsAnnotations
)
{
endDescriptor
=
ascii
.
indexOf
(
"\n
@"
,
startDescriptor
);
endDescriptor
=
ascii
.
indexOf
(
NL
+
"
@"
,
startDescriptor
);
}
if
(
endDescriptor
<
0
)
{
endDescriptor
=
ascii
.
indexOf
(
splitToken
,
startDescriptor
);
...
...
@@ -183,7 +195,7 @@ public abstract class DescriptorImpl implements Descriptor {
this
.
failUnrecognizedDescriptorLines
=
failUnrecognizedDescriptorLines
;
this
.
cutOffAnnotations
(
rawDescriptorBytes
);
this
.
countKey
word
s
(
rawDescriptorBytes
,
blankLinesAllowed
);
this
.
countKeys
(
rawDescriptorBytes
,
blankLinesAllowed
);
}
/* Parse annotation lines from the descriptor bytes. */
...
...
@@ -194,8 +206,8 @@ public abstract class DescriptorImpl implements Descriptor {
String
ascii
=
new
String
(
rawDescriptorBytes
);
int
start
=
0
;
while
((
start
==
0
&&
ascii
.
startsWith
(
"@"
))
||
(
start
>
0
&&
ascii
.
indexOf
(
"\n
@"
,
start
-
1
)
>=
0
))
{
int
end
=
ascii
.
indexOf
(
"\n"
,
start
);
||
(
start
>
0
&&
ascii
.
indexOf
(
NL
+
"
@"
,
start
-
1
)
>=
0
))
{
int
end
=
ascii
.
indexOf
(
NL
,
start
);
if
(
end
<
0
)
{
throw
new
DescriptorParseException
(
"Annotation line does not "
+
"contain a newline."
);
...
...
@@ -217,130 +229,129 @@ public abstract class DescriptorImpl implements Descriptor {
return
new
ArrayList
<>(
this
.
annotations
);
}
private
String
firstKey
word
;
private
Key
firstKey
=
Key
.
EMPTY
;
private
String
lastKey
word
;
private
Key
lastKey
=
Key
.
EMPTY
;
private
Map
<
String
,
Integer
>
parsedKey
word
s
=
new
Hash
Map
<>();
private
Map
<
Key
,
Integer
>
parsedKeys
=
new
Enum
Map
<>(
Key
.
class
);
/* Count parsed keywords for consistency checks by subclasses. */
private
void
countKey
word
s
(
byte
[]
rawDescriptorBytes
,
private
void
countKeys
(
byte
[]
rawDescriptorBytes
,
boolean
blankLinesAllowed
)
throws
DescriptorParseException
{
if
(
rawDescriptorBytes
.
length
==
0
)
{
throw
new
DescriptorParseException
(
"Descriptor is empty."
);
}
String
descriptorString
=
new
String
(
rawDescriptorBytes
);
if
(!
blankLinesAllowed
&&
(
descriptorString
.
startsWith
(
"\n"
)
||
descriptorString
.
contains
(
"\n\n"
)))
{
if
(!
blankLinesAllowed
&&
(
descriptorString
.
startsWith
(
NL
)
||
descriptorString
.
contains
(
NL
+
NL
)))
{
throw
new
DescriptorParseException
(
"Blank lines are not allowed."
);
}
boolean
skipCrypto
=
false
;
Scanner
scanner
=
new
Scanner
(
descriptorString
).
useDelimiter
(
"\n"
);
Scanner
scanner
=
new
Scanner
(
descriptorString
).
useDelimiter
(
NL
);
while
(
scanner
.
hasNext
())
{
String
line
=
scanner
.
next
();
if
(
line
.
startsWith
(
"-----BEGIN"
))
{
if
(
line
.
startsWith
(
Key
.
CRYPTO_BEGIN
.
keyword
))
{
skipCrypto
=
true
;
}
else
if
(
line
.
startsWith
(
"-----END"
))
{
}
else
if
(
line
.
startsWith
(
Key
.
CRYPTO_END
.
keyword
))
{
skipCrypto
=
false
;
}
else
if
(!
line
.
isEmpty
()
&&
!
line
.
startsWith
(
"@"
)
&&
!
skipCrypto
)
{
String
lineNoOpt
=
line
.
startsWith
(
"opt "
)
?
line
.
substring
(
"opt "
.
length
())
:
line
;
String
keyword
=
lineNoOpt
.
split
(
" "
,
-
1
)[
0
];
String
lineNoOpt
=
line
.
startsWith
(
Key
.
OPT
.
keyword
+
SP
)
?
line
.
substring
(
Key
.
OPT
.
keyword
.
length
()
+
1
)
:
line
;
String
keyword
=
lineNoOpt
.
split
(
SP
,
-
1
)[
0
];
if
(
keyword
.
equals
(
""
))
{
throw
new
DescriptorParseException
(
"Illegal keyword in line '"
+
line
+
"'."
);
}
if
(
this
.
firstKeyword
==
null
)
{
this
.
firstKeyword
=
keyword
;
Key
key
=
Key
.
get
(
keyword
);
if
(
Key
.
EMPTY
==
this
.
firstKey
)
{
this
.
firstKey
=
key
;
}
lastKey
word
=
key
word
;
if
(
parsedKey
word
s
.
containsKey
(
key
word
))
{
parsedKey
word
s
.
put
(
key
word
,
parsedKey
word
s
.
get
(
key
word
)
+
1
);
lastKey
=
key
;
if
(
parsedKeys
.
containsKey
(
key
))
{
parsedKeys
.
put
(
key
,
parsedKeys
.
get
(
key
)
+
1
);
}
else
{
parsedKey
word
s
.
put
(
key
word
,
1
);
parsedKeys
.
put
(
key
,
1
);
}
}
}
}
protected
void
checkFirstKey
word
(
String
keyword
)
protected
void
checkFirstKey
(
Key
key
)
throws
DescriptorParseException
{
if
(
this
.
firstKeyword
==
null
||
!
this
.
firstKeyword
.
equals
(
keyword
))
{
throw
new
DescriptorParseException
(
"Keyword '"
+
keyword
+
"' must "
if
(
this
.
firstKey
!=
key
)
{
throw
new
DescriptorParseException
(
"Keyword '"
+
key
.
keyword
+
"' must "
+
"be contained in the first line."
);
}
}
protected
void
checkLastKey
word
(
String
keyword
)
protected
void
checkLastKey
(
Key
key
)
throws
DescriptorParseException
{
if
(
this
.
lastKeyword
==
null
||
!
this
.
lastKeyword
.
equals
(
keyword
))
{
throw
new
DescriptorParseException
(
"Keyword '"
+
keyword
+
"' must "
if
(
this
.
lastKey
!=
key
)
{
throw
new
DescriptorParseException
(
"Keyword '"
+
key
.
keyword
+
"' must "
+
"be contained in the last line."
);
}
}
protected
void
checkExactlyOnceKey
word
s
(
Set
<
String
>
key
word
s
)
protected
void
checkExactlyOnceKeys
(
Set
<
Key
>
keys
)
throws
DescriptorParseException
{
for
(
String
keyword
:
key
word
s
)
{
for
(
Key
key
:
keys
)
{
int
contained
=
0
;
if
(
this
.
parsedKey
word
s
.
containsKey
(
key
word
))
{
contained
=
this
.
parsedKey
word
s
.
get
(
key
word
);
if
(
this
.
parsedKeys
.
containsKey
(
key
))
{
contained
=
this
.
parsedKeys
.
get
(
key
);
}
if
(
contained
!=
1
)
{
throw
new
DescriptorParseException
(
"Keyword '"
+
keyword
+
"' is "
throw
new
DescriptorParseException
(
"Keyword '"
+
key
.
keyword
+
"' is "
+
"contained "
+
contained
+
" times, but must be contained "
+
"exactly once."
);
}
}
}
protected
void
checkAtLeastOnceKey
word
s
(
Set
<
String
>
key
word
s
)
protected
void
checkAtLeastOnceKeys
(
Set
<
Key
>
keys
)
throws
DescriptorParseException
{
for
(
String
keyword
:
key
word
s
)
{
if
(!
this
.
parsedKey
word
s
.
containsKey
(
key
word
))
{
throw
new
DescriptorParseException
(
"Keyword '"
+
keyword
+
"' is "
for
(
Key
key
:
keys
)
{
if
(!
this
.
parsedKeys
.
containsKey
(
key
))
{
throw
new
DescriptorParseException
(
"Keyword '"
+
key
.
keyword
+
"' is "
+
"contained 0 times, but must be contained at least once."
);
}
}
}
protected
void
checkAtMostOnceKey
word
s
(
Set
<
String
>
key
word
s
)
protected
void
checkAtMostOnceKeys
(
Set
<
Key
>
keys
)
throws
DescriptorParseException
{
for
(
String
keyword
:
key
word
s
)
{
if
(
this
.
parsedKey
word
s
.
containsKey
(
key
word
)
&&
this
.
parsedKey
word
s
.
get
(
key
word
)
>
1
)
{
throw
new
DescriptorParseException
(
"Keyword '"
+
keyword
+
"' is "
+
"contained "
+
this
.
parsedKey
word
s
.
get
(
key
word
)
+
" times, "
for
(
Key
key
:
keys
)
{
if
(
this
.
parsedKeys
.
containsKey
(
key
)
&&
this
.
parsedKeys
.
get
(
key
)
>
1
)
{
throw
new
DescriptorParseException
(
"Keyword '"
+
key
.
keyword
+
"' is "
+
"contained "
+
this
.
parsedKeys
.
get
(
key
)
+
" times, "
+
"but must be contained at most once."
);
}
}
}
protected
void
checkKey
word
sDependOn
(
Set
<
String
>
dependentKey
word
s
,
String
dependingKey
word
)
throws
DescriptorParseException
{
for
(
String
dependentKey
word
:
dependentKey
word
s
)
{
if
(
this
.
parsedKey
word
s
.
containsKey
(
dependentKey
word
)
&&
!
this
.
parsedKey
word
s
.
containsKey
(
dependingKey
word
))
{
throw
new
DescriptorParseException
(
"Keyword '"
+
dependentKeyword
+
"' is contained, but keyword '"
+
dependingKeyword
+
"' is "
protected
void
checkKeysDependOn
(
Set
<
Key
>
dependentKeys
,
Key
dependingKey
)
throws
DescriptorParseException
{
for
(
Key
dependentKey
:
dependentKeys
)
{
if
(
this
.
parsedKeys
.
containsKey
(
dependentKey
)
&&
!
this
.
parsedKeys
.
containsKey
(
dependingKey
))
{
throw
new
DescriptorParseException
(
"Keyword '"
+
dependentKey
.
key
word
+
"' is contained, but keyword '"
+
dependingKey
.
key
word
+
"' is "
+
"not."
);
}
}
}
protected
int
getKey
word
Count
(
String
keyword
)
{
if
(!
this
.
parsedKey
word
s
.
containsKey
(
key
word
))
{
protected
int
getKeyCount
(
Key
key
)
{
if
(!
this
.
parsedKeys
.
containsKey
(
key
))
{
return
0
;
}
else
{
return
this
.
parsedKey
word
s
.
get
(
key
word
);
return
this
.
parsedKeys
.
get
(
key
);
}
}
protected
void
clearParsedKey
word
s
()
{
this
.
parsedKey
word
s
=
null
;
protected
void
clearParsedKeys
()
{
this
.
parsedKeys
=
null
;
}
}
src/main/java/org/torproject/descriptor/impl/DirSourceEntryImpl.java
View file @
df6bdc8d
...
...
@@ -3,14 +3,17 @@
package
org.torproject.descriptor.impl
;
import
static
org
.
torproject
.
descriptor
.
impl
.
DescriptorImpl
.
NL
;
import
static
org
.
torproject
.
descriptor
.
impl
.
DescriptorImpl
.
SP
;
import
org.torproject.descriptor.DescriptorParseException
;
import
org.torproject.descriptor.DirSourceEntry
;
import
java.util.ArrayList
;
import
java.util.EnumSet
;
import
java.util.List
;
import
java.util.Scanner
;
import
java.util.SortedSet
;
import
java.util.TreeSet
;
import
java.util.Set
;
public
class
DirSourceEntryImpl
implements
DirSourceEntry
{
...
...
@@ -37,72 +40,67 @@ public class DirSourceEntryImpl implements DirSourceEntry {
this
.
dirSourceEntryBytes
=
dirSourceEntryBytes
;
this
.
failUnrecognizedDescriptorLines
=
failUnrecognizedDescriptorLines
;
this
.
initializeKeywords
();
this
.
parseDirSourceEntryBytes
();
this
.
checkAndClearKey
word
s
();
this
.
checkAndClearKeys
();
}
private
SortedSet
<
String
>
exactlyOnceKeywords
;
private
SortedSet
<
String
>
atMostOnceKeywords
;
private
Set
<
Key
>
exactlyOnceKeys
=
EnumSet
.
of
(
Key
.
DIR_SOURCE
,
Key
.
VOTE_DIGEST
);
private
void
initializeKeywords
()
{
this
.
exactlyOnceKeywords
=
new
TreeSet
<>();
this
.
exactlyOnceKeywords
.
add
(
"dir-source"
);
this
.
exactlyOnceKeywords
.
add
(
"vote-digest"
);
this
.
atMostOnceKeywords
=
new
TreeSet
<>();
this
.
atMostOnceKeywords
.
add
(
"contact"
);
}
private
Set
<
Key
>
atMostOnceKeys
=
EnumSet
.
of
(
Key
.
CONTACT
);
private
void
parsedExactlyOnceKey
word
(
String
keyword
)
private
void
parsedExactlyOnceKey
(
Key
key
)
throws
DescriptorParseException
{
if
(!
this
.
exactlyOnceKey
word
s
.
contains
(
key
word
))
{
throw
new
DescriptorParseException
(
"Duplicate '"
+
keyword
if
(!
this
.
exactlyOnceKeys
.
contains
(
key
))
{
throw
new
DescriptorParseException
(
"Duplicate '"
+
key
.
keyword
+
"' line in dir-source."
);
}
this
.
exactlyOnceKey
word
s
.
remove
(
key
word
);
this
.
exactlyOnceKeys
.
remove
(
key
);
}
private
void
parsedAtMostOnceKey
word
(
String
keyword
)
private
void
parsedAtMostOnceKey
(
Key
key
)
throws
DescriptorParseException
{
if
(!
this
.
atMostOnceKey
word
s
.
contains
(
key
word
))
{
throw
new
DescriptorParseException
(
"Duplicate "
+
keyword
+
"line "
if
(!
this
.
atMostOnceKeys
.
contains
(
key
))
{
throw
new
DescriptorParseException
(
"Duplicate "
+
key
.
keyword
+
"line "
+
"in dir-source."
);
}
this
.
atMostOnceKey
word
s
.
remove
(
key
word
);
this
.
atMostOnceKeys
.
remove
(
key
);
}
private
void
checkAndClearKeywords
()
throws
DescriptorParseException
{
if
(!
this
.
exactlyOnceKeywords
.
isEmpty
())
{
throw
new
DescriptorParseException
(
"dir-source does not contain a '"
+
this
.
exactlyOnceKeywords
.
first
()
+
"' line."
);
private
void
checkAndClearKeys
()
throws
DescriptorParseException
{
if
(!
this
.
exactlyOnceKeys
.
isEmpty
())
{
for
(
Key
key
:
this
.
exactlyOnceKeys
)
{
throw
new
DescriptorParseException
(
"dir-source does not contain a '"
+
key
.
keyword
+
"' line."
);
}
}
this
.
exactlyOnceKey
word
s
=
null
;
this
.
atMostOnceKey
word
s
=
null
;
this
.
exactlyOnceKeys
=
null
;
this
.
atMostOnceKeys
=
null
;
}