Compare commits

...

65 Commits

Author SHA1 Message Date
akwizgran
48918f4727 Bumped version numbers for beta release. 2017-11-30 13:35:43 +00:00
akwizgran
303b5bd395 Merge branch 'target-sdk-26' into 'master'
Target API version 26, upgrade support library

See merge request !626
2017-11-29 17:38:12 +00:00
akwizgran
97733a52c8 Updated translations. 2017-11-23 17:03:15 +00:00
akwizgran
89dcbec599 Upgrade Gradle plugin to 3.0.1. 2017-11-23 17:01:16 +00:00
akwizgran
6497809fe1 Merge branch '1103-dont-ask-again-doze' into 'master'
Show Doze Mode Warning with Don't Ask Again Option

Closes #1103

See merge request !625
2017-11-23 16:23:39 +00:00
akwizgran
9f3a63d8c4 Don't unregister receiver unless it was registered. 2017-11-22 11:37:58 +00:00
akwizgran
748fa77d94 Move doze receiver out of BriarService. 2017-11-22 11:07:28 +00:00
Torsten Grote
4ca86ee4eb Address review comments 2017-11-21 16:01:07 -02:00
Torsten Grote
ec2f372933 Remember that app entered doze mode and inform user when returning 2017-11-21 15:55:00 -02:00
Torsten Grote
4267800db2 Allow Account Creation without Doze White-listing 2017-11-21 15:55:00 -02:00
Torsten Grote
bb8cb9bcbb Show Doze Dialog only after startup and provide "don't ask again" option 2017-11-21 15:54:59 -02:00
akwizgran
d5b9e15ee1 Bump compileSdkVersion to match support library. 2017-11-21 17:33:40 +00:00
akwizgran
43ee3246f6 Remove redundant casts from findViewById. 2017-11-21 17:29:21 +00:00
akwizgran
b56724dee5 Set target SDK version to 26, upgrade support library. 2017-11-21 17:29:21 +00:00
akwizgran
92748ac872 Accept build tools license for CI. 2017-11-21 17:28:11 +00:00
akwizgran
b89686c287 Merge branch 'upgrade-gradle-witness' into 'master'
Upgrade Gradle Witness

See merge request !623
2017-11-21 17:11:06 +00:00
akwizgran
a34692630b Use testImplementation for Mockito. 2017-11-21 17:03:38 +00:00
akwizgran
735208562a Use java-library plugin for Java modules. 2017-11-21 16:35:08 +00:00
akwizgran
49826fdc56 Use new Gradle configurations for Android modules. 2017-11-21 16:35:08 +00:00
akwizgran
e8c54a609c Upgrade Gradle Witness. 2017-11-21 16:35:03 +00:00
akwizgran
ece2c51358 A few more Java 8 changes in merged code. 2017-11-21 16:21:15 +00:00
akwizgran
3ec8af4661 Merge branch 'use-java-8-language-features' into 'master'
Use java 8 language features

See merge request !621
2017-11-21 15:22:52 +00:00
Torsten Grote
77a08596fe Merge branch '764-bdf-list-dictionary-not-thread-safe' into 'master'
BdfList and BdfDictionary don't need to be thread-safe

Closes #764

See merge request !614
2017-11-21 13:00:23 +00:00
akwizgran
879f699b2b A few more lambdas. 2017-11-21 10:51:37 -02:00
akwizgran
d7383a3361 Effectively final. 2017-11-21 10:51:35 -02:00
akwizgran
a5b321a93b Multi-catch. 2017-11-21 10:49:10 -02:00
akwizgran
5fa6b0ca1c Lambdas. 2017-11-21 10:49:08 -02:00
akwizgran
27328afe3c Diamond operators. 2017-11-21 10:45:47 -02:00
Torsten Grote
2d26af1ae2 Merge branch 'java-8-language-features' into 'master'
Support Java 8 language features

See merge request !620
2017-11-21 12:09:27 +00:00
Torsten Grote
6db8f33e8f Merge branch 'log-network-usage' into 'master'
Log network usage at shutdown

See merge request !616
2017-11-21 11:45:42 +00:00
akwizgran
d6a7e6d52c Resolve merge conflicts.
# Conflicts:
#   briar-android/build.gradle
#   briar-android/src/test/java/org/briarproject/briar/android/login/SetupActivityTest.java
2017-11-21 10:27:31 +00:00
akwizgran
df99b3b666 Merge branch '1085-startup-wizard' into 'master'
Setup Wizard that asks for Doze Mode exception

Closes #1085 and #1018

See merge request !603
2017-11-21 09:40:10 +00:00
akwizgran
0f1c9f4fe2 Refactored tests for account setup and changing password. 2017-11-20 14:11:31 -02:00
Torsten Grote
5dcd5f79dc Test PasswordFragment account creation individually 2017-11-20 11:52:06 -02:00
Torsten Grote
8a81171739 Setup Wizard that asks for Doze Mode exception
Keep checking if we are whitelisted and request it if not
2017-11-20 11:52:05 -02:00
akwizgran
1c4f20f76f Merge branch 'simply-build-gradle' into 'master'
Simply bramble-androids's build.gradle

See merge request !622
2017-11-17 16:11:00 +00:00
goapunk
f84fa588f6 simply bramble-androids's build.gradle
Signed-off-by: goapunk <noobie@goapunks.net>
2017-11-17 16:43:07 +01:00
akwizgran
e30e34f342 Include java.lang.invoke classes in bootstrap classpath. 2017-11-16 15:26:05 +00:00
akwizgran
fc93ced067 Download the Android support repository for CI. 2017-11-16 12:54:57 +00:00
akwizgran
bb7df72d31 Compile against OpenJDK 6 standard library for CI. 2017-11-16 12:54:50 +00:00
akwizgran
f8425658e4 Support Java 8 language features in Java modules. 2017-11-16 11:46:35 +00:00
akwizgran
53c8cf09b6 Support Java 8 language features in Android modules. 2017-11-16 11:46:34 +00:00
akwizgran
9f29bf4949 Upgrade Gradle and Android Gradle plugin 2017-11-16 11:46:32 +00:00
akwizgran
98e2adf794 Fix Dagger setup, remove android-apt plugin. 2017-11-16 11:46:02 +00:00
Torsten Grote
2a43e0b0ed Merge branch '545-simple-db-indexes' into 'master'
Add some simple indexes to the DB

See merge request !618
2017-11-09 12:10:07 +00:00
akwizgran
773ae73820 Updated translations. 2017-11-09 12:05:21 +00:00
akwizgran
009db57bc5 Merge branch '482-delete-old-transport-property-updates' into 'master'
Delete old transport property updates

Closes #482

See merge request !617
2017-11-09 11:59:00 +00:00
akwizgran
5e98126e77 Completely remove old local updates from the database. 2017-11-09 10:58:51 +00:00
akwizgran
bd7ebfd83a Unit tests for TransportPropertyManagerImpl. 2017-11-08 16:44:26 +00:00
akwizgran
10f41ef157 Log network usage at shutdown. 2017-11-08 14:46:56 +00:00
akwizgran
1dd4960109 Transactions that delete old updates must be read-write. 2017-11-08 14:23:30 +00:00
akwizgran
75413b6c86 Delete old transport property updates.
Some of this code is only needed for backward compatibility - it can be removed when we break compatibility for 1.0.
2017-11-08 09:47:59 +00:00
akwizgran
b2180582a7 BdfList and BdfDictionary don't need to be thread-safe.
Same goes for Metadata.
2017-11-06 15:20:21 +00:00
akwizgran
8211ce7ae3 Add some simple indexes to the DB. 2017-11-03 15:06:34 +00:00
akwizgran
e6b1597fa7 Upgraded Gradle to 3.5. 2017-10-26 18:07:20 +01:00
akwizgran
8937d3cd9c Updated translations. 2017-10-24 17:01:11 +01:00
akwizgran
51f320d147 Merge branch '992-wake-lock-tag' into 'master'
Change wake lock tag

Closes #992 and #1087

See merge request !612
2017-10-24 13:36:26 +00:00
goapunk
e402a894bb Change wake lock tag
Signed-off-by: goapunk <noobie@goapunks.net>
2017-10-24 13:45:27 +02:00
Torsten Grote
9b577f1219 Merge branch 'remove-location-permission' into 'master'
Remove unused location permission

See merge request !611
2017-10-18 16:31:56 +00:00
akwizgran
220f678403 Removed unused location permission. 2017-10-18 14:05:11 +01:00
akwizgran
4173fc4daa Merge branch '1045-preference-divider' into 'master'
Don't use a custom widget to separate preference categories

Closes #1045

See merge request !609
2017-10-17 17:03:13 +00:00
Torsten Grote
c6756d2145 Merge branch 'gradle-plugin-2.3.3' into 'master'
Upgrade Gradle plugin and build tools

See merge request !610
2017-10-17 16:14:53 +00:00
akwizgran
6731f6eeb5 Added checksum for Gradle download. 2017-10-17 17:01:46 +01:00
akwizgran
6f7f8b40e3 Upgraded Gradle plugin and build tools. 2017-10-17 15:31:28 +01:00
akwizgran
4fe4c298d7 Don't use a custom widget to separate preference categories. 2017-10-11 17:35:05 +01:00
312 changed files with 6908 additions and 6516 deletions

View File

@@ -6,8 +6,18 @@ cache:
- .gradle/caches - .gradle/caches
before_script: before_script:
- set -e
- export GRADLE_USER_HOME=$PWD/.gradle - export GRADLE_USER_HOME=$PWD/.gradle
- echo y | /opt/android-sdk/tools/bin/sdkmanager "build-tools;23.0.3" # Accept the license for the Android build tools
- echo y | /opt/android-sdk/tools/bin/sdkmanager "build-tools;26.0.2"
# Download OpenJDK 6 so we can compile against its standard library
- JDK_FILE=openjdk-6-jre-headless_6b38-1.13.10-1~deb7u1_amd64.deb
- if [ ! -d openjdk ]
- then
- wget -q http://ftp.uk.debian.org/debian/pool/main/o/openjdk-6/$JDK_FILE
- dpkg-deb -x $JDK_FILE openjdk
- fi
- export JAVA_6_HOME=$PWD/openjdk/usr/lib/jvm/java-6-openjdk-amd64
test: test:
script: script:

View File

@@ -6,99 +6,90 @@ apply plugin: 'witness'
apply plugin: 'de.undercouch.download' apply plugin: 'de.undercouch.download'
android { android {
compileSdkVersion 23 compileSdkVersion 27
buildToolsVersion "23.0.3" buildToolsVersion '26.0.2'
defaultConfig { defaultConfig {
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 22 targetSdkVersion 26
versionCode 1611 versionCode 1612
versionName "0.16.11" versionName "0.16.12"
consumerProguardFiles 'proguard-rules.txt' consumerProguardFiles 'proguard-rules.txt'
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_8
} }
} }
dependencies { dependencies {
compile project(':bramble-core') implementation project(path: ':bramble-core', configuration: 'default')
compile fileTree(dir: 'libs', include: '*.jar') implementation fileTree(dir: 'libs', include: '*.jar')
provided 'javax.annotation:jsr250-api:1.0'
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
compileOnly 'javax.annotation:jsr250-api:1.0'
} }
def torBinaryDir = 'src/main/res/raw' dependencyVerification {
verify = [
task downloadTorGeoIp(type: Download) { 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
src 'https://briarproject.org/build/geoip-2017-09-06.zip' 'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
dest "$torBinaryDir/geoip.zip" 'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
onlyIfNewer true 'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.jacoco:org.jacoco.agent:0.7.4.201502262128:org.jacoco.agent-0.7.4.201502262128-runtime.jar:e357a0f1d573c2f702a273992b1b6cb661734f66311854efb3778a888515c5b5',
'org.jacoco:org.jacoco.agent:0.7.4.201502262128:org.jacoco.agent-0.7.4.201502262128.jar:47b4bec6df11a1118da3953da8b9fa1e7079d6fec857faa1a3cf912e53a6fd4e',
'org.jacoco:org.jacoco.ant:0.7.4.201502262128:org.jacoco.ant-0.7.4.201502262128.jar:013ce2a68ba57a3c59215ae0dec4df3498c078062a38c3b94c841fc14450f283',
'org.jacoco:org.jacoco.core:0.7.4.201502262128:org.jacoco.core-0.7.4.201502262128.jar:ec4c74554312fac5116350164786f91b35c9e082fa4ea598bfa42b5db05d7abb',
'org.jacoco:org.jacoco.report:0.7.4.201502262128:org.jacoco.report-0.7.4.201502262128.jar:7a3554c605e088e7e323b1084656243f0444fa353e2f2dee1f1a4204eb64ff09',
'org.ow2.asm:asm-debug-all:5.0.1:asm-debug-all-5.0.1.jar:4734de5b515a454b0096db6971fb068e5f70e6f10bbee2b3bd2fdfe5d978ed57',
]
} }
task downloadTorBinaryArm(type: Download) { ext.torBinaryDir = 'src/main/res/raw'
src 'https://briarproject.org/build/tor-0.2.9.12-arm.zip' ext.torVersion = '0.2.9.12'
dest "$torBinaryDir/tor_arm.zip" ext.geoipVersion = '2017-09-06'
onlyIfNewer true ext.torDownloadUrl = 'https://briarproject.org/build/'
def torBinaries = [
"tor_arm" : '8ed0b347ffed1d6a4d2fd14495118eb92be83e9cc06e057e15220dc288b31688',
"tor_arm_pie": '64403262511c29f462ca5e7c7621bfc3c944898364d1d5ad35a016bb8a034283',
"tor_x86" : '61e014607a2079bcf1646289c67bff6372b1aded6e1d8d83d7791efda9a4d5ab',
"tor_x86_pie": '18fbc98356697dd0895836ab46d5c9877d1c539193464f7db1e82a65adaaf288',
"geoip" : 'fe49d3adb86d3c512373101422a017dbb86c85a570524663f09dd8ce143a24f3'
]
def downloadBinary(name) {
return tasks.create("downloadBinary${name}", Download) {
src "${torDownloadUrl}${name}.zip"
.replace('tor_', "tor-${torVersion}-")
.replace('geoip', "geoip-${geoipVersion}")
.replaceAll('_', '-')
dest "${torBinaryDir}/${name}.zip"
onlyIfNewer true
}
} }
task downloadTorBinaryArmPie(type: Download) { def verifyBinary(name, chksum) {
src 'https://briarproject.org/build/tor-0.2.9.12-arm-pie.zip' return tasks.create([
dest "$torBinaryDir/tor_arm_pie.zip" name : "verifyBinary${name}",
onlyIfNewer true type : Verify,
} dependsOn: downloadBinary(name)]) {
src "${torBinaryDir}/${name}.zip"
task downloadTorBinaryX86(type: Download) { algorithm 'SHA-256'
src 'https://briarproject.org/build/tor-0.2.9.12-x86.zip' checksum chksum
dest "$torBinaryDir/tor_x86.zip" }
onlyIfNewer true
}
task downloadTorBinaryX86Pie(type: Download) {
src 'https://briarproject.org/build/tor-0.2.9.12-x86-pie.zip'
dest "$torBinaryDir/tor_x86_pie.zip"
onlyIfNewer true
}
task verifyTorGeoIp(type: Verify, dependsOn: 'downloadTorGeoIp') {
src "$torBinaryDir/geoip.zip"
algorithm 'SHA-256'
checksum 'fe49d3adb86d3c512373101422a017dbb86c85a570524663f09dd8ce143a24f3'
}
task verifyTorBinaryArm(type: Verify, dependsOn: 'downloadTorBinaryArm') {
src "$torBinaryDir/tor_arm.zip"
algorithm 'SHA-256'
checksum '8ed0b347ffed1d6a4d2fd14495118eb92be83e9cc06e057e15220dc288b31688'
}
task verifyTorBinaryArmPie(type: Verify, dependsOn: 'downloadTorBinaryArmPie') {
src "$torBinaryDir/tor_arm_pie.zip"
algorithm 'SHA-256'
checksum '64403262511c29f462ca5e7c7621bfc3c944898364d1d5ad35a016bb8a034283'
}
task verifyTorBinaryX86(type: Verify, dependsOn: 'downloadTorBinaryX86') {
src "$torBinaryDir/tor_x86.zip"
algorithm 'SHA-256'
checksum '61e014607a2079bcf1646289c67bff6372b1aded6e1d8d83d7791efda9a4d5ab'
}
task verifyTorBinaryX86Pie(type: Verify, dependsOn: 'downloadTorBinaryX86Pie') {
src "$torBinaryDir/tor_x86_pie.zip"
algorithm 'SHA-256'
checksum '18fbc98356697dd0895836ab46d5c9877d1c539193464f7db1e82a65adaaf288'
} }
project.afterEvaluate { project.afterEvaluate {
preBuild.dependsOn { torBinaries.every { key, value ->
[ preBuild.dependsOn.add(verifyBinary(key, value))
'verifyTorGeoIp',
'verifyTorBinaryArm',
'verifyTorBinaryArmPie',
'verifyTorBinaryX86',
'verifyTorBinaryX86Pie'
]
} }
} }

View File

@@ -11,8 +11,6 @@
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_LOGS"/> <uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.WAKE_LOCK"/>
<!-- Since API 23, this is needed to add contacts via Bluetooth -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application <application
android:allowBackup="false" android:allowBackup="false"

View File

@@ -45,7 +45,7 @@ public class AndroidPluginModule {
backoffFactory); backoffFactory);
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor, DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
backoffFactory, appContext); backoffFactory, appContext);
final Collection<DuplexPluginFactory> duplex = Collection<DuplexPluginFactory> duplex =
Arrays.asList(bluetooth, tor, lan); Arrays.asList(bluetooth, tor, lan);
@NotNullByDefault @NotNullByDefault
PluginConfig pluginConfig = new PluginConfig() { PluginConfig pluginConfig = new PluginConfig() {

View File

@@ -124,12 +124,7 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
// with a message queue, so submit it to the AndroidExecutor // with a message queue, so submit it to the AndroidExecutor
try { try {
adapter = androidExecutor.runOnBackgroundThread( adapter = androidExecutor.runOnBackgroundThread(
new Callable<BluetoothAdapter>() { BluetoothAdapter::getDefaultAdapter).get();
@Override
public BluetoothAdapter call() throws Exception {
return BluetoothAdapter.getDefaultAdapter();
}
}).get();
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
LOG.warning("Interrupted while getting BluetoothAdapter"); LOG.warning("Interrupted while getting BluetoothAdapter");
@@ -162,40 +157,36 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
} }
private void bind() { private void bind() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override if (!isRunning()) return;
public void run() { String address = AndroidUtils.getBluetoothAddress(appContext,
if (!isRunning()) return; adapter);
String address = AndroidUtils.getBluetoothAddress(appContext, if (LOG.isLoggable(INFO))
adapter); LOG.info("Local address " + scrubMacAddress(address));
if (LOG.isLoggable(INFO)) if (!StringUtils.isNullOrEmpty(address)) {
LOG.info("Local address " + scrubMacAddress(address)); // Advertise the Bluetooth address to contacts
if (!StringUtils.isNullOrEmpty(address)) { TransportProperties p = new TransportProperties();
// Advertise the Bluetooth address to contacts p.put(PROP_ADDRESS, address);
TransportProperties p = new TransportProperties(); callback.mergeLocalProperties(p);
p.put(PROP_ADDRESS, address);
callback.mergeLocalProperties(p);
}
// Bind a server socket to accept connections from contacts
BluetoothServerSocket ss;
try {
ss = adapter.listenUsingInsecureRfcommWithServiceRecord(
"RFCOMM", getUuid());
} catch (IOException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
return;
}
if (!isRunning()) {
tryToClose(ss);
return;
}
LOG.info("Socket bound");
socket = ss;
backoff.reset();
callback.transportEnabled();
acceptContactConnections();
} }
// Bind a server socket to accept connections from contacts
BluetoothServerSocket ss;
try {
ss = adapter.listenUsingInsecureRfcommWithServiceRecord(
"RFCOMM", getUuid());
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return;
}
if (!isRunning()) {
tryToClose(ss);
return;
}
LOG.info("Socket bound");
socket = ss;
backoff.reset();
callback.transportEnabled();
acceptContactConnections();
}); });
} }
@@ -294,21 +285,18 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
Map<ContactId, TransportProperties> remote = Map<ContactId, TransportProperties> remote =
callback.getRemoteProperties(); callback.getRemoteProperties();
for (Entry<ContactId, TransportProperties> e : remote.entrySet()) { for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
final ContactId c = e.getKey(); ContactId c = e.getKey();
if (connected.contains(c)) continue; if (connected.contains(c)) continue;
final String address = e.getValue().get(PROP_ADDRESS); String address = e.getValue().get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) continue; if (StringUtils.isNullOrEmpty(address)) continue;
final String uuid = e.getValue().get(PROP_UUID); String uuid = e.getValue().get(PROP_UUID);
if (StringUtils.isNullOrEmpty(uuid)) continue; if (StringUtils.isNullOrEmpty(uuid)) continue;
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override if (!running) return;
public void run() { BluetoothSocket s = connect(address, uuid);
if (!running) return; if (s != null) {
BluetoothSocket s = connect(address, uuid); backoff.reset();
if (s != null) { callback.outgoingConnectionCreated(c, wrapSocket(s));
backoff.reset();
callback.outgoingConnectionCreated(c, wrapSocket(s));
}
} }
}); });
} }
@@ -438,21 +426,11 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
} }
private void enableAdapterAsync() { private void enableAdapterAsync() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(this::enableAdapter);
@Override
public void run() {
enableAdapter();
}
});
} }
private void disableAdapterAsync() { private void disableAdapterAsync() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(this::disableAdapter);
@Override
public void run() {
disableAdapter();
}
});
} }
private class BluetoothStateReceiver extends BroadcastReceiver { private class BluetoothStateReceiver extends BroadcastReceiver {
@@ -490,16 +468,13 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
@Override @Override
public Callable<KeyAgreementConnection> listen() { public Callable<KeyAgreementConnection> listen() {
return new Callable<KeyAgreementConnection>() { return () -> {
@Override BluetoothSocket s = ss.accept();
public KeyAgreementConnection call() throws IOException { if (LOG.isLoggable(INFO))
BluetoothSocket s = ss.accept(); LOG.info(ID.getString() + ": Incoming connection");
if (LOG.isLoggable(INFO)) return new KeyAgreementConnection(
LOG.info(ID.getString() + ": Incoming connection"); new DroidtoothTransportConnection(
return new KeyAgreementConnection( DroidtoothPlugin.this, s), ID);
new DroidtoothTransportConnection(
DroidtoothPlugin.this, s), ID);
}
}; };
} }

View File

@@ -149,7 +149,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
cookieFile = new File(torDirectory, ".tor/control_auth_cookie"); cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
Object o = appContext.getSystemService(POWER_SERVICE); Object o = appContext.getSystemService(POWER_SERVICE);
PowerManager pm = (PowerManager) o; PowerManager pm = (PowerManager) o;
wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "TorPlugin"); // This tag will prevent Huawei's powermanager from killing us.
wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "LocationManagerService");
wakeLock.setReferenceCounted(false); wakeLock.setReferenceCounted(false);
} }
@@ -369,57 +370,45 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
private void sendDevReports() { private void sendDevReports() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override // TODO: Trigger this with a TransportEnabledEvent
public void run() { File reportDir = AndroidUtils.getReportDir(appContext);
// TODO: Trigger this with a TransportEnabledEvent reporter.sendReports(reportDir);
File reportDir = AndroidUtils.getReportDir(appContext);
reporter.sendReports(reportDir);
}
}); });
} }
private void bind() { private void bind() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override // If there's already a port number stored in config, reuse it
public void run() { String portString = callback.getSettings().get(PREF_TOR_PORT);
// If there's already a port number stored in config, reuse it int port;
String portString = callback.getSettings().get(PREF_TOR_PORT); if (StringUtils.isNullOrEmpty(portString)) port = 0;
int port; else port = Integer.parseInt(portString);
if (StringUtils.isNullOrEmpty(portString)) port = 0; // Bind a server socket to receive connections from Tor
else port = Integer.parseInt(portString); ServerSocket ss = null;
// Bind a server socket to receive connections from Tor try {
ServerSocket ss = null; ss = new ServerSocket();
try { ss.bind(new InetSocketAddress("127.0.0.1", port));
ss = new ServerSocket(); } catch (IOException e) {
ss.bind(new InetSocketAddress("127.0.0.1", port)); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (IOException e) { tryToClose(ss);
if (LOG.isLoggable(WARNING)) return;
LOG.log(WARNING, e.toString(), e);
tryToClose(ss);
return;
}
if (!running) {
tryToClose(ss);
return;
}
socket = ss;
// Store the port number
final String localPort = String.valueOf(ss.getLocalPort());
Settings s = new Settings();
s.put(PREF_TOR_PORT, localPort);
callback.mergeSettings(s);
// Create a hidden service if necessary
ioExecutor.execute(new Runnable() {
@Override
public void run() {
publishHiddenService(localPort);
}
});
backoff.reset();
// Accept incoming hidden service connections from Tor
acceptContactConnections(ss);
} }
if (!running) {
tryToClose(ss);
return;
}
socket = ss;
// Store the port number
String localPort = String.valueOf(ss.getLocalPort());
Settings s = new Settings();
s.put(PREF_TOR_PORT, localPort);
callback.mergeSettings(s);
// Create a hidden service if necessary
ioExecutor.execute(() -> publishHiddenService(localPort));
backoff.reset();
// Accept incoming hidden service connections from Tor
acceptContactConnections(ss);
}); });
} }
@@ -547,17 +536,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
} }
private void connectAndCallBack(final ContactId c, private void connectAndCallBack(ContactId c, TransportProperties p) {
final TransportProperties p) { ioExecutor.execute(() -> {
ioExecutor.execute(new Runnable() { if (!isRunning()) return;
@Override DuplexTransportConnection d = createConnection(p);
public void run() { if (d != null) {
if (!isRunning()) return; backoff.reset();
DuplexTransportConnection d = createConnection(p); callback.outgoingConnectionCreated(c, d);
if (d != null) {
backoff.reset();
callback.outgoingConnectionCreated(c, d);
}
} }
}); });
} }
@@ -690,48 +675,43 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
private void updateConnectionStatus() { private void updateConnectionStatus() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override if (!running) return;
public void run() {
if (!running) return;
Object o = appContext.getSystemService(CONNECTIVITY_SERVICE); Object o = appContext.getSystemService(CONNECTIVITY_SERVICE);
ConnectivityManager cm = (ConnectivityManager) o; ConnectivityManager cm = (ConnectivityManager) o;
NetworkInfo net = cm.getActiveNetworkInfo(); NetworkInfo net = cm.getActiveNetworkInfo();
boolean online = net != null && net.isConnected(); boolean online = net != null && net.isConnected();
boolean wifi = online && net.getType() == TYPE_WIFI; boolean wifi = online && net.getType() == TYPE_WIFI;
String country = locationUtils.getCurrentCountry(); String country = locationUtils.getCurrentCountry();
boolean blocked = TorNetworkMetadata.isTorProbablyBlocked( boolean blocked = TorNetworkMetadata.isTorProbablyBlocked(
country); country);
Settings s = callback.getSettings(); Settings s = callback.getSettings();
int network = s.getInt(PREF_TOR_NETWORK, int network = s.getInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_ALWAYS);
PREF_TOR_NETWORK_ALWAYS);
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(INFO)) {
LOG.info("Online: " + online + ", wifi: " + wifi); LOG.info("Online: " + online + ", wifi: " + wifi);
if ("".equals(country)) LOG.info("Country code unknown"); if ("".equals(country)) LOG.info("Country code unknown");
else LOG.info("Country code: " + country); else LOG.info("Country code: " + country);
} }
try { try {
if (!online) { if (!online) {
LOG.info("Disabling network, device is offline"); LOG.info("Disabling network, device is offline");
enableNetwork(false); enableNetwork(false);
} else if (blocked) { } else if (blocked) {
LOG.info("Disabling network, country is blocked"); LOG.info("Disabling network, country is blocked");
enableNetwork(false); enableNetwork(false);
} else if (network == PREF_TOR_NETWORK_NEVER } else if (network == PREF_TOR_NETWORK_NEVER
|| (network == PREF_TOR_NETWORK_WIFI && !wifi)) { || (network == PREF_TOR_NETWORK_WIFI && !wifi)) {
LOG.info("Disabling network due to data setting"); LOG.info("Disabling network due to data setting");
enableNetwork(false); enableNetwork(false);
} else { } else {
LOG.info("Enabling network"); LOG.info("Enabling network");
enableNetwork(true); enableNetwork(true);
}
} catch (IOException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
} }
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} }
}); });
} }

View File

@@ -27,14 +27,11 @@ class AndroidExecutorImpl implements AndroidExecutor {
@Inject @Inject
AndroidExecutorImpl(Application app) { AndroidExecutorImpl(Application app) {
uiHandler = new Handler(app.getApplicationContext().getMainLooper()); uiHandler = new Handler(app.getApplicationContext().getMainLooper());
loop = new Runnable() { loop = () -> {
@Override Looper.prepare();
public void run() { backgroundHandler = new Handler();
Looper.prepare(); startLatch.countDown();
backgroundHandler = new Handler(); Looper.loop();
startLatch.countDown();
Looper.loop();
}
}; };
} }

View File

@@ -1,30 +1,39 @@
apply plugin: 'java' apply plugin: 'java-library'
sourceCompatibility = 1.6 sourceCompatibility = 1.8
targetCompatibility = 1.6 targetCompatibility = 1.8
apply plugin: 'witness' apply plugin: 'witness'
dependencies { dependencies {
compile "com.google.dagger:dagger:2.0.2" implementation "com.google.dagger:dagger:2.0.2"
compile 'com.google.dagger:dagger-compiler:2.0.2' implementation 'com.google.code.findbugs:jsr305:3.0.2'
compile 'com.google.code.findbugs:jsr305:3.0.2'
testCompile 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
testCompile "org.jmock:jmock:2.8.2" testImplementation "org.jmock:jmock:2.8.2"
testCompile "org.jmock:jmock-junit4:2.8.2" testImplementation "org.jmock:jmock-junit4:2.8.2"
testCompile "org.jmock:jmock-legacy:2.8.2" testImplementation "org.jmock:jmock-legacy:2.8.2"
testCompile "org.hamcrest:hamcrest-library:1.3" testImplementation "org.hamcrest:hamcrest-library:1.3"
testCompile "org.hamcrest:hamcrest-core:1.3" testImplementation "org.hamcrest:hamcrest-core:1.3"
} }
dependencyVerification { dependencyVerification {
verify = [ verify = [
'com.google.dagger:dagger:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.dagger:dagger-compiler:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.code.findbugs:jsr305:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', 'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'com.google.dagger:dagger-producers:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b', 'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'com.google.guava:guava:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99', 'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
] ]
} }
@@ -39,3 +48,8 @@ task jarTest(type: Jar, dependsOn: testClasses) {
artifacts { artifacts {
testOutput jarTest testOutput jarTest
} }
// If a Java 6 JRE is available, check we're not using any Java 7 or 8 APIs
tasks.withType(JavaCompile) {
useJava6StandardLibrary(it)
}

View File

@@ -23,7 +23,7 @@ public class BdfMessageContext {
} }
public BdfMessageContext(BdfDictionary dictionary) { public BdfMessageContext(BdfDictionary dictionary) {
this(dictionary, Collections.<MessageId>emptyList()); this(dictionary, Collections.emptyList());
} }
public BdfDictionary getDictionary() { public BdfDictionary getDictionary() {

View File

@@ -4,11 +4,14 @@ import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap; import java.util.Map.Entry;
import java.util.TreeMap;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
public class BdfDictionary extends ConcurrentSkipListMap<String, Object> { @NotThreadSafe
public class BdfDictionary extends TreeMap<String, Object> {
public static final Object NULL_VALUE = new Object(); public static final Object NULL_VALUE = new Object();

View File

@@ -3,15 +3,17 @@ package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.Bytes; import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Vector;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE; import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
public class BdfList extends Vector<Object> { @NotThreadSafe
public class BdfList extends ArrayList<Object> {
/** /**
* Factory method for constructing lists inline. * Factory method for constructing lists inline.

View File

@@ -122,8 +122,9 @@ public interface DatabaseComponent {
throws DbException; throws DbException;
/** /**
* Deletes the message with the given ID. The message ID and any other * Deletes the message with the given ID. Unlike
* associated data are not deleted. * {@link #removeMessage(Transaction, MessageId)}, the message ID and any
* other associated data are not deleted.
*/ */
void deleteMessage(Transaction txn, MessageId m) throws DbException; void deleteMessage(Transaction txn, MessageId m) throws DbException;
@@ -452,6 +453,11 @@ public interface DatabaseComponent {
*/ */
void removeLocalAuthor(Transaction txn, AuthorId a) throws DbException; void removeLocalAuthor(Transaction txn, AuthorId a) throws DbException;
/**
* Removes a message (and all associated state) from the database.
*/
void removeMessage(Transaction txn, MessageId m) throws DbException;
/** /**
* Removes a transport (and all associated state) from the database. * Removes a transport (and all associated state) from the database.
*/ */

View File

@@ -1,11 +1,11 @@
package org.briarproject.bramble.api.db; package org.briarproject.bramble.api.db;
import java.util.Hashtable; import java.util.TreeMap;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.NotThreadSafe;
@ThreadSafe @NotThreadSafe
public class Metadata extends Hashtable<String, byte[]> { public class Metadata extends TreeMap<String, byte[]> {
/** /**
* Special value to indicate that a key is being removed. * Special value to indicate that a key is being removed.

View File

@@ -45,7 +45,7 @@ public class Transaction {
* committed. * committed.
*/ */
public void attach(Event e) { public void attach(Event e) {
if (events == null) events = new ArrayList<Event>(); if (events == null) events = new ArrayList<>();
events.add(e); events.add(e);
} }

View File

@@ -33,7 +33,7 @@ public interface TransportPropertyManager {
/** /**
* Returns the local transport properties for all transports. * Returns the local transport properties for all transports.
* <br/> * <br/>
* Read-Only * TODO: Transaction can be read-only when code is simplified
*/ */
Map<TransportId, TransportProperties> getLocalProperties(Transaction txn) Map<TransportId, TransportProperties> getLocalProperties(Transaction txn)
throws DbException; throws DbException;

View File

@@ -22,7 +22,7 @@ public class MessageContext {
} }
public MessageContext(Metadata metadata) { public MessageContext(Metadata metadata) {
this(metadata, Collections.<MessageId>emptyList()); this(metadata, Collections.emptyList());
} }
public Metadata getMetadata() { public Metadata getMetadata() {

View File

@@ -3,8 +3,7 @@ package org.briarproject.bramble.test;
import org.jmock.Mockery; import org.jmock.Mockery;
import org.junit.After; import org.junit.After;
public abstract class BrambleMockTestCase extends public abstract class BrambleMockTestCase extends BrambleTestCase {
BrambleTestCase {
protected final Mockery context = new Mockery(); protected final Mockery context = new Mockery();

View File

@@ -8,12 +8,9 @@ public abstract class BrambleTestCase {
public BrambleTestCase() { public BrambleTestCase() {
// Ensure exceptions thrown on worker threads cause tests to fail // Ensure exceptions thrown on worker threads cause tests to fail
UncaughtExceptionHandler fail = new UncaughtExceptionHandler() { UncaughtExceptionHandler fail = (thread, throwable) -> {
@Override throwable.printStackTrace();
public void uncaughtException(Thread thread, Throwable throwable) { fail();
throwable.printStackTrace();
fail();
}
}; };
Thread.setDefaultUncaughtExceptionHandler(fail); Thread.setDefaultUncaughtExceptionHandler(fail);
} }

View File

@@ -1,28 +1,54 @@
plugins { apply plugin: 'java-library'
id 'java' sourceCompatibility = 1.8
id 'net.ltgt.apt' version '0.9' targetCompatibility = 1.8
id 'idea'
}
sourceCompatibility = 1.6
targetCompatibility = 1.6
apply plugin: 'net.ltgt.apt'
apply plugin: 'idea'
apply plugin: 'witness' apply plugin: 'witness'
dependencies { dependencies {
compile project(':bramble-api') implementation project(path: ':bramble-api', configuration: 'default')
compile 'com.madgag.spongycastle:core:1.58.0.0' implementation 'com.madgag.spongycastle:core:1.58.0.0'
compile 'com.h2database:h2:1.4.192' // This is the last version that supports Java 1.6 implementation 'com.h2database:h2:1.4.192' // This is the last version that supports Java 1.6
compile 'org.bitlet:weupnp:0.1.4' implementation 'org.bitlet:weupnp:0.1.4'
testCompile project(path: ':bramble-api', configuration: 'testOutput') apt 'com.google.dagger:dagger-compiler:2.0.2'
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation "org.hamcrest:hamcrest-library:1.3"
testImplementation "org.hamcrest:hamcrest-core:1.3"
testApt 'com.google.dagger:dagger-compiler:2.0.2'
} }
dependencyVerification { dependencyVerification {
verify = [ verify = [
'com.madgag.spongycastle:core:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.h2database:h2:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'org.bitlet:weupnp:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb', 'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
] ]
} }
@@ -37,3 +63,8 @@ task jarTest(type: Jar, dependsOn: testClasses) {
artifacts { artifacts {
testOutput jarTest testOutput jarTest
} }
// If a Java 6 JRE is available, check we're not using any Java 7 or 8 APIs
tasks.withType(JavaCompile) {
useJava6StandardLibrary(it)
}

View File

@@ -24,7 +24,7 @@ public class PoliteExecutor implements Executor {
private final Object lock = new Object(); private final Object lock = new Object();
@GuardedBy("lock") @GuardedBy("lock")
private final Queue<Runnable> queue = new LinkedList<Runnable>(); private final Queue<Runnable> queue = new LinkedList<>();
private final Executor delegate; private final Executor delegate;
private final int maxConcurrentTasks; private final int maxConcurrentTasks;
private final Logger log; private final Logger log;
@@ -48,20 +48,17 @@ public class PoliteExecutor implements Executor {
} }
@Override @Override
public void execute(final Runnable r) { public void execute(Runnable r) {
final long submitted = System.currentTimeMillis(); long submitted = System.currentTimeMillis();
Runnable wrapped = new Runnable() { Runnable wrapped = () -> {
@Override if (log.isLoggable(LOG_LEVEL)) {
public void run() { long queued = System.currentTimeMillis() - submitted;
if (log.isLoggable(LOG_LEVEL)) { log.log(LOG_LEVEL, "Queue time " + queued + " ms");
long queued = System.currentTimeMillis() - submitted; }
log.log(LOG_LEVEL, "Queue time " + queued + " ms"); try {
} r.run();
try { } finally {
r.run(); scheduleNext();
} finally {
scheduleNext();
}
} }
}; };
synchronized (lock) { synchronized (lock) {

View File

@@ -28,19 +28,16 @@ public class TimeLoggingExecutor extends ThreadPoolExecutor {
} }
@Override @Override
public void execute(final Runnable r) { public void execute(Runnable r) {
if (log.isLoggable(LOG_LEVEL)) { if (log.isLoggable(LOG_LEVEL)) {
final long submitted = System.currentTimeMillis(); long submitted = System.currentTimeMillis();
super.execute(new Runnable() { super.execute(() -> {
@Override long started = System.currentTimeMillis();
public void run() { long queued = started - submitted;
long started = System.currentTimeMillis(); log.log(LOG_LEVEL, "Queue time " + queued + " ms");
long queued = started - submitted; r.run();
log.log(LOG_LEVEL, "Queue time " + queued + " ms"); long executing = System.currentTimeMillis() - started;
r.run(); log.log(LOG_LEVEL, "Execution time " + executing + " ms");
long executing = System.currentTimeMillis() - started;
log.log(LOG_LEVEL, "Execution time " + executing + " ms");
}
}); });
} else { } else {
super.execute(r); super.execute(r);

View File

@@ -201,8 +201,7 @@ class ClientHelperImpl implements ClientHelper {
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary( public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
Transaction txn, GroupId g) throws DbException, FormatException { Transaction txn, GroupId g) throws DbException, FormatException {
Map<MessageId, Metadata> raw = db.getMessageMetadata(txn, g); Map<MessageId, Metadata> raw = db.getMessageMetadata(txn, g);
Map<MessageId, BdfDictionary> parsed = Map<MessageId, BdfDictionary> parsed = new HashMap<>(raw.size());
new HashMap<MessageId, BdfDictionary>(raw.size());
for (Entry<MessageId, Metadata> e : raw.entrySet()) for (Entry<MessageId, Metadata> e : raw.entrySet())
parsed.put(e.getKey(), metadataParser.parse(e.getValue())); parsed.put(e.getKey(), metadataParser.parse(e.getValue()));
return parsed; return parsed;
@@ -229,8 +228,7 @@ class ClientHelperImpl implements ClientHelper {
FormatException { FormatException {
Metadata metadata = metadataEncoder.encode(query); Metadata metadata = metadataEncoder.encode(query);
Map<MessageId, Metadata> raw = db.getMessageMetadata(txn, g, metadata); Map<MessageId, Metadata> raw = db.getMessageMetadata(txn, g, metadata);
Map<MessageId, BdfDictionary> parsed = Map<MessageId, BdfDictionary> parsed = new HashMap<>(raw.size());
new HashMap<MessageId, BdfDictionary>(raw.size());
for (Entry<MessageId, Metadata> e : raw.entrySet()) for (Entry<MessageId, Metadata> e : raw.entrySet())
parsed.put(e.getKey(), metadataParser.parse(e.getValue())); parsed.put(e.getKey(), metadataParser.parse(e.getValue()));
return parsed; return parsed;

View File

@@ -184,12 +184,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
// Close the outgoing stream and expect EOF on the incoming stream // Close the outgoing stream and expect EOF on the incoming stream
w.close(); w.close();
if (!r.eof()) LOG.warning("Unexpected data at end of connection"); if (!r.eof()) LOG.warning("Unexpected data at end of connection");
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException | IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
listener.contactExchangeFailed();
tryToClose(conn, true);
return;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
listener.contactExchangeFailed(); listener.contactExchangeFailed();
tryToClose(conn, true); tryToClose(conn, true);
@@ -276,8 +271,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
private Map<TransportId, TransportProperties> receiveTransportProperties( private Map<TransportId, TransportProperties> receiveTransportProperties(
BdfReader r) throws IOException { BdfReader r) throws IOException {
Map<TransportId, TransportProperties> remote = Map<TransportId, TransportProperties> remote = new HashMap<>();
new HashMap<TransportId, TransportProperties>();
r.readListStart(); r.readListStart();
while (!r.hasListEnd()) { while (!r.hasListEnd()) {
r.readListStart(); r.readListStart();

View File

@@ -34,8 +34,8 @@ class ContactManagerImpl implements ContactManager {
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager) { ContactManagerImpl(DatabaseComponent db, KeyManager keyManager) {
this.db = db; this.db = db;
this.keyManager = keyManager; this.keyManager = keyManager;
addHooks = new CopyOnWriteArrayList<AddContactHook>(); addHooks = new CopyOnWriteArrayList<>();
removeHooks = new CopyOnWriteArrayList<RemoveContactHook>(); removeHooks = new CopyOnWriteArrayList<>();
} }
@Override @Override
@@ -125,7 +125,7 @@ class ContactManagerImpl implements ContactManager {
} finally { } finally {
db.endTransaction(txn); db.endTransaction(txn);
} }
List<Contact> active = new ArrayList<Contact>(contacts.size()); List<Contact> active = new ArrayList<>(contacts.size());
for (Contact c : contacts) if (c.isActive()) active.add(c); for (Contact c : contacts) if (c.isActive()) active.add(c);
return active; return active;
} }

View File

@@ -602,8 +602,8 @@ class CryptoComponentImpl implements CryptoComponent {
// Package access for testing // Package access for testing
int chooseIterationCount(int targetMillis) { int chooseIterationCount(int targetMillis) {
List<Long> quickSamples = new ArrayList<Long>(PBKDF_SAMPLES); List<Long> quickSamples = new ArrayList<>(PBKDF_SAMPLES);
List<Long> slowSamples = new ArrayList<Long>(PBKDF_SAMPLES); List<Long> slowSamples = new ArrayList<>(PBKDF_SAMPLES);
long iterationNanos = 0, initNanos = 0; long iterationNanos = 0, initNanos = 0;
while (iterationNanos <= 0 || initNanos <= 0) { while (iterationNanos <= 0 || initNanos <= 0) {
// Sample the running time with one iteration and two iterations // Sample the running time with one iteration and two iterations

View File

@@ -48,7 +48,7 @@ public class CryptoModule {
public CryptoModule() { public CryptoModule() {
// Use an unbounded queue // Use an unbounded queue
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(); BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
// Discard tasks that are submitted during shutdown // Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy = RejectedExecutionHandler policy =
new ThreadPoolExecutor.DiscardPolicy(); new ThreadPoolExecutor.DiscardPolicy();

View File

@@ -16,7 +16,7 @@ class PasswordStrengthEstimatorImpl implements PasswordStrengthEstimator {
@Override @Override
public float estimateStrength(String password) { public float estimateStrength(String password) {
HashSet<Character> unique = new HashSet<Character>(); HashSet<Character> unique = new HashSet<>();
int length = password.length(); int length = password.length();
for (int i = 0; i < length; i++) unique.add(password.charAt(i)); for (int i = 0; i < length; i++) unique.add(password.charAt(i));
return Math.min(1, (float) unique.size() / STRONG_UNIQUE_CHARS); return Math.min(1, (float) unique.size() / STRONG_UNIQUE_CHARS);

View File

@@ -103,15 +103,11 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Override @Override
public boolean open() throws DbException { public boolean open() throws DbException {
Runnable shutdownHook = new Runnable() { Runnable shutdownHook = () -> {
@Override try {
public void run() { close();
try { } catch (DbException e) {
close(); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
}
} }
}; };
boolean reopened = db.open(); boolean reopened = db.open();
@@ -141,11 +137,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} }
try { try {
return new Transaction(db.startTransaction(), readOnly); return new Transaction(db.startTransaction(), readOnly);
} catch (DbException e) { } catch (DbException | RuntimeException e) {
if (readOnly) lock.readLock().unlock();
else lock.writeLock().unlock();
throw e;
} catch (RuntimeException e) {
if (readOnly) lock.readLock().unlock(); if (readOnly) lock.readLock().unlock();
else lock.writeLock().unlock(); else lock.writeLock().unlock();
throw e; throw e;
@@ -331,7 +323,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
if (!db.containsContact(txn, c)) if (!db.containsContact(txn, c))
throw new NoSuchContactException(); throw new NoSuchContactException();
Collection<MessageId> ids = db.getMessagesToSend(txn, c, maxLength); Collection<MessageId> ids = db.getMessagesToSend(txn, c, maxLength);
List<byte[]> messages = new ArrayList<byte[]>(ids.size()); List<byte[]> messages = new ArrayList<>(ids.size());
for (MessageId m : ids) { for (MessageId m : ids) {
messages.add(db.getRawMessage(txn, m)); messages.add(db.getRawMessage(txn, m));
db.updateExpiryTime(txn, c, m, maxLatency); db.updateExpiryTime(txn, c, m, maxLatency);
@@ -381,7 +373,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
throw new NoSuchContactException(); throw new NoSuchContactException();
Collection<MessageId> ids = db.getRequestedMessagesToSend(txn, c, Collection<MessageId> ids = db.getRequestedMessagesToSend(txn, c,
maxLength); maxLength);
List<byte[]> messages = new ArrayList<byte[]>(ids.size()); List<byte[]> messages = new ArrayList<>(ids.size());
for (MessageId m : ids) { for (MessageId m : ids) {
messages.add(db.getRawMessage(txn, m)); messages.add(db.getRawMessage(txn, m));
db.updateExpiryTime(txn, c, m, maxLatency); db.updateExpiryTime(txn, c, m, maxLatency);
@@ -661,7 +653,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
T txn = unbox(transaction); T txn = unbox(transaction);
if (!db.containsContact(txn, c)) if (!db.containsContact(txn, c))
throw new NoSuchContactException(); throw new NoSuchContactException();
Collection<MessageId> acked = new ArrayList<MessageId>(); Collection<MessageId> acked = new ArrayList<>();
for (MessageId m : a.getMessageIds()) { for (MessageId m : a.getMessageIds()) {
if (db.containsVisibleMessage(txn, c, m)) { if (db.containsVisibleMessage(txn, c, m)) {
db.raiseSeenFlag(txn, c, m); db.raiseSeenFlag(txn, c, m);
@@ -770,6 +762,16 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
transaction.attach(new LocalAuthorRemovedEvent(a)); transaction.attach(new LocalAuthorRemovedEvent(a));
} }
@Override
public void removeMessage(Transaction transaction, MessageId m)
throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
db.removeMessage(txn, m);
}
@Override @Override
public void removeTransport(Transaction transaction, TransportId t) public void removeTransport(Transaction transaction, TransportId t)
throws DbException { throws DbException {
@@ -886,8 +888,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
Map<ContactId, TransportKeys> keys) throws DbException { Map<ContactId, TransportKeys> keys) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException(); if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction); T txn = unbox(transaction);
Map<ContactId, TransportKeys> filtered = Map<ContactId, TransportKeys> filtered = new HashMap<>();
new HashMap<ContactId, TransportKeys>();
for (Entry<ContactId, TransportKeys> e : keys.entrySet()) { for (Entry<ContactId, TransportKeys> e : keys.entrySet()) {
ContactId c = e.getKey(); ContactId c = e.getKey();
TransportKeys k = e.getValue(); TransportKeys k = e.getValue();

View File

@@ -32,7 +32,7 @@ public class DatabaseExecutorModule {
public DatabaseExecutorModule() { public DatabaseExecutorModule() {
// Use an unbounded queue // Use an unbounded queue
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(); BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
// Discard tasks that are submitted during shutdown // Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy = RejectedExecutionHandler policy =
new ThreadPoolExecutor.DiscardPolicy(); new ThreadPoolExecutor.DiscardPolicy();

View File

@@ -26,7 +26,7 @@ public class DatabaseModule {
@Singleton @Singleton
DatabaseComponent provideDatabaseComponent(Database<Connection> db, DatabaseComponent provideDatabaseComponent(Database<Connection> db,
EventBus eventBus, ShutdownManager shutdown) { EventBus eventBus, ShutdownManager shutdown) {
return new DatabaseComponentImpl<Connection>(db, Connection.class, return new DatabaseComponentImpl<>(db, Connection.class, eventBus,
eventBus, shutdown); shutdown);
} }
} }

View File

@@ -232,6 +232,30 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " REFERENCES transports (transportId)" + " REFERENCES transports (transportId)"
+ " ON DELETE CASCADE)"; + " ON DELETE CASCADE)";
private static final String INDEX_CONTACTS_BY_AUTHOR_ID =
"CREATE INDEX IF NOT EXISTS contactsByAuthorId"
+ " ON contacts (authorId)";
private static final String INDEX_MESSAGES_BY_GROUP_ID =
"CREATE INDEX IF NOT EXISTS messagesByGroupId"
+ " ON messages (groupId)";
private static final String INDEX_OFFERS_BY_CONTACT_ID =
"CREATE INDEX IF NOT EXISTS offersByContactId"
+ " ON offers (contactId)";
private static final String INDEX_GROUPS_BY_CLIENT_ID =
"CREATE INDEX IF NOT EXISTS groupsByClientId"
+ " ON groups (clientId)";
private static final String INDEX_MESSAGE_METADATA_BY_MESSAGE_ID =
"CREATE INDEX IF NOT EXISTS messageMetadataByMessageId"
+ " ON messageMetadata (messageId)";
private static final String INDEX_GROUP_METADATA_BY_GROUP_ID =
"CREATE INDEX IF NOT EXISTS groupMetadataByGroupId"
+ " ON groupMetadata (groupId)";
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(JdbcDatabase.class.getName()); Logger.getLogger(JdbcDatabase.class.getName());
@@ -239,8 +263,8 @@ abstract class JdbcDatabase implements Database<Connection> {
private final String hashType, binaryType, counterType, secretType; private final String hashType, binaryType, counterType, secretType;
private final Clock clock; private final Clock clock;
private final LinkedList<Connection> connections = // Locking: connectionsLock
new LinkedList<Connection>(); // Locking: connectionsLock private final LinkedList<Connection> connections = new LinkedList<>();
private int openConnections = 0; // Locking: connectionsLock private int openConnections = 0; // Locking: connectionsLock
private boolean closed = false; // Locking: connectionsLock private boolean closed = false; // Locking: connectionsLock
@@ -267,7 +291,7 @@ abstract class JdbcDatabase implements Database<Connection> {
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
throw new DbException(e); throw new DbException(e);
} }
// Open the database and create the tables if necessary // Open the database and create the tables and indexes if necessary
Connection txn = startTransaction(); Connection txn = startTransaction();
try { try {
if (reopen) { if (reopen) {
@@ -276,6 +300,7 @@ abstract class JdbcDatabase implements Database<Connection> {
createTables(txn); createTables(txn);
storeSchemaVersion(txn); storeSchemaVersion(txn);
} }
createIndexes(txn);
commitTransaction(txn); commitTransaction(txn);
} catch (DbException e) { } catch (DbException e) {
abortTransaction(txn); abortTransaction(txn);
@@ -340,6 +365,23 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
private void createIndexes(Connection txn) throws DbException {
Statement s = null;
try {
s = txn.createStatement();
s.executeUpdate(INDEX_CONTACTS_BY_AUTHOR_ID);
s.executeUpdate(INDEX_MESSAGES_BY_GROUP_ID);
s.executeUpdate(INDEX_OFFERS_BY_CONTACT_ID);
s.executeUpdate(INDEX_GROUPS_BY_CLIENT_ID);
s.executeUpdate(INDEX_MESSAGE_METADATA_BY_MESSAGE_ID);
s.executeUpdate(INDEX_GROUP_METADATA_BY_GROUP_ID);
s.close();
} catch (SQLException e) {
tryToClose(s);
throw new DbException(e);
}
}
private String insertTypeNames(String s) { private String insertTypeNames(String s) {
s = s.replaceAll("HASH", hashType); s = s.replaceAll("HASH", hashType);
s = s.replaceAll("BINARY", binaryType); s = s.replaceAll("BINARY", binaryType);
@@ -993,7 +1035,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " FROM contacts"; + " FROM contacts";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<Contact> contacts = new ArrayList<Contact>(); List<Contact> contacts = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
ContactId contactId = new ContactId(rs.getInt(1)); ContactId contactId = new ContactId(rs.getInt(1));
AuthorId authorId = new AuthorId(rs.getBytes(2)); AuthorId authorId = new AuthorId(rs.getBytes(2));
@@ -1027,7 +1069,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, local.getBytes()); ps.setBytes(1, local.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<ContactId> ids = new ArrayList<ContactId>(); List<ContactId> ids = new ArrayList<>();
while (rs.next()) ids.add(new ContactId(rs.getInt(1))); while (rs.next()) ids.add(new ContactId(rs.getInt(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1052,7 +1094,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, remote.getBytes()); ps.setBytes(1, remote.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<Contact> contacts = new ArrayList<Contact>(); List<Contact> contacts = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
ContactId c = new ContactId(rs.getInt(1)); ContactId c = new ContactId(rs.getInt(1));
String name = rs.getString(2); String name = rs.getString(2);
@@ -1108,7 +1150,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setString(1, c.getString()); ps.setString(1, c.getString());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<Group> groups = new ArrayList<Group>(); List<Group> groups = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
GroupId id = new GroupId(rs.getBytes(1)); GroupId id = new GroupId(rs.getBytes(1));
byte[] descriptor = rs.getBytes(2); byte[] descriptor = rs.getBytes(2);
@@ -1161,7 +1203,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, g.getBytes()); ps.setBytes(1, g.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<ContactId> visible = new ArrayList<ContactId>(); List<ContactId> visible = new ArrayList<>();
while (rs.next()) visible.add(new ContactId(rs.getInt(1))); while (rs.next()) visible.add(new ContactId(rs.getInt(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1213,7 +1255,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " FROM localAuthors"; + " FROM localAuthors";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<LocalAuthor> authors = new ArrayList<LocalAuthor>(); List<LocalAuthor> authors = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
AuthorId authorId = new AuthorId(rs.getBytes(1)); AuthorId authorId = new AuthorId(rs.getBytes(1));
String name = rs.getString(2); String name = rs.getString(2);
@@ -1243,7 +1285,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, g.getBytes()); ps.setBytes(1, g.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1266,7 +1308,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(1, state.getValue()); ps.setInt(1, state.getValue());
ps.setBytes(2, g.getBytes()); ps.setBytes(2, g.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1301,7 +1343,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setString(3, e.getKey()); ps.setString(3, e.getKey());
ps.setBytes(4, e.getValue()); ps.setBytes(4, e.getValue());
rs = ps.executeQuery(); rs = ps.executeQuery();
Set<MessageId> ids = new HashSet<MessageId>(); Set<MessageId> ids = new HashSet<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1335,7 +1377,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(1, DELIVERED.getValue()); ps.setInt(1, DELIVERED.getValue());
ps.setBytes(2, g.getBytes()); ps.setBytes(2, g.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
Map<MessageId, Metadata> all = new HashMap<MessageId, Metadata>(); Map<MessageId, Metadata> all = new HashMap<>();
Metadata metadata = null; Metadata metadata = null;
MessageId lastMessageId = null; MessageId lastMessageId = null;
while (rs.next()) { while (rs.next()) {
@@ -1364,8 +1406,7 @@ abstract class JdbcDatabase implements Database<Connection> {
Collection<MessageId> matches = getMessageIds(txn, g, query); Collection<MessageId> matches = getMessageIds(txn, g, query);
if (matches.isEmpty()) return Collections.emptyMap(); if (matches.isEmpty()) return Collections.emptyMap();
// Retrieve the metadata for each match // Retrieve the metadata for each match
Map<MessageId, Metadata> all = new HashMap<MessageId, Metadata>( Map<MessageId, Metadata> all = new HashMap<>(matches.size());
matches.size());
for (MessageId m : matches) all.put(m, getMessageMetadata(txn, m)); for (MessageId m : matches) all.put(m, getMessageMetadata(txn, m));
return all; return all;
} }
@@ -1463,7 +1504,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setBytes(1, g.getBytes()); ps.setBytes(1, g.getBytes());
ps.setInt(2, c.getInt()); ps.setInt(2, c.getInt());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageStatus> statuses = new ArrayList<MessageStatus>(); List<MessageStatus> statuses = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
MessageId messageId = new MessageId(rs.getBytes(1)); MessageId messageId = new MessageId(rs.getBytes(1));
boolean sent = rs.getBoolean(2); boolean sent = rs.getBoolean(2);
@@ -1522,7 +1563,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, m.getBytes()); ps.setBytes(1, m.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
Map<MessageId, State> dependencies = new HashMap<MessageId, State>(); Map<MessageId, State> dependencies = new HashMap<>();
while (rs.next()) { while (rs.next()) {
MessageId dependency = new MessageId(rs.getBytes(1)); MessageId dependency = new MessageId(rs.getBytes(1));
State state = State.fromValue(rs.getInt(2)); State state = State.fromValue(rs.getInt(2));
@@ -1560,7 +1601,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, m.getBytes()); ps.setBytes(1, m.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
Map<MessageId, State> dependents = new HashMap<MessageId, State>(); Map<MessageId, State> dependents = new HashMap<>();
while (rs.next()) { while (rs.next()) {
MessageId dependent = new MessageId(rs.getBytes(1)); MessageId dependent = new MessageId(rs.getBytes(1));
State state = State.fromValue(rs.getInt(2)); State state = State.fromValue(rs.getInt(2));
@@ -1612,7 +1653,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(1, c.getInt()); ps.setInt(1, c.getInt());
ps.setInt(2, maxMessages); ps.setInt(2, maxMessages);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1648,7 +1689,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setLong(3, now); ps.setLong(3, now);
ps.setInt(4, maxMessages); ps.setInt(4, maxMessages);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1673,7 +1714,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(1, c.getInt()); ps.setInt(1, c.getInt());
ps.setInt(2, maxMessages); ps.setInt(2, maxMessages);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1708,7 +1749,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(2, DELIVERED.getValue()); ps.setInt(2, DELIVERED.getValue());
ps.setLong(3, now); ps.setLong(3, now);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
int total = 0; int total = 0;
while (rs.next()) { while (rs.next()) {
int length = rs.getInt(1); int length = rs.getInt(1);
@@ -1750,7 +1791,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(1, state.getValue()); ps.setInt(1, state.getValue());
ps.setString(2, c.getString()); ps.setString(2, c.getString());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1780,7 +1821,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setString(1, c.getString()); ps.setString(1, c.getString());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
while (rs.next()) ids.add(new MessageId(rs.getBytes(1))); while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1839,7 +1880,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(2, DELIVERED.getValue()); ps.setInt(2, DELIVERED.getValue());
ps.setLong(3, now); ps.setLong(3, now);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
int total = 0; int total = 0;
while (rs.next()) { while (rs.next()) {
int length = rs.getInt(1); int length = rs.getInt(1);
@@ -1893,7 +1934,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setString(1, t.getString()); ps.setString(1, t.getString());
rs = ps.executeQuery(); rs = ps.executeQuery();
List<IncomingKeys> inKeys = new ArrayList<IncomingKeys>(); List<IncomingKeys> inKeys = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
long rotationPeriod = rs.getLong(1); long rotationPeriod = rs.getLong(1);
SecretKey tagKey = new SecretKey(rs.getBytes(2)); SecretKey tagKey = new SecretKey(rs.getBytes(2));
@@ -1913,8 +1954,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setString(1, t.getString()); ps.setString(1, t.getString());
rs = ps.executeQuery(); rs = ps.executeQuery();
Map<ContactId, TransportKeys> keys = Map<ContactId, TransportKeys> keys = new HashMap<>();
new HashMap<ContactId, TransportKeys>();
for (int i = 0; rs.next(); i++) { for (int i = 0; rs.next(); i++) {
// There should be three times as many incoming keys // There should be three times as many incoming keys
if (inKeys.size() < (i + 1) * 3) throw new DbStateException(); if (inKeys.size() < (i + 1) * 3) throw new DbStateException();
@@ -2032,8 +2072,8 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
// Determine which keys are being removed // Determine which keys are being removed
List<String> removed = new ArrayList<String>(); List<String> removed = new ArrayList<>();
Map<String, byte[]> retained = new HashMap<String, byte[]>(); Map<String, byte[]> retained = new HashMap<>();
for (Entry<String, byte[]> e : meta.entrySet()) { for (Entry<String, byte[]> e : meta.entrySet()) {
if (e.getValue() == REMOVE) removed.add(e.getKey()); if (e.getValue() == REMOVE) removed.add(e.getKey());
else retained.put(e.getKey(), e.getValue()); else retained.put(e.getKey(), e.getValue());

View File

@@ -15,7 +15,7 @@ import javax.annotation.concurrent.ThreadSafe;
class EventBusImpl implements EventBus { class EventBusImpl implements EventBus {
private final Collection<EventListener> listeners = private final Collection<EventListener> listeners =
new CopyOnWriteArrayList<EventListener>(); new CopyOnWriteArrayList<>();
@Override @Override
public void addListener(EventListener l) { public void addListener(EventListener l) {

View File

@@ -50,10 +50,9 @@ class KeyAgreementConnector {
private final PluginManager pluginManager; private final PluginManager pluginManager;
private final CompletionService<KeyAgreementConnection> connect; private final CompletionService<KeyAgreementConnection> connect;
private final List<KeyAgreementListener> listeners = private final List<KeyAgreementListener> listeners = new ArrayList<>();
new ArrayList<KeyAgreementListener>();
private final List<Future<KeyAgreementConnection>> pending = private final List<Future<KeyAgreementConnection>> pending =
new ArrayList<Future<KeyAgreementConnection>>(); new ArrayList<>();
private volatile boolean connecting = false; private volatile boolean connecting = false;
private volatile boolean alice = false; private volatile boolean alice = false;
@@ -65,8 +64,7 @@ class KeyAgreementConnector {
this.clock = clock; this.clock = clock;
this.crypto = crypto; this.crypto = crypto;
this.pluginManager = pluginManager; this.pluginManager = pluginManager;
connect = new ExecutorCompletionService<KeyAgreementConnection>( connect = new ExecutorCompletionService<>(ioExecutor);
ioExecutor);
} }
public Payload listen(KeyPair localKeyPair) { public Payload listen(KeyPair localKeyPair) {
@@ -75,8 +73,7 @@ class KeyAgreementConnector {
byte[] commitment = crypto.deriveKeyCommitment( byte[] commitment = crypto.deriveKeyCommitment(
localKeyPair.getPublic().getEncoded()); localKeyPair.getPublic().getEncoded());
// Start all listeners and collect their descriptors // Start all listeners and collect their descriptors
List<TransportDescriptor> descriptors = List<TransportDescriptor> descriptors = new ArrayList<>();
new ArrayList<TransportDescriptor>();
for (DuplexPlugin plugin : pluginManager.getKeyAgreementPlugins()) { for (DuplexPlugin plugin : pluginManager.getKeyAgreementPlugins()) {
KeyAgreementListener l = KeyAgreementListener l =
plugin.createKeyAgreementListener(commitment); plugin.createKeyAgreementListener(commitment);
@@ -132,10 +129,7 @@ class KeyAgreementConnector {
LOG.info("Interrupted while waiting for connection"); LOG.info("Interrupted while waiting for connection");
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
return null; return null;
} catch (ExecutionException e) { } catch (ExecutionException | IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return null;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return null; return null;
} finally { } finally {

View File

@@ -51,8 +51,7 @@ class PayloadParserImpl implements PayloadParser {
byte[] commitment = payload.getRaw(1); byte[] commitment = payload.getRaw(1);
if (commitment.length != COMMIT_LENGTH) throw new FormatException(); if (commitment.length != COMMIT_LENGTH) throw new FormatException();
// Remaining elements: transport descriptors // Remaining elements: transport descriptors
List<TransportDescriptor> recognised = List<TransportDescriptor> recognised = new ArrayList<>();
new ArrayList<TransportDescriptor>();
for (int i = 2; i < payload.size(); i++) { for (int i = 2; i < payload.size(); i++) {
BdfList descriptor = payload.getList(i); BdfList descriptor = payload.getList(i);
long transportId = descriptor.getLong(0); long transportId = descriptor.getLong(0);

View File

@@ -63,9 +63,9 @@ class LifecycleManagerImpl implements LifecycleManager {
this.crypto = crypto; this.crypto = crypto;
this.authorFactory = authorFactory; this.authorFactory = authorFactory;
this.identityManager = identityManager; this.identityManager = identityManager;
services = new CopyOnWriteArrayList<Service>(); services = new CopyOnWriteArrayList<>();
clients = new CopyOnWriteArrayList<Client>(); clients = new CopyOnWriteArrayList<>();
executors = new CopyOnWriteArrayList<ExecutorService>(); executors = new CopyOnWriteArrayList<>();
} }
@Override @Override
@@ -88,7 +88,7 @@ class LifecycleManagerImpl implements LifecycleManager {
executors.add(e); executors.add(e);
} }
private LocalAuthor createLocalAuthor(final String nickname) { private LocalAuthor createLocalAuthor(String nickname) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
KeyPair keyPair = crypto.generateSignatureKeyPair(); KeyPair keyPair = crypto.generateSignatureKeyPair();
byte[] publicKey = keyPair.getPublic().getEncoded(); byte[] publicKey = keyPair.getPublic().getEncoded();
@@ -203,9 +203,7 @@ class LifecycleManagerImpl implements LifecycleManager {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Closing database took " + duration + " ms"); LOG.info("Closing database took " + duration + " ms");
shutdownLatch.countDown(); shutdownLatch.countDown();
} catch (DbException e) { } catch (DbException | ServiceException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (ServiceException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} finally { } finally {
startStopSemaphore.release(); startStopSemaphore.release();

View File

@@ -37,7 +37,7 @@ public class LifecycleModule {
public LifecycleModule() { public LifecycleModule() {
// The thread pool is unbounded, so use direct handoff // The thread pool is unbounded, so use direct handoff
BlockingQueue<Runnable> queue = new SynchronousQueue<Runnable>(); BlockingQueue<Runnable> queue = new SynchronousQueue<>();
// Discard tasks that are submitted during shutdown // Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy = RejectedExecutionHandler policy =
new ThreadPoolExecutor.DiscardPolicy(); new ThreadPoolExecutor.DiscardPolicy();

View File

@@ -21,7 +21,7 @@ class ShutdownManagerImpl implements ShutdownManager {
private int nextHandle = 0; private int nextHandle = 0;
ShutdownManagerImpl() { ShutdownManagerImpl() {
hooks = new HashMap<Integer, Thread>(); hooks = new HashMap<>();
} }
@Override @Override

View File

@@ -134,11 +134,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
byte[] tag = readTag(reader); byte[] tag = readTag(reader);
ctx = keyManager.getStreamContext(transportId, tag); ctx = keyManager.getStreamContext(transportId, tag);
} catch (IOException e) { } catch (IOException | DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, false);
return;
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, false); disposeReader(true, false);
return; return;
@@ -249,11 +245,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
byte[] tag = readTag(reader); byte[] tag = readTag(reader);
ctx = keyManager.getStreamContext(transportId, tag); ctx = keyManager.getStreamContext(transportId, tag);
} catch (IOException e) { } catch (IOException | DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, false);
return;
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, false); disposeReader(true, false);
return; return;
@@ -266,12 +258,7 @@ class ConnectionManagerImpl implements ConnectionManager {
contactId = ctx.getContactId(); contactId = ctx.getContactId();
connectionRegistry.registerConnection(contactId, transportId, true); connectionRegistry.registerConnection(contactId, transportId, true);
// Start the outgoing session on another thread // Start the outgoing session on another thread
ioExecutor.execute(new Runnable() { ioExecutor.execute(this::runOutgoingSession);
@Override
public void run() {
runOutgoingSession();
}
});
try { try {
// Create and run the incoming session // Create and run the incoming session
incomingSession = createIncomingSession(ctx, reader); incomingSession = createIncomingSession(ctx, reader);
@@ -368,12 +355,7 @@ class ConnectionManagerImpl implements ConnectionManager {
return; return;
} }
// Start the incoming session on another thread // Start the incoming session on another thread
ioExecutor.execute(new Runnable() { ioExecutor.execute(this::runIncomingSession);
@Override
public void run() {
runIncomingSession();
}
});
try { try {
// Create and run the outgoing session // Create and run the outgoing session
outgoingSession = createDuplexOutgoingSession(ctx, writer); outgoingSession = createDuplexOutgoingSession(ctx, writer);
@@ -391,11 +373,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
byte[] tag = readTag(reader); byte[] tag = readTag(reader);
ctx = keyManager.getStreamContext(transportId, tag); ctx = keyManager.getStreamContext(transportId, tag);
} catch (IOException e) { } catch (IOException | DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, false);
return;
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, false); disposeReader(true, false);
return; return;

View File

@@ -42,8 +42,8 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
@Inject @Inject
ConnectionRegistryImpl(EventBus eventBus) { ConnectionRegistryImpl(EventBus eventBus) {
this.eventBus = eventBus; this.eventBus = eventBus;
connections = new HashMap<TransportId, Map<ContactId, Integer>>(); connections = new HashMap<>();
contactCounts = new HashMap<ContactId, Integer>(); contactCounts = new HashMap<>();
} }
@Override @Override
@@ -58,7 +58,7 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
try { try {
Map<ContactId, Integer> m = connections.get(t); Map<ContactId, Integer> m = connections.get(t);
if (m == null) { if (m == null) {
m = new HashMap<ContactId, Integer>(); m = new HashMap<>();
connections.put(t, m); connections.put(t, m);
} }
Integer count = m.get(c); Integer count = m.get(c);
@@ -124,7 +124,7 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
try { try {
Map<ContactId, Integer> m = connections.get(t); Map<ContactId, Integer> m = connections.get(t);
if (m == null) return Collections.emptyList(); if (m == null) return Collections.emptyList();
List<ContactId> ids = new ArrayList<ContactId>(m.keySet()); List<ContactId> ids = new ArrayList<>(m.keySet());
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info(ids.size() + " contacts connected"); LOG.info(ids.size() + " contacts connected");
return ids; return ids;

View File

@@ -82,10 +82,10 @@ class PluginManagerImpl implements PluginManager, Service {
this.settingsManager = settingsManager; this.settingsManager = settingsManager;
this.transportPropertyManager = transportPropertyManager; this.transportPropertyManager = transportPropertyManager;
this.uiCallback = uiCallback; this.uiCallback = uiCallback;
plugins = new ConcurrentHashMap<TransportId, Plugin>(); plugins = new ConcurrentHashMap<>();
simplexPlugins = new CopyOnWriteArrayList<SimplexPlugin>(); simplexPlugins = new CopyOnWriteArrayList<>();
duplexPlugins = new CopyOnWriteArrayList<DuplexPlugin>(); duplexPlugins = new CopyOnWriteArrayList<>();
startLatches = new ConcurrentHashMap<TransportId, CountDownLatch>(); startLatches = new ConcurrentHashMap<>();
} }
@Override @Override
@@ -156,17 +156,17 @@ class PluginManagerImpl implements PluginManager, Service {
@Override @Override
public Collection<SimplexPlugin> getSimplexPlugins() { public Collection<SimplexPlugin> getSimplexPlugins() {
return new ArrayList<SimplexPlugin>(simplexPlugins); return new ArrayList<>(simplexPlugins);
} }
@Override @Override
public Collection<DuplexPlugin> getDuplexPlugins() { public Collection<DuplexPlugin> getDuplexPlugins() {
return new ArrayList<DuplexPlugin>(duplexPlugins); return new ArrayList<>(duplexPlugins);
} }
@Override @Override
public Collection<DuplexPlugin> getKeyAgreementPlugins() { public Collection<DuplexPlugin> getKeyAgreementPlugins() {
List<DuplexPlugin> supported = new ArrayList<DuplexPlugin>(); List<DuplexPlugin> supported = new ArrayList<>();
for (DuplexPlugin d : duplexPlugins) for (DuplexPlugin d : duplexPlugins)
if (d.supportsKeyAgreement()) supported.add(d); if (d.supportsKeyAgreement()) supported.add(d);
return supported; return supported;

View File

@@ -66,7 +66,7 @@ class Poller implements EventListener {
this.random = random; this.random = random;
this.clock = clock; this.clock = clock;
lock = new ReentrantLock(); lock = new ReentrantLock();
tasks = new HashMap<TransportId, PollTask>(); tasks = new HashMap<>();
} }
@Override @Override
@@ -111,30 +111,24 @@ class Poller implements EventListener {
connectToContact(c, (DuplexPlugin) p); connectToContact(c, (DuplexPlugin) p);
} }
private void connectToContact(final ContactId c, final SimplexPlugin p) { private void connectToContact(ContactId c, SimplexPlugin p) {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override TransportId t = p.getId();
public void run() { if (!connectionRegistry.isConnected(c, t)) {
TransportId t = p.getId(); TransportConnectionWriter w = p.createWriter(c);
if (!connectionRegistry.isConnected(c, t)) { if (w != null)
TransportConnectionWriter w = p.createWriter(c); connectionManager.manageOutgoingConnection(c, t, w);
if (w != null)
connectionManager.manageOutgoingConnection(c, t, w);
}
} }
}); });
} }
private void connectToContact(final ContactId c, final DuplexPlugin p) { private void connectToContact(ContactId c, DuplexPlugin p) {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override TransportId t = p.getId();
public void run() { if (!connectionRegistry.isConnected(c, t)) {
TransportId t = p.getId(); DuplexTransportConnection d = p.createConnection(c);
if (!connectionRegistry.isConnected(c, t)) { if (d != null)
DuplexTransportConnection d = p.createConnection(c); connectionManager.manageOutgoingConnection(c, t, d);
if (d != null)
connectionManager.manageOutgoingConnection(c, t, d);
}
} }
}); });
} }
@@ -159,14 +153,10 @@ class Poller implements EventListener {
try { try {
PollTask scheduled = tasks.get(t); PollTask scheduled = tasks.get(t);
if (scheduled == null || due < scheduled.due) { if (scheduled == null || due < scheduled.due) {
final PollTask task = new PollTask(p, due, randomiseNext); PollTask task = new PollTask(p, due, randomiseNext);
tasks.put(t, task); tasks.put(t, task);
scheduler.schedule(new Runnable() { scheduler.schedule(
@Override () -> ioExecutor.execute(task), delay, MILLISECONDS);
public void run() {
ioExecutor.execute(task);
}
}, delay, MILLISECONDS);
} }
} finally { } finally {
lock.unlock(); lock.unlock();
@@ -174,7 +164,7 @@ class Poller implements EventListener {
} }
@IoExecutor @IoExecutor
private void poll(final Plugin p) { private void poll(Plugin p) {
TransportId t = p.getId(); TransportId t = p.getId();
if (LOG.isLoggable(INFO)) LOG.info("Polling plugin " + t); if (LOG.isLoggable(INFO)) LOG.info("Polling plugin " + t);
p.poll(connectionRegistry.getConnectedContacts(t)); p.poll(connectionRegistry.getConnectedContacts(t));

View File

@@ -108,7 +108,7 @@ abstract class FilePlugin implements SimplexPlugin {
} }
} }
protected void createReaderFromFile(final File f) { protected void createReaderFromFile(File f) {
if (!running) return; if (!running) return;
ioExecutor.execute(new ReaderCreator(f)); ioExecutor.execute(new ReaderCreator(f));
} }

View File

@@ -63,7 +63,7 @@ class LanTcpPlugin extends TcpPlugin {
TransportProperties p = callback.getLocalProperties(); TransportProperties p = callback.getLocalProperties();
String oldIpPorts = p.get(PROP_IP_PORTS); String oldIpPorts = p.get(PROP_IP_PORTS);
List<InetSocketAddress> olds = parseSocketAddresses(oldIpPorts); List<InetSocketAddress> olds = parseSocketAddresses(oldIpPorts);
List<InetSocketAddress> locals = new LinkedList<InetSocketAddress>(); List<InetSocketAddress> locals = new LinkedList<>();
for (InetAddress local : getLocalIpAddresses()) { for (InetAddress local : getLocalIpAddresses()) {
if (isAcceptableAddress(local)) { if (isAcceptableAddress(local)) {
// If this is the old address, try to use the same port // If this is the old address, try to use the same port
@@ -82,7 +82,7 @@ class LanTcpPlugin extends TcpPlugin {
private List<InetSocketAddress> parseSocketAddresses(String ipPorts) { private List<InetSocketAddress> parseSocketAddresses(String ipPorts) {
if (StringUtils.isNullOrEmpty(ipPorts)) return Collections.emptyList(); if (StringUtils.isNullOrEmpty(ipPorts)) return Collections.emptyList();
String[] split = ipPorts.split(SEPARATOR); String[] split = ipPorts.split(SEPARATOR);
List<InetSocketAddress> addresses = new ArrayList<InetSocketAddress>(); List<InetSocketAddress> addresses = new ArrayList<>();
for (String ipPort : split) { for (String ipPort : split) {
InetSocketAddress a = parseSocketAddress(ipPort); InetSocketAddress a = parseSocketAddress(ipPort);
if (a != null) addresses.add(a); if (a != null) addresses.add(a);
@@ -95,7 +95,7 @@ class LanTcpPlugin extends TcpPlugin {
String ipPort = getIpPortString(a); String ipPort = getIpPortString(a);
// Get the list of recently used addresses // Get the list of recently used addresses
String setting = callback.getSettings().get(PREF_LAN_IP_PORTS); String setting = callback.getSettings().get(PREF_LAN_IP_PORTS);
List<String> recent = new ArrayList<String>(); List<String> recent = new ArrayList<>();
if (!StringUtils.isNullOrEmpty(setting)) if (!StringUtils.isNullOrEmpty(setting))
Collections.addAll(recent, setting.split(SEPARATOR)); Collections.addAll(recent, setting.split(SEPARATOR));
// Is the address already in the list? // Is the address already in the list?
@@ -111,7 +111,7 @@ class LanTcpPlugin extends TcpPlugin {
recent = recent.subList(0, MAX_ADDRESSES); recent = recent.subList(0, MAX_ADDRESSES);
setting = StringUtils.join(recent, SEPARATOR); setting = StringUtils.join(recent, SEPARATOR);
// Update the list of addresses shared with contacts // Update the list of addresses shared with contacts
List<String> shared = new ArrayList<String>(recent); List<String> shared = new ArrayList<>(recent);
Collections.sort(shared); Collections.sort(shared);
String property = StringUtils.join(shared, SEPARATOR); String property = StringUtils.join(shared, SEPARATOR);
TransportProperties properties = new TransportProperties(); TransportProperties properties = new TransportProperties();
@@ -260,16 +260,12 @@ class LanTcpPlugin extends TcpPlugin {
@Override @Override
public Callable<KeyAgreementConnection> listen() { public Callable<KeyAgreementConnection> listen() {
return new Callable<KeyAgreementConnection>() { return () -> {
@Override Socket s = ss.accept();
public KeyAgreementConnection call() throws IOException { if (LOG.isLoggable(INFO))
Socket s = ss.accept(); LOG.info(ID.getString() + ": Incoming connection");
if (LOG.isLoggable(INFO)) return new KeyAgreementConnection(
LOG.info(ID.getString() + ": Incoming connection"); new TcpTransportConnection(LanTcpPlugin.this, s), ID);
return new KeyAgreementConnection(
new TcpTransportConnection(LanTcpPlugin.this, s),
ID);
}
}; };
} }

View File

@@ -37,7 +37,7 @@ class PortMapperImpl implements PortMapper {
} }
@Override @Override
public MappingResult map(final int port) { public MappingResult map(int port) {
if (!started.getAndSet(true)) start(); if (!started.getAndSet(true)) start();
if (gateway == null) return null; if (gateway == null) return null;
InetAddress internal = gateway.getLocalAddress(); InetAddress internal = gateway.getLocalAddress();
@@ -50,12 +50,7 @@ class PortMapperImpl implements PortMapper {
succeeded = gateway.addPortMapping(port, port, succeeded = gateway.addPortMapping(port, port,
getHostAddress(internal), "TCP", "TCP"); getHostAddress(internal), "TCP", "TCP");
if (succeeded) { if (succeeded) {
shutdownManager.addShutdownHook(new Runnable() { shutdownManager.addShutdownHook(() -> deleteMapping(port));
@Override
public void run() {
deleteMapping(port);
}
});
} }
String externalString = gateway.getExternalIPAddress(); String externalString = gateway.getExternalIPAddress();
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
@@ -63,9 +58,7 @@ class PortMapperImpl implements PortMapper {
"External address " + scrubInetAddress(externalString)); "External address " + scrubInetAddress(externalString));
if (externalString != null) if (externalString != null)
external = InetAddress.getByName(externalString); external = InetAddress.getByName(externalString);
} catch (IOException e) { } catch (IOException | SAXException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (SAXException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} }
return new MappingResult(internal, external, port, succeeded); return new MappingResult(internal, external, port, succeeded);
@@ -82,11 +75,7 @@ class PortMapperImpl implements PortMapper {
GatewayDiscover d = new GatewayDiscover(); GatewayDiscover d = new GatewayDiscover();
try { try {
d.discover(); d.discover();
} catch (IOException e) { } catch (IOException | SAXException | ParserConfigurationException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (SAXException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (ParserConfigurationException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} }
gateway = d.getValidGateway(); gateway = d.getValidGateway();
@@ -97,9 +86,7 @@ class PortMapperImpl implements PortMapper {
gateway.deletePortMapping(port, "TCP"); gateway.deletePortMapping(port, "TCP");
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Deleted mapping for port " + port); LOG.info("Deleted mapping for port " + port);
} catch (IOException e) { } catch (IOException | SAXException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (SAXException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} }
} }

View File

@@ -110,41 +110,37 @@ abstract class TcpPlugin implements DuplexPlugin {
} }
protected void bind() { protected void bind() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override if (!running) return;
public void run() { ServerSocket ss = null;
if (!running) return; for (InetSocketAddress addr : getLocalSocketAddresses()) {
ServerSocket ss = null; try {
for (InetSocketAddress addr : getLocalSocketAddresses()) { ss = new ServerSocket();
try { ss.bind(addr);
ss = new ServerSocket(); break;
ss.bind(addr); } catch (IOException e) {
break; if (LOG.isLoggable(INFO))
} catch (IOException e) { LOG.info("Failed to bind " + scrubSocketAddress(addr));
if (LOG.isLoggable(INFO))
LOG.info("Failed to bind " +
scrubSocketAddress(addr));
tryToClose(ss);
}
}
if (ss == null || !ss.isBound()) {
LOG.info("Could not bind server socket");
return;
}
if (!running) {
tryToClose(ss); tryToClose(ss);
return;
} }
socket = ss;
backoff.reset();
InetSocketAddress local =
(InetSocketAddress) ss.getLocalSocketAddress();
setLocalSocketAddress(local);
if (LOG.isLoggable(INFO))
LOG.info("Listening on " + scrubSocketAddress(local));
callback.transportEnabled();
acceptContactConnections();
} }
if (ss == null || !ss.isBound()) {
LOG.info("Could not bind server socket");
return;
}
if (!running) {
tryToClose(ss);
return;
}
socket = ss;
backoff.reset();
InetSocketAddress local =
(InetSocketAddress) ss.getLocalSocketAddress();
setLocalSocketAddress(local);
if (LOG.isLoggable(INFO))
LOG.info("Listening on " + scrubSocketAddress(local));
callback.transportEnabled();
acceptContactConnections();
}); });
} }
@@ -218,17 +214,13 @@ abstract class TcpPlugin implements DuplexPlugin {
} }
} }
private void connectAndCallBack(final ContactId c, private void connectAndCallBack(ContactId c, TransportProperties p) {
final TransportProperties p) { ioExecutor.execute(() -> {
ioExecutor.execute(new Runnable() { if (!isRunning()) return;
@Override DuplexTransportConnection d = createConnection(p);
public void run() { if (d != null) {
if (!isRunning()) return; backoff.reset();
DuplexTransportConnection d = createConnection(p); callback.outgoingConnectionCreated(c, d);
if (d != null) {
backoff.reset();
callback.outgoingConnectionCreated(c, d);
}
} }
}); });
} }
@@ -317,7 +309,7 @@ abstract class TcpPlugin implements DuplexPlugin {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return Collections.emptyList(); return Collections.emptyList();
} }
List<InetAddress> addrs = new ArrayList<InetAddress>(); List<InetAddress> addrs = new ArrayList<>();
for (NetworkInterface iface : ifaces) for (NetworkInterface iface : ifaces)
addrs.addAll(Collections.list(iface.getInetAddresses())); addrs.addAll(Collections.list(iface.getInetAddresses()));
return addrs; return addrs;

View File

@@ -43,7 +43,7 @@ class WanTcpPlugin extends TcpPlugin {
// Use the same address and port as last time if available // Use the same address and port as last time if available
TransportProperties p = callback.getLocalProperties(); TransportProperties p = callback.getLocalProperties();
InetSocketAddress old = parseSocketAddress(p.get(PROP_IP_PORT)); InetSocketAddress old = parseSocketAddress(p.get(PROP_IP_PORT));
List<InetSocketAddress> addrs = new LinkedList<InetSocketAddress>(); List<InetSocketAddress> addrs = new LinkedList<>();
for (InetAddress a : getLocalIpAddresses()) { for (InetAddress a : getLocalIpAddresses()) {
if (isAcceptableAddress(a)) { if (isAcceptableAddress(a)) {
// If this is the old address, try to use the same port // If this is the old address, try to use the same port

View File

@@ -40,9 +40,12 @@ public class PropertiesModule {
@Provides @Provides
@Singleton @Singleton
TransportPropertyManager getTransportPropertyManager( TransportPropertyManager getTransportPropertyManager(
LifecycleManager lifecycleManager, ContactManager contactManager, LifecycleManager lifecycleManager,
ValidationManager validationManager, ContactManager contactManager,
TransportPropertyManagerImpl transportPropertyManager) { TransportPropertyManagerImpl transportPropertyManager) {
lifecycleManager.registerClient(transportPropertyManager); lifecycleManager.registerClient(transportPropertyManager);
validationManager.registerIncomingMessageHook(CLIENT_ID,
transportPropertyManager);
contactManager.registerAddContactHook(transportPropertyManager); contactManager.registerAddContactHook(transportPropertyManager);
contactManager.registerRemoveContactHook(transportPropertyManager); contactManager.registerRemoveContactHook(transportPropertyManager);
return transportPropertyManager; return transportPropertyManager;

View File

@@ -9,8 +9,10 @@ import org.briarproject.bramble.api.contact.ContactManager.AddContactHook;
import org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook; import org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook;
import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataParser;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
@@ -19,8 +21,10 @@ import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.sync.Client; import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import java.util.HashMap; import java.util.HashMap;
@@ -36,20 +40,22 @@ import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
class TransportPropertyManagerImpl implements TransportPropertyManager, class TransportPropertyManagerImpl implements TransportPropertyManager,
Client, AddContactHook, RemoveContactHook { Client, AddContactHook, RemoveContactHook, IncomingMessageHook {
private final DatabaseComponent db; private final DatabaseComponent db;
private final ClientHelper clientHelper; private final ClientHelper clientHelper;
private final MetadataParser metadataParser;
private final ContactGroupFactory contactGroupFactory; private final ContactGroupFactory contactGroupFactory;
private final Clock clock; private final Clock clock;
private final Group localGroup; private final Group localGroup;
@Inject @Inject
TransportPropertyManagerImpl(DatabaseComponent db, TransportPropertyManagerImpl(DatabaseComponent db,
ClientHelper clientHelper, ContactGroupFactory contactGroupFactory, ClientHelper clientHelper, MetadataParser metadataParser,
Clock clock) { ContactGroupFactory contactGroupFactory, Clock clock) {
this.db = db; this.db = db;
this.clientHelper = clientHelper; this.clientHelper = clientHelper;
this.metadataParser = metadataParser;
this.contactGroupFactory = contactGroupFactory; this.contactGroupFactory = contactGroupFactory;
this.clock = clock; this.clock = clock;
localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID); localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID);
@@ -84,6 +90,31 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
db.removeGroup(txn, getContactGroup(c)); db.removeGroup(txn, getContactGroup(c));
} }
@Override
public boolean incomingMessage(Transaction txn, Message m, Metadata meta)
throws DbException, InvalidMessageException {
try {
// Find the latest update for this transport, if any
BdfDictionary d = metadataParser.parse(meta);
TransportId t = new TransportId(d.getString("transportId"));
LatestUpdate latest = findLatest(txn, m.getGroupId(), t, false);
if (latest != null) {
if (d.getLong("version") > latest.version) {
// This update is newer - delete the previous update
db.deleteMessage(txn, latest.messageId);
db.deleteMessageMetadata(txn, latest.messageId);
} else {
// We've already received a newer update - delete this one
db.deleteMessage(txn, m.getId());
db.deleteMessageMetadata(txn, m.getId());
}
}
} catch (FormatException e) {
throw new InvalidMessageException(e);
}
return false;
}
@Override @Override
public void addRemoteProperties(Transaction txn, ContactId c, public void addRemoteProperties(Transaction txn, ContactId c,
Map<TransportId, TransportProperties> props) throws DbException { Map<TransportId, TransportProperties> props) throws DbException {
@@ -98,7 +129,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
public Map<TransportId, TransportProperties> getLocalProperties() public Map<TransportId, TransportProperties> getLocalProperties()
throws DbException { throws DbException {
Map<TransportId, TransportProperties> local; Map<TransportId, TransportProperties> local;
Transaction txn = db.startTransaction(true); // TODO: Transaction can be read-only when code is simplified
Transaction txn = db.startTransaction(false);
try { try {
local = getLocalProperties(txn); local = getLocalProperties(txn);
db.commitTransaction(txn); db.commitTransaction(txn);
@@ -112,11 +144,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
public Map<TransportId, TransportProperties> getLocalProperties( public Map<TransportId, TransportProperties> getLocalProperties(
Transaction txn) throws DbException { Transaction txn) throws DbException {
try { try {
Map<TransportId, TransportProperties> local = Map<TransportId, TransportProperties> local = new HashMap<>();
new HashMap<TransportId, TransportProperties>();
// Find the latest local update for each transport // Find the latest local update for each transport
Map<TransportId, LatestUpdate> latest = findLatest(txn, Map<TransportId, LatestUpdate> latest = findLatestLocal(txn);
localGroup.getId(), true);
// Retrieve and parse the latest local properties // Retrieve and parse the latest local properties
for (Entry<TransportId, LatestUpdate> e : latest.entrySet()) { for (Entry<TransportId, LatestUpdate> e : latest.entrySet()) {
BdfList message = clientHelper.getMessageAsList(txn, BdfList message = clientHelper.getMessageAsList(txn,
@@ -135,7 +165,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
throws DbException { throws DbException {
try { try {
TransportProperties p = null; TransportProperties p = null;
Transaction txn = db.startTransaction(true); // TODO: Transaction can be read-only when code is simplified
Transaction txn = db.startTransaction(false);
try { try {
// Find the latest local update // Find the latest local update
LatestUpdate latest = findLatest(txn, localGroup.getId(), t, LatestUpdate latest = findLatest(txn, localGroup.getId(), t,
@@ -160,9 +191,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Override @Override
public Map<ContactId, TransportProperties> getRemoteProperties( public Map<ContactId, TransportProperties> getRemoteProperties(
TransportId t) throws DbException { TransportId t) throws DbException {
Map<ContactId, TransportProperties> remote = Map<ContactId, TransportProperties> remote = new HashMap<>();
new HashMap<ContactId, TransportProperties>(); // TODO: Transaction can be read-only when code is simplified
Transaction txn = db.startTransaction(true); Transaction txn = db.startTransaction(false);
try { try {
for (Contact c : db.getContacts(txn)) for (Contact c : db.getContacts(txn))
remote.put(c.getId(), getRemoteProperties(txn, c, t)); remote.put(c.getId(), getRemoteProperties(txn, c, t));
@@ -196,7 +227,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
public TransportProperties getRemoteProperties(ContactId c, TransportId t) public TransportProperties getRemoteProperties(ContactId c, TransportId t)
throws DbException { throws DbException {
TransportProperties p; TransportProperties p;
Transaction txn = db.startTransaction(true); // TODO: Transaction can be read-only when code is simplified
Transaction txn = db.startTransaction(false);
try { try {
p = getRemoteProperties(txn, db.getContact(txn, c), t); p = getRemoteProperties(txn, db.getContact(txn, c), t);
db.commitTransaction(txn); db.commitTransaction(txn);
@@ -234,6 +266,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
long version = latest == null ? 1 : latest.version + 1; long version = latest == null ? 1 : latest.version + 1;
storeMessage(txn, localGroup.getId(), t, merged, version, storeMessage(txn, localGroup.getId(), t, merged, version,
true, false); true, false);
// Delete the previous update, if any
if (latest != null)
db.removeMessage(txn, latest.messageId);
// Store the merged properties in each contact's group // Store the merged properties in each contact's group
for (Contact c : db.getContacts(txn)) { for (Contact c : db.getContacts(txn)) {
Group g = getContactGroup(c); Group g = getContactGroup(c);
@@ -241,6 +276,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
version = latest == null ? 1 : latest.version + 1; version = latest == null ? 1 : latest.version + 1;
storeMessage(txn, g.getId(), t, merged, version, storeMessage(txn, g.getId(), t, merged, version,
true, true); true, true);
// Delete the previous update, if any
if (latest != null)
db.removeMessage(txn, latest.messageId);
} }
} }
db.commitTransaction(txn); db.commitTransaction(txn);
@@ -278,20 +316,26 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
return BdfList.of(t.getString(), version, p); return BdfList.of(t.getString(), version, p);
} }
private Map<TransportId, LatestUpdate> findLatest(Transaction txn, private Map<TransportId, LatestUpdate> findLatestLocal(Transaction txn)
GroupId g, boolean local) throws DbException, FormatException { throws DbException, FormatException {
Map<TransportId, LatestUpdate> latestUpdates = // TODO: This can be simplified before 1.0
new HashMap<TransportId, LatestUpdate>(); Map<TransportId, LatestUpdate> latestUpdates = new HashMap<>();
Map<MessageId, BdfDictionary> metadata = Map<MessageId, BdfDictionary> metadata = clientHelper
clientHelper.getMessageMetadataAsDictionary(txn, g); .getMessageMetadataAsDictionary(txn, localGroup.getId());
for (Entry<MessageId, BdfDictionary> e : metadata.entrySet()) { for (Entry<MessageId, BdfDictionary> e : metadata.entrySet()) {
BdfDictionary meta = e.getValue(); BdfDictionary meta = e.getValue();
if (meta.getBoolean("local") == local) { TransportId t = new TransportId(meta.getString("transportId"));
TransportId t = new TransportId(meta.getString("transportId")); long version = meta.getLong("version");
long version = meta.getLong("version"); LatestUpdate latest = latestUpdates.get(t);
LatestUpdate latest = latestUpdates.get(t); if (latest == null) {
if (latest == null || version > latest.version) latestUpdates.put(t, new LatestUpdate(e.getKey(), version));
latestUpdates.put(t, new LatestUpdate(e.getKey(), version)); } else if (version > latest.version) {
// This update is newer - delete the previous one
db.removeMessage(txn, latest.messageId);
latestUpdates.put(t, new LatestUpdate(e.getKey(), version));
} else {
// We've already found a newer update - delete this one
db.removeMessage(txn, e.getKey());
} }
} }
return latestUpdates; return latestUpdates;
@@ -300,6 +344,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Nullable @Nullable
private LatestUpdate findLatest(Transaction txn, GroupId g, TransportId t, private LatestUpdate findLatest(Transaction txn, GroupId g, TransportId t,
boolean local) throws DbException, FormatException { boolean local) throws DbException, FormatException {
// TODO: This can be simplified before 1.0
LatestUpdate latest = null; LatestUpdate latest = null;
Map<MessageId, BdfDictionary> metadata = Map<MessageId, BdfDictionary> metadata =
clientHelper.getMessageMetadataAsDictionary(txn, g); clientHelper.getMessageMetadataAsDictionary(txn, g);
@@ -308,8 +353,26 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
if (meta.getString("transportId").equals(t.getString()) if (meta.getString("transportId").equals(t.getString())
&& meta.getBoolean("local") == local) { && meta.getBoolean("local") == local) {
long version = meta.getLong("version"); long version = meta.getLong("version");
if (latest == null || version > latest.version) if (latest == null) {
latest = new LatestUpdate(e.getKey(), version); latest = new LatestUpdate(e.getKey(), version);
} else if (version > latest.version) {
// This update is newer - delete the previous one
if (local) {
db.removeMessage(txn, latest.messageId);
} else {
db.deleteMessage(txn, latest.messageId);
db.deleteMessageMetadata(txn, latest.messageId);
}
latest = new LatestUpdate(e.getKey(), version);
} else {
// We've already found a newer update - delete this one
if (local) {
db.removeMessage(txn, e.getKey());
} else {
db.deleteMessage(txn, e.getKey());
db.deleteMessageMetadata(txn, e.getKey());
}
}
} }
} }
return latest; return latest;

View File

@@ -41,7 +41,7 @@ class Receiver implements ReadHandler {
Receiver(Clock clock, Sender sender) { Receiver(Clock clock, Sender sender) {
this.sender = sender; this.sender = sender;
this.clock = clock; this.clock = clock;
dataFrames = new TreeSet<Data>(new SequenceNumberComparator()); dataFrames = new TreeSet<>(new SequenceNumberComparator());
} }
Data read() throws IOException, InterruptedException { Data read() throws IOException, InterruptedException {

View File

@@ -42,48 +42,44 @@ class ReliabilityLayerImpl implements ReliabilityLayer, WriteHandler {
this.executor = executor; this.executor = executor;
this.clock = clock; this.clock = clock;
this.writeHandler = writeHandler; this.writeHandler = writeHandler;
writes = new LinkedBlockingQueue<byte[]>(); writes = new LinkedBlockingQueue<>();
} }
@Override @Override
public void start() { public void start() {
SlipEncoder encoder = new SlipEncoder(this); SlipEncoder encoder = new SlipEncoder(this);
final Sender sender = new Sender(clock, encoder); Sender sender = new Sender(clock, encoder);
receiver = new Receiver(clock, sender); receiver = new Receiver(clock, sender);
decoder = new SlipDecoder(receiver, Data.MAX_LENGTH); decoder = new SlipDecoder(receiver, Data.MAX_LENGTH);
inputStream = new ReceiverInputStream(receiver); inputStream = new ReceiverInputStream(receiver);
outputStream = new SenderOutputStream(sender); outputStream = new SenderOutputStream(sender);
running = true; running = true;
executor.execute(new Runnable() { executor.execute(() -> {
@Override long now = clock.currentTimeMillis();
public void run() { long next = now + TICK_INTERVAL;
long now = clock.currentTimeMillis(); try {
long next = now + TICK_INTERVAL; while (running) {
try { byte[] b = null;
while (running) { while (now < next && b == null) {
byte[] b = null; b = writes.poll(next - now, MILLISECONDS);
while (now < next && b == null) { if (!running) return;
b = writes.poll(next - now, MILLISECONDS); now = clock.currentTimeMillis();
if (!running) return; }
now = clock.currentTimeMillis(); if (b == null) {
} sender.tick();
if (b == null) { while (next <= now) next += TICK_INTERVAL;
sender.tick(); } else {
while (next <= now) next += TICK_INTERVAL; if (b.length == 0) return; // Poison pill
} else { writeHandler.handleWrite(b);
if (b.length == 0) return; // Poison pill
writeHandler.handleWrite(b);
}
} }
} catch (InterruptedException e) {
LOG.warning("Interrupted while waiting to write");
Thread.currentThread().interrupt();
running = false;
} catch (IOException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
running = false;
} }
} catch (InterruptedException e) {
LOG.warning("Interrupted while waiting to write");
Thread.currentThread().interrupt();
running = false;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
running = false;
} }
}); });
} }

View File

@@ -46,7 +46,7 @@ class Sender {
Sender(Clock clock, WriteHandler writeHandler) { Sender(Clock clock, WriteHandler writeHandler) {
this.clock = clock; this.clock = clock;
this.writeHandler = writeHandler; this.writeHandler = writeHandler;
outstanding = new LinkedList<Outstanding>(); outstanding = new LinkedList<>();
} }
void sendAck(long sequenceNumber, int windowSize) throws IOException { void sendAck(long sequenceNumber, int windowSize) throws IOException {
@@ -136,7 +136,7 @@ class Sender {
if (now - o.lastTransmitted > rto) { if (now - o.lastTransmitted > rto) {
it.remove(); it.remove();
if (retransmit == null) if (retransmit == null)
retransmit = new ArrayList<Outstanding>(); retransmit = new ArrayList<>();
retransmit.add(o); retransmit.add(o);
// Update the retransmission timeout // Update the retransmission timeout
rto <<= 1; rto <<= 1;

View File

@@ -54,12 +54,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(DuplexOutgoingSession.class.getName()); Logger.getLogger(DuplexOutgoingSession.class.getName());
private static final ThrowingRunnable<IOException> CLOSE = private static final ThrowingRunnable<IOException> CLOSE = () -> {};
new ThrowingRunnable<IOException>() {
@Override
public void run() {
}
};
private final DatabaseComponent db; private final DatabaseComponent db;
private final Executor dbExecutor; private final Executor dbExecutor;
@@ -83,7 +78,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
this.maxLatency = maxLatency; this.maxLatency = maxLatency;
this.maxIdleTime = maxIdleTime; this.maxIdleTime = maxIdleTime;
this.recordWriter = recordWriter; this.recordWriter = recordWriter;
writerTasks = new LinkedBlockingQueue<ThrowingRunnable<IOException>>(); writerTasks = new LinkedBlockingQueue<>();
} }
@IoExecutor @IoExecutor

View File

@@ -116,7 +116,7 @@ class RecordReaderImpl implements RecordReader {
private List<MessageId> readMessageIds() throws IOException { private List<MessageId> readMessageIds() throws IOException {
if (payloadLength == 0) throw new FormatException(); if (payloadLength == 0) throw new FormatException();
if (payloadLength % UniqueId.LENGTH != 0) throw new FormatException(); if (payloadLength % UniqueId.LENGTH != 0) throw new FormatException();
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
for (int off = 0; off < payloadLength; off += UniqueId.LENGTH) { for (int off = 0; off < payloadLength; off += UniqueId.LENGTH) {
byte[] id = new byte[UniqueId.LENGTH]; byte[] id = new byte[UniqueId.LENGTH];
System.arraycopy(payload, off, id, 0, UniqueId.LENGTH); System.arraycopy(payload, off, id, 0, UniqueId.LENGTH);

View File

@@ -43,12 +43,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(SimplexOutgoingSession.class.getName()); Logger.getLogger(SimplexOutgoingSession.class.getName());
private static final ThrowingRunnable<IOException> CLOSE = private static final ThrowingRunnable<IOException> CLOSE = () -> {};
new ThrowingRunnable<IOException>() {
@Override
public void run() {
}
};
private final DatabaseComponent db; private final DatabaseComponent db;
private final Executor dbExecutor; private final Executor dbExecutor;
@@ -71,7 +66,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
this.maxLatency = maxLatency; this.maxLatency = maxLatency;
this.recordWriter = recordWriter; this.recordWriter = recordWriter;
outstandingQueries = new AtomicInteger(2); // One per type of record outstandingQueries = new AtomicInteger(2); // One per type of record
writerTasks = new LinkedBlockingQueue<ThrowingRunnable<IOException>>(); writerTasks = new LinkedBlockingQueue<>();
} }
@IoExecutor @IoExecutor

View File

@@ -64,8 +64,8 @@ class ValidationManagerImpl implements ValidationManager, Service,
this.dbExecutor = dbExecutor; this.dbExecutor = dbExecutor;
this.validationExecutor = validationExecutor; this.validationExecutor = validationExecutor;
this.messageFactory = messageFactory; this.messageFactory = messageFactory;
validators = new ConcurrentHashMap<ClientId, MessageValidator>(); validators = new ConcurrentHashMap<>();
hooks = new ConcurrentHashMap<ClientId, IncomingMessageHook>(); hooks = new ConcurrentHashMap<>();
} }
@Override @Override
@@ -93,19 +93,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
hooks.put(c, hook); hooks.put(c, hook);
} }
private void validateOutstandingMessagesAsync(final ClientId c) { private void validateOutstandingMessagesAsync(ClientId c) {
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> validateOutstandingMessages(c));
@Override
public void run() {
validateOutstandingMessages(c);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
private void validateOutstandingMessages(ClientId c) { private void validateOutstandingMessages(ClientId c) {
try { try {
Queue<MessageId> unvalidated = new LinkedList<MessageId>(); Queue<MessageId> unvalidated = new LinkedList<>();
Transaction txn = db.startTransaction(true); Transaction txn = db.startTransaction(true);
try { try {
unvalidated.addAll(db.getMessagesToValidate(txn, c)); unvalidated.addAll(db.getMessagesToValidate(txn, c));
@@ -119,14 +114,9 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
} }
private void validateNextMessageAsync(final Queue<MessageId> unvalidated) { private void validateNextMessageAsync(Queue<MessageId> unvalidated) {
if (unvalidated.isEmpty()) return; if (unvalidated.isEmpty()) return;
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> validateNextMessage(unvalidated));
@Override
public void run() {
validateNextMessage(unvalidated);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
@@ -158,19 +148,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
} }
private void deliverOutstandingMessagesAsync(final ClientId c) { private void deliverOutstandingMessagesAsync(ClientId c) {
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> deliverOutstandingMessages(c));
@Override
public void run() {
deliverOutstandingMessages(c);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
private void deliverOutstandingMessages(ClientId c) { private void deliverOutstandingMessages(ClientId c) {
try { try {
Queue<MessageId> pending = new LinkedList<MessageId>(); Queue<MessageId> pending = new LinkedList<>();
Transaction txn = db.startTransaction(true); Transaction txn = db.startTransaction(true);
try { try {
pending.addAll(db.getPendingMessages(txn, c)); pending.addAll(db.getPendingMessages(txn, c));
@@ -184,15 +169,9 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
} }
private void deliverNextPendingMessageAsync( private void deliverNextPendingMessageAsync(Queue<MessageId> pending) {
final Queue<MessageId> pending) {
if (pending.isEmpty()) return; if (pending.isEmpty()) return;
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> deliverNextPendingMessage(pending));
@Override
public void run() {
deliverNextPendingMessage(pending);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
@@ -229,8 +208,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
pending.addAll(getPendingDependents(txn, id)); pending.addAll(getPendingDependents(txn, id));
if (result.share) { if (result.share) {
db.setMessageShared(txn, id); db.setMessageShared(txn, id);
toShare = new LinkedList<MessageId>( toShare = new LinkedList<>(states.keySet());
states.keySet());
} }
} else { } else {
invalidate = getDependentsToInvalidate(txn, id); invalidate = getDependentsToInvalidate(txn, id);
@@ -255,13 +233,8 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
} }
private void validateMessageAsync(final Message m, final Group g) { private void validateMessageAsync(Message m, Group g) {
validationExecutor.execute(new Runnable() { validationExecutor.execute(() -> validateMessage(m, g));
@Override
public void run() {
validateMessage(m, g);
}
});
} }
@ValidationExecutor @ValidationExecutor
@@ -277,21 +250,16 @@ class ValidationManagerImpl implements ValidationManager, Service,
} catch (InvalidMessageException e) { } catch (InvalidMessageException e) {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.log(INFO, e.toString(), e); LOG.log(INFO, e.toString(), e);
Queue<MessageId> invalidate = new LinkedList<MessageId>(); Queue<MessageId> invalidate = new LinkedList<>();
invalidate.add(m.getId()); invalidate.add(m.getId());
invalidateNextMessageAsync(invalidate); invalidateNextMessageAsync(invalidate);
} }
} }
} }
private void storeMessageContextAsync(final Message m, final ClientId c, private void storeMessageContextAsync(Message m, ClientId c,
final MessageContext result) { MessageContext result) {
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> storeMessageContext(m, c, result));
@Override
public void run() {
storeMessageContext(m, c, result);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
@@ -331,8 +299,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
pending = getPendingDependents(txn, id); pending = getPendingDependents(txn, id);
if (result.share) { if (result.share) {
db.setMessageShared(txn, id); db.setMessageShared(txn, id);
toShare = toShare = new LinkedList<>(dependencies);
new LinkedList<MessageId>(dependencies);
} }
} else { } else {
invalidate = getDependentsToInvalidate(txn, id); invalidate = getDependentsToInvalidate(txn, id);
@@ -378,7 +345,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
@DatabaseExecutor @DatabaseExecutor
private Queue<MessageId> getPendingDependents(Transaction txn, MessageId m) private Queue<MessageId> getPendingDependents(Transaction txn, MessageId m)
throws DbException { throws DbException {
Queue<MessageId> pending = new LinkedList<MessageId>(); Queue<MessageId> pending = new LinkedList<>();
Map<MessageId, State> states = db.getMessageDependents(txn, m); Map<MessageId, State> states = db.getMessageDependents(txn, m);
for (Entry<MessageId, State> e : states.entrySet()) { for (Entry<MessageId, State> e : states.entrySet()) {
if (e.getValue() == PENDING) pending.add(e.getKey()); if (e.getValue() == PENDING) pending.add(e.getKey());
@@ -386,19 +353,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
return pending; return pending;
} }
private void shareOutstandingMessagesAsync(final ClientId c) { private void shareOutstandingMessagesAsync(ClientId c) {
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> shareOutstandingMessages(c));
@Override
public void run() {
shareOutstandingMessages(c);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
private void shareOutstandingMessages(ClientId c) { private void shareOutstandingMessages(ClientId c) {
try { try {
Queue<MessageId> toShare = new LinkedList<MessageId>(); Queue<MessageId> toShare = new LinkedList<>();
Transaction txn = db.startTransaction(true); Transaction txn = db.startTransaction(true);
try { try {
toShare.addAll(db.getMessagesToShare(txn, c)); toShare.addAll(db.getMessagesToShare(txn, c));
@@ -418,14 +380,9 @@ class ValidationManagerImpl implements ValidationManager, Service,
* This method should only be called for messages that have all their * This method should only be called for messages that have all their
* dependencies delivered and have been delivered themselves. * dependencies delivered and have been delivered themselves.
*/ */
private void shareNextMessageAsync(final Queue<MessageId> toShare) { private void shareNextMessageAsync(Queue<MessageId> toShare) {
if (toShare.isEmpty()) return; if (toShare.isEmpty()) return;
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> shareNextMessage(toShare));
@Override
public void run() {
shareNextMessage(toShare);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
@@ -452,14 +409,9 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
} }
private void invalidateNextMessageAsync(final Queue<MessageId> invalidate) { private void invalidateNextMessageAsync(Queue<MessageId> invalidate) {
if (invalidate.isEmpty()) return; if (invalidate.isEmpty()) return;
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> invalidateNextMessage(invalidate));
@Override
public void run() {
invalidateNextMessage(invalidate);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
@@ -496,7 +448,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
@DatabaseExecutor @DatabaseExecutor
private Queue<MessageId> getDependentsToInvalidate(Transaction txn, private Queue<MessageId> getDependentsToInvalidate(Transaction txn,
MessageId m) throws DbException { MessageId m) throws DbException {
Queue<MessageId> invalidate = new LinkedList<MessageId>(); Queue<MessageId> invalidate = new LinkedList<>();
Map<MessageId, State> states = db.getMessageDependents(txn, m); Map<MessageId, State> states = db.getMessageDependents(txn, m);
for (Entry<MessageId, State> e : states.entrySet()) { for (Entry<MessageId, State> e : states.entrySet()) {
if (e.getValue() != INVALID) invalidate.add(e.getKey()); if (e.getValue() != INVALID) invalidate.add(e.getKey());
@@ -514,17 +466,12 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
} }
private void loadGroupAndValidateAsync(final Message m) { private void loadGroupAndValidateAsync(Message m) {
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> loadGroupAndValidate(m));
@Override
public void run() {
loadGroupAndValidate(m);
}
});
} }
@DatabaseExecutor @DatabaseExecutor
private void loadGroupAndValidate(final Message m) { private void loadGroupAndValidate(Message m) {
try { try {
Group g; Group g;
Transaction txn = db.startTransaction(true); Transaction txn = db.startTransaction(true);

View File

@@ -58,15 +58,14 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
this.pluginConfig = pluginConfig; this.pluginConfig = pluginConfig;
this.transportKeyManagerFactory = transportKeyManagerFactory; this.transportKeyManagerFactory = transportKeyManagerFactory;
// Use a ConcurrentHashMap as a thread-safe set // Use a ConcurrentHashMap as a thread-safe set
activeContacts = new ConcurrentHashMap<ContactId, Boolean>(); activeContacts = new ConcurrentHashMap<>();
managers = new ConcurrentHashMap<TransportId, TransportKeyManager>(); managers = new ConcurrentHashMap<>();
} }
@Override @Override
public void startService() throws ServiceException { public void startService() throws ServiceException {
if (used.getAndSet(true)) throw new IllegalStateException(); if (used.getAndSet(true)) throw new IllegalStateException();
Map<TransportId, Integer> transports = Map<TransportId, Integer> transports = new HashMap<>();
new HashMap<TransportId, Integer>();
for (SimplexPluginFactory f : pluginConfig.getSimplexFactories()) for (SimplexPluginFactory f : pluginConfig.getSimplexFactories())
transports.put(f.getId(), f.getMaxLatency()); transports.put(f.getId(), f.getMaxLatency());
for (DuplexPluginFactory f : pluginConfig.getDuplexFactories()) for (DuplexPluginFactory f : pluginConfig.getDuplexFactories())
@@ -156,14 +155,10 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
} }
} }
private void removeContact(final ContactId c) { private void removeContact(ContactId c) {
activeContacts.remove(c); activeContacts.remove(c);
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> {
@Override for (TransportKeyManager m : managers.values()) m.removeContact(c);
public void run() {
for (TransportKeyManager m : managers.values())
m.removeContact(c);
}
}); });
} }
} }

View File

@@ -45,7 +45,7 @@ class ReorderingWindow {
} }
List<Long> getUnseen() { List<Long> getUnseen() {
List<Long> unseen = new ArrayList<Long>(seen.length); List<Long> unseen = new ArrayList<>(seen.length);
for (int i = 0; i < seen.length; i++) for (int i = 0; i < seen.length; i++)
if (!seen[i]) unseen.add(base + i); if (!seen[i]) unseen.add(base + i);
return unseen; return unseen;
@@ -69,8 +69,8 @@ class ReorderingWindow {
return new Change(added, removed); return new Change(added, removed);
} }
// Record the elements that will be added and removed // Record the elements that will be added and removed
List<Long> added = new ArrayList<Long>(slide); List<Long> added = new ArrayList<>(slide);
List<Long> removed = new ArrayList<Long>(slide); List<Long> removed = new ArrayList<>(slide);
for (int i = 0; i < slide; i++) { for (int i = 0; i < slide; i++) {
if (!seen[i]) removed.add(base + i); if (!seen[i]) removed.add(base + i);
added.add(base + seen.length + i); added.add(base + seen.length + i);

View File

@@ -65,9 +65,9 @@ class TransportKeyManagerImpl implements TransportKeyManager {
this.transportId = transportId; this.transportId = transportId;
rotationPeriodLength = maxLatency + MAX_CLOCK_DIFFERENCE; rotationPeriodLength = maxLatency + MAX_CLOCK_DIFFERENCE;
lock = new ReentrantLock(); lock = new ReentrantLock();
inContexts = new HashMap<Bytes, TagContext>(); inContexts = new HashMap<>();
outContexts = new HashMap<ContactId, MutableOutgoingKeys>(); outContexts = new HashMap<>();
keys = new HashMap<ContactId, MutableTransportKeys>(); keys = new HashMap<>();
} }
@Override @Override
@@ -134,32 +134,22 @@ class TransportKeyManagerImpl implements TransportKeyManager {
} }
private void scheduleKeyRotation(long now) { private void scheduleKeyRotation(long now) {
Runnable task = new Runnable() {
@Override
public void run() {
rotateKeys();
}
};
long delay = rotationPeriodLength - now % rotationPeriodLength; long delay = rotationPeriodLength - now % rotationPeriodLength;
scheduler.schedule(task, delay, MILLISECONDS); scheduler.schedule((Runnable) this::rotateKeys, delay, MILLISECONDS);
} }
private void rotateKeys() { private void rotateKeys() {
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> {
@Override try {
public void run() { Transaction txn = db.startTransaction(false);
try { try {
Transaction txn = db.startTransaction(false); rotateKeys(txn);
try { db.commitTransaction(txn);
rotateKeys(txn); } finally {
db.commitTransaction(txn); db.endTransaction(txn);
} finally {
db.endTransaction(txn);
}
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
} }
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} }
}); });
} }
@@ -272,8 +262,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
lock.lock(); lock.lock();
try { try {
// Rotate the keys to the current rotation period // Rotate the keys to the current rotation period
Map<ContactId, TransportKeys> snapshot = Map<ContactId, TransportKeys> snapshot = new HashMap<>();
new HashMap<ContactId, TransportKeys>();
for (Entry<ContactId, MutableTransportKeys> e : keys.entrySet()) for (Entry<ContactId, MutableTransportKeys> e : keys.entrySet())
snapshot.put(e.getKey(), e.getValue().snapshot()); snapshot.put(e.getKey(), e.getValue().snapshot());
RotationResult rotationResult = rotateKeys(snapshot, now); RotationResult rotationResult = rotateKeys(snapshot, now);
@@ -311,8 +300,8 @@ class TransportKeyManagerImpl implements TransportKeyManager {
private final Map<ContactId, TransportKeys> current, rotated; private final Map<ContactId, TransportKeys> current, rotated;
private RotationResult() { private RotationResult() {
current = new HashMap<ContactId, TransportKeys>(); current = new HashMap<>();
rotated = new HashMap<ContactId, TransportKeys>(); rotated = new HashMap<>();
} }
} }
} }

View File

@@ -24,16 +24,13 @@ public class PoliteExecutorTest extends BrambleTestCase {
Executor delegate = Executors.newSingleThreadExecutor(); Executor delegate = Executors.newSingleThreadExecutor();
// Allow all the tasks to be delegated straight away // Allow all the tasks to be delegated straight away
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, TASKS * 2); PoliteExecutor polite = new PoliteExecutor(TAG, delegate, TASKS * 2);
final List<Integer> list = new Vector<Integer>(); List<Integer> list = new Vector<>();
final CountDownLatch latch = new CountDownLatch(TASKS); CountDownLatch latch = new CountDownLatch(TASKS);
for (int i = 0; i < TASKS; i++) { for (int i = 0; i < TASKS; i++) {
final int result = i; int result = i;
polite.execute(new Runnable() { polite.execute(() -> {
@Override list.add(result);
public void run() { latch.countDown();
list.add(result);
latch.countDown();
}
}); });
} }
// Wait for all the tasks to finish // Wait for all the tasks to finish
@@ -49,16 +46,13 @@ public class PoliteExecutorTest extends BrambleTestCase {
Executor delegate = Executors.newSingleThreadExecutor(); Executor delegate = Executors.newSingleThreadExecutor();
// Allow two tasks to be delegated at a time // Allow two tasks to be delegated at a time
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, 2); PoliteExecutor polite = new PoliteExecutor(TAG, delegate, 2);
final List<Integer> list = new Vector<Integer>(); List<Integer> list = new Vector<>();
final CountDownLatch latch = new CountDownLatch(TASKS); CountDownLatch latch = new CountDownLatch(TASKS);
for (int i = 0; i < TASKS; i++) { for (int i = 0; i < TASKS; i++) {
final int result = i; int result = i;
polite.execute(new Runnable() { polite.execute(() -> {
@Override list.add(result);
public void run() { latch.countDown();
list.add(result);
latch.countDown();
}
}); });
} }
// Wait for all the tasks to finish // Wait for all the tasks to finish
@@ -73,23 +67,20 @@ public class PoliteExecutorTest extends BrambleTestCase {
Executor delegate = Executors.newCachedThreadPool(); Executor delegate = Executors.newCachedThreadPool();
// Allow all the tasks to be delegated straight away // Allow all the tasks to be delegated straight away
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, TASKS * 2); PoliteExecutor polite = new PoliteExecutor(TAG, delegate, TASKS * 2);
final List<Integer> list = new Vector<Integer>(); List<Integer> list = new Vector<>();
final CountDownLatch[] latches = new CountDownLatch[TASKS]; CountDownLatch[] latches = new CountDownLatch[TASKS];
for (int i = 0; i < TASKS; i++) latches[i] = new CountDownLatch(1); for (int i = 0; i < TASKS; i++) latches[i] = new CountDownLatch(1);
for (int i = 0; i < TASKS; i++) { for (int i = 0; i < TASKS; i++) {
final int result = i; int result = i;
polite.execute(new Runnable() { polite.execute(() -> {
@Override try {
public void run() { // Each task waits for the next task, if any, to finish
try { if (result < TASKS - 1) latches[result + 1].await();
// Each task waits for the next task, if any, to finish list.add(result);
if (result < TASKS - 1) latches[result + 1].await(); } catch (InterruptedException e) {
list.add(result); fail();
} catch (InterruptedException e) {
fail();
}
latches[result].countDown();
} }
latches[result].countDown();
}); });
} }
// Wait for all the tasks to finish // Wait for all the tasks to finish
@@ -104,22 +95,19 @@ public class PoliteExecutorTest extends BrambleTestCase {
Executor delegate = Executors.newCachedThreadPool(); Executor delegate = Executors.newCachedThreadPool();
// Allow one task to be delegated at a time // Allow one task to be delegated at a time
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, 1); PoliteExecutor polite = new PoliteExecutor(TAG, delegate, 1);
final List<Integer> list = new Vector<Integer>(); List<Integer> list = new Vector<>();
final CountDownLatch latch = new CountDownLatch(TASKS); CountDownLatch latch = new CountDownLatch(TASKS);
for (int i = 0; i < TASKS; i++) { for (int i = 0; i < TASKS; i++) {
final int result = i; int result = i;
polite.execute(new Runnable() { polite.execute(() -> {
@Override try {
public void run() { // Each task runs faster than the previous task
try { Thread.sleep(TASKS - result);
// Each task runs faster than the previous task list.add(result);
Thread.sleep(TASKS - result); } catch (InterruptedException e) {
list.add(result); fail();
} catch (InterruptedException e) {
fail();
}
latch.countDown();
} }
latch.countDown();
}); });
} }
// Wait for all the tasks to finish // Wait for all the tasks to finish

View File

@@ -83,9 +83,9 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
@Test(expected = InvalidMessageException.class) @Test(expected = InvalidMessageException.class)
public void testRejectsTooShortMessage() throws Exception { public void testRejectsTooShortMessage() throws Exception {
final byte[] invalidRaw = new byte[MESSAGE_HEADER_LENGTH]; byte[] invalidRaw = new byte[MESSAGE_HEADER_LENGTH];
// Use a mock message so the length of the raw message can be invalid // Use a mock message so the length of the raw message can be invalid
final Message invalidMessage = context.mock(Message.class); Message invalidMessage = context.mock(Message.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(invalidMessage).getTimestamp(); oneOf(invalidMessage).getTimestamp();
@@ -101,8 +101,8 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
@Test @Test
public void testAcceptsMinLengthMessage() throws Exception { public void testAcceptsMinLengthMessage() throws Exception {
final byte[] shortRaw = new byte[MESSAGE_HEADER_LENGTH + 1]; byte[] shortRaw = new byte[MESSAGE_HEADER_LENGTH + 1];
final Message shortMessage = Message shortMessage =
new Message(messageId, groupId, timestamp, shortRaw); new Message(messageId, groupId, timestamp, shortRaw);
context.checking(new Expectations() {{ context.checking(new Expectations() {{

View File

@@ -76,8 +76,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testAddLocalMessage() throws Exception { public void testAddLocalMessage() throws Exception {
final boolean shared = true; boolean shared = true;
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(false); oneOf(db).startTransaction(false);
@@ -95,7 +95,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testCreateMessage() throws Exception { public void testCreateMessage() throws Exception {
final byte[] bytes = expectToByteArray(list); byte[] bytes = expectToByteArray(list);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(messageFactory).createMessage(groupId, timestamp, bytes); oneOf(messageFactory).createMessage(groupId, timestamp, bytes);
@@ -107,7 +107,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testGetMessageAsList() throws Exception { public void testGetMessageAsList() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
expectToList(true); expectToList(true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -125,7 +125,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testGetGroupMetadataAsDictionary() throws Exception { public void testGetGroupMetadataAsDictionary() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
@@ -145,7 +145,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testGetMessageMetadataAsDictionary() throws Exception { public void testGetMessageMetadataAsDictionary() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
@@ -165,10 +165,9 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testGetMessageMetadataAsDictionaryMap() throws Exception { public void testGetMessageMetadataAsDictionaryMap() throws Exception {
final Map<MessageId, BdfDictionary> map = Map<MessageId, BdfDictionary> map = new HashMap<>();
new HashMap<MessageId, BdfDictionary>();
map.put(messageId, dictionary); map.put(messageId, dictionary);
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
@@ -188,14 +187,13 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testGetMessageMetadataAsDictionaryQuery() throws Exception { public void testGetMessageMetadataAsDictionaryQuery() throws Exception {
final Map<MessageId, BdfDictionary> map = Map<MessageId, BdfDictionary> map = new HashMap<>();
new HashMap<MessageId, BdfDictionary>();
map.put(messageId, dictionary); map.put(messageId, dictionary);
final BdfDictionary query = BdfDictionary query =
BdfDictionary.of(new BdfEntry("query", "me")); BdfDictionary.of(new BdfEntry("query", "me"));
final Metadata queryMetadata = new Metadata(); Metadata queryMetadata = new Metadata();
queryMetadata.put("query", getRandomBytes(42)); queryMetadata.put("query", getRandomBytes(42));
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
@@ -217,7 +215,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testMergeGroupMetadata() throws Exception { public void testMergeGroupMetadata() throws Exception {
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(false); oneOf(db).startTransaction(false);
@@ -235,7 +233,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testMergeMessageMetadata() throws Exception { public void testMergeMessageMetadata() throws Exception {
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(false); oneOf(db).startTransaction(false);
@@ -282,10 +280,10 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testSign() throws Exception { public void testSign() throws Exception {
final byte[] privateKey = getRandomBytes(42); byte[] privateKey = getRandomBytes(42);
final byte[] signed = getRandomBytes(42); byte[] signed = getRandomBytes(42);
final byte[] bytes = expectToByteArray(list); byte[] bytes = expectToByteArray(list);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(cryptoComponent).sign(label, bytes, privateKey); oneOf(cryptoComponent).sign(label, bytes, privateKey);
will(returnValue(signed)); will(returnValue(signed));
@@ -297,8 +295,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testVerifySignature() throws Exception { public void testVerifySignature() throws Exception {
final byte[] publicKey = getRandomBytes(42); byte[] publicKey = getRandomBytes(42);
final byte[] bytes = expectToByteArray(list); byte[] bytes = expectToByteArray(list);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage); oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage);
@@ -311,8 +309,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
@Test @Test
public void testVerifyWrongSignature() throws Exception { public void testVerifyWrongSignature() throws Exception {
final byte[] publicKey = getRandomBytes(42); byte[] publicKey = getRandomBytes(42);
final byte[] bytes = expectToByteArray(list); byte[] bytes = expectToByteArray(list);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage); oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage);
@@ -329,8 +327,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
} }
} }
private byte[] expectToByteArray(final BdfList list) throws Exception { private byte[] expectToByteArray(BdfList list) throws Exception {
final BdfWriter bdfWriter = context.mock(BdfWriter.class); BdfWriter bdfWriter = context.mock(BdfWriter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(bdfWriterFactory) oneOf(bdfWriterFactory)
@@ -341,8 +339,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
return new byte[0]; return new byte[0];
} }
private void expectToList(final boolean eof) throws Exception { private void expectToList(boolean eof) throws Exception {
final BdfReader bdfReader = context.mock(BdfReader.class); BdfReader bdfReader = context.mock(BdfReader.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(bdfReaderFactory) oneOf(bdfReaderFactory)

View File

@@ -46,10 +46,10 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testAddContact() throws Exception { public void testAddContact() throws Exception {
final SecretKey master = getSecretKey(); SecretKey master = getSecretKey();
final long timestamp = 42; long timestamp = 42;
final boolean alice = true; boolean alice = true;
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(false); oneOf(db).startTransaction(false);
@@ -64,14 +64,13 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
oneOf(db).endTransaction(txn); oneOf(db).endTransaction(txn);
}}); }});
assertEquals(contactId, contactManager assertEquals(contactId, contactManager.addContact(remote, local,
.addContact(remote, local, master, timestamp, alice, verified, master, timestamp, alice, verified, active));
active));
} }
@Test @Test
public void testGetContact() throws Exception { public void testGetContact() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));
@@ -86,8 +85,8 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testGetContactByAuthor() throws Exception { public void testGetContactByAuthor() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Collection<Contact> contacts = Collections.singleton(contact); Collection<Contact> contacts = Collections.singleton(contact);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));
@@ -102,7 +101,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test(expected = NoSuchContactException.class) @Test(expected = NoSuchContactException.class)
public void testGetContactByUnknownAuthor() throws Exception { public void testGetContactByUnknownAuthor() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));
@@ -116,8 +115,8 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test(expected = NoSuchContactException.class) @Test(expected = NoSuchContactException.class)
public void testGetContactByUnknownLocalAuthor() throws Exception { public void testGetContactByUnknownLocalAuthor() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Collection<Contact> contacts = Collections.singleton(contact); Collection<Contact> contacts = Collections.singleton(contact);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));
@@ -132,10 +131,9 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testActiveContacts() throws Exception { public void testActiveContacts() throws Exception {
Collection<Contact> activeContacts = Collections.singletonList(contact); Collection<Contact> activeContacts = Collections.singletonList(contact);
final Collection<Contact> contacts = Collection<Contact> contacts = new ArrayList<>(activeContacts);
new ArrayList<Contact>(activeContacts);
contacts.add(new Contact(new ContactId(3), remote, local, true, false)); contacts.add(new Contact(new ContactId(3), remote, local, true, false));
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));
@@ -150,7 +148,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testRemoveContact() throws Exception { public void testRemoveContact() throws Exception {
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(false); oneOf(db).startTransaction(false);
will(returnValue(txn)); will(returnValue(txn));
@@ -166,7 +164,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testSetContactActive() throws Exception { public void testSetContactActive() throws Exception {
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).setContactActive(txn, contactId, active); oneOf(db).setContactActive(txn, contactId, active);
}}); }});
@@ -176,7 +174,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testContactExists() throws Exception { public void testContactExists() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));

View File

@@ -69,7 +69,7 @@ public class EllipticCurvePerformanceTest {
ECPublicKeyParameters public2 = ECPublicKeyParameters public2 =
(ECPublicKeyParameters) keyPair2.getPublic(); (ECPublicKeyParameters) keyPair2.getPublic();
// Time some ECDH key agreements // Time some ECDH key agreements
List<Long> samples = new ArrayList<Long>(); List<Long> samples = new ArrayList<>();
for (int i = 0; i < SAMPLES; i++) { for (int i = 0; i < SAMPLES; i++) {
ECDHCBasicAgreement agreement = new ECDHCBasicAgreement(); ECDHCBasicAgreement agreement = new ECDHCBasicAgreement();
long start = System.nanoTime(); long start = System.nanoTime();
@@ -79,7 +79,7 @@ public class EllipticCurvePerformanceTest {
} }
long agreementMedian = median(samples); long agreementMedian = median(samples);
// Time some signatures // Time some signatures
List<byte[]> signatures = new ArrayList<byte[]>(); List<byte[]> signatures = new ArrayList<>();
samples.clear(); samples.clear();
for (int i = 0; i < SAMPLES; i++) { for (int i = 0; i < SAMPLES; i++) {
Digest digest = new Blake2sDigest(); Digest digest = new Blake2sDigest();

View File

@@ -145,7 +145,7 @@ public class KeyDerivationTest extends BrambleTestCase {
} }
private void assertAllDifferent(TransportKeys... transportKeys) { private void assertAllDifferent(TransportKeys... transportKeys) {
List<SecretKey> secretKeys = new ArrayList<SecretKey>(); List<SecretKey> secretKeys = new ArrayList<>();
for (TransportKeys k : transportKeys) { for (TransportKeys k : transportKeys) {
secretKeys.add(k.getPreviousIncomingKeys().getTagKey()); secretKeys.add(k.getPreviousIncomingKeys().getTagKey());
secretKeys.add(k.getPreviousIncomingKeys().getHeaderKey()); secretKeys.add(k.getPreviousIncomingKeys().getHeaderKey());
@@ -160,7 +160,7 @@ public class KeyDerivationTest extends BrambleTestCase {
} }
private void assertAllDifferent(List<SecretKey> keys) { private void assertAllDifferent(List<SecretKey> keys) {
Set<Bytes> set = new HashSet<Bytes>(); Set<Bytes> set = new HashSet<>();
for (SecretKey k : keys) assertTrue(set.add(new Bytes(k.getBytes()))); for (SecretKey k : keys) assertTrue(set.add(new Bytes(k.getBytes())));
} }
} }

View File

@@ -28,7 +28,7 @@ public class TagEncodingTest extends BrambleTestCase {
@Test @Test
public void testKeyAffectsTag() throws Exception { public void testKeyAffectsTag() throws Exception {
Set<Bytes> set = new HashSet<Bytes>(); Set<Bytes> set = new HashSet<>();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
byte[] tag = new byte[TAG_LENGTH]; byte[] tag = new byte[TAG_LENGTH];
SecretKey tagKey = TestUtils.getSecretKey(); SecretKey tagKey = TestUtils.getSecretKey();
@@ -39,7 +39,7 @@ public class TagEncodingTest extends BrambleTestCase {
@Test @Test
public void testProtocolVersionAffectsTag() throws Exception { public void testProtocolVersionAffectsTag() throws Exception {
Set<Bytes> set = new HashSet<Bytes>(); Set<Bytes> set = new HashSet<>();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
byte[] tag = new byte[TAG_LENGTH]; byte[] tag = new byte[TAG_LENGTH];
crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION + i, streamNumber); crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION + i, streamNumber);
@@ -49,7 +49,7 @@ public class TagEncodingTest extends BrambleTestCase {
@Test @Test
public void testStreamNumberAffectsTag() throws Exception { public void testStreamNumberAffectsTag() throws Exception {
Set<Bytes> set = new HashSet<Bytes>(); Set<Bytes> set = new HashSet<>();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
byte[] tag = new byte[TAG_LENGTH]; byte[] tag = new byte[TAG_LENGTH];
crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION, streamNumber + i); crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION, streamNumber + i);

View File

@@ -1,7 +1,6 @@
package org.briarproject.bramble.data; package org.briarproject.bramble.data;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -155,7 +154,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
@Test @Test
public void testWriteList() throws IOException { public void testWriteList() throws IOException {
List<Object> l = new ArrayList<Object>(); List<Object> l = new ArrayList<>();
for (int i = 0; i < 3; i++) l.add(i); for (int i = 0; i < 3; i++) l.add(i);
w.writeList(l); w.writeList(l);
// LIST tag, elements as integers, END tag // LIST tag, elements as integers, END tag
@@ -164,7 +163,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
@Test @Test
public void testListCanContainNull() throws IOException { public void testListCanContainNull() throws IOException {
List<Object> l = new ArrayList<Object>(); List<Object> l = new ArrayList<>();
l.add(1); l.add(1);
l.add(null); l.add(null);
l.add(NULL_VALUE); l.add(NULL_VALUE);
@@ -177,7 +176,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
@Test @Test
public void testWriteDictionary() throws IOException { public void testWriteDictionary() throws IOException {
// Use LinkedHashMap to get predictable iteration order // Use LinkedHashMap to get predictable iteration order
Map<String, Object> m = new LinkedHashMap<String, Object>(); Map<String, Object> m = new LinkedHashMap<>();
for (int i = 0; i < 4; i++) m.put(String.valueOf(i), i); for (int i = 0; i < 4; i++) m.put(String.valueOf(i), i);
w.writeDictionary(m); w.writeDictionary(m);
// DICTIONARY tag, keys as strings and values as integers, END tag // DICTIONARY tag, keys as strings and values as integers, END tag
@@ -216,12 +215,12 @@ public class BdfWriterImplTest extends BrambleTestCase {
@Test @Test
public void testWriteNestedDictionariesAndLists() throws IOException { public void testWriteNestedDictionariesAndLists() throws IOException {
Map<String, Object> inner = new LinkedHashMap<String, Object>(); Map<String, Object> inner = new LinkedHashMap<>();
inner.put("bar", new byte[0]); inner.put("bar", new byte[0]);
List<Object> list = new ArrayList<Object>(); List<Object> list = new ArrayList<>();
list.add(1); list.add(1);
list.add(inner); list.add(inner);
Map<String, Object> outer = new LinkedHashMap<String, Object>(); Map<String, Object> outer = new LinkedHashMap<>();
outer.put("foo", list); outer.put("foo", list);
w.writeDictionary(outer); w.writeDictionary(outer);
// DICTIONARY tag, "foo" as string, LIST tag, 1 as integer, // DICTIONARY tag, "foo" as string, LIST tag, 1 as integer,

View File

@@ -99,7 +99,7 @@ public class MetadataEncoderParserIntegrationTest extends BrambleTestCase {
@Test @Test
public void testList() throws FormatException { public void testList() throws FormatException {
List<Long> l = new ArrayList<Long>(4); List<Long> l = new ArrayList<>(4);
l.add(42L); l.add(42L);
l.add(1337L); l.add(1337L);
l.add(Long.MIN_VALUE); l.add(Long.MIN_VALUE);
@@ -114,7 +114,7 @@ public class MetadataEncoderParserIntegrationTest extends BrambleTestCase {
@Test @Test
public void testDictionary() throws FormatException { public void testDictionary() throws FormatException {
Map<String, Boolean> m = new HashMap<String, Boolean>(); Map<String, Boolean> m = new HashMap<>();
m.put("1", true); m.put("1", true);
m.put("2", false); m.put("2", false);
@@ -130,19 +130,19 @@ public class MetadataEncoderParserIntegrationTest extends BrambleTestCase {
@Test @Test
public void testComplexDictionary() throws FormatException { public void testComplexDictionary() throws FormatException {
Map<String, List> m = new HashMap<String, List>(); Map<String, List> m = new HashMap<>();
List<String> one = new ArrayList<String>(3); List<String> one = new ArrayList<>(3);
one.add("\uFDD0"); one.add("\uFDD0");
one.add("\uFDD1"); one.add("\uFDD1");
one.add("\uFDD2"); one.add("\uFDD2");
m.put("One", one); m.put("One", one);
List<String> two = new ArrayList<String>(2); List<String> two = new ArrayList<>(2);
two.add("\u0080"); two.add("\u0080");
two.add("\uD800\uDC00"); two.add("\uD800\uDC00");
m.put("Two", two); m.put("Two", two);
d.put("test", m); d.put("test", m);
Map<String, Boolean> m2 = new HashMap<String, Boolean>(); Map<String, Boolean> m2 = new HashMap<>();
m2.put("should be true", true); m2.put("should be true", true);
d.put("another test", m2); d.put("another test", m2);

View File

@@ -323,7 +323,7 @@ public class BasicH2Test extends BrambleTestCase {
private List<String> getNames() throws SQLException { private List<String> getNames() throws SQLException {
String sql = "SELECT name FROM foo ORDER BY uniqueId"; String sql = "SELECT name FROM foo ORDER BY uniqueId";
List<String> names = new ArrayList<String>(); List<String> names = new ArrayList<>();
try { try {
PreparedStatement ps = connection.prepareStatement(sql); PreparedStatement ps = connection.prepareStatement(sql);
ResultSet rs = ps.executeQuery(); ResultSet rs = ps.executeQuery();

View File

@@ -120,18 +120,18 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
private DatabaseComponent createDatabaseComponent(Database<Object> database, private DatabaseComponent createDatabaseComponent(Database<Object> database,
EventBus eventBus, ShutdownManager shutdown) { EventBus eventBus, ShutdownManager shutdown) {
return new DatabaseComponentImpl<Object>(database, Object.class, return new DatabaseComponentImpl<>(database, Object.class, eventBus,
eventBus, shutdown); shutdown);
} }
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testSimpleCalls() throws Exception { public void testSimpleCalls() throws Exception {
final int shutdownHandle = 12345; int shutdownHandle = 12345;
Mockery context = new Mockery(); Mockery context = new Mockery();
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// open() // open()
oneOf(database).open(); oneOf(database).open();
@@ -230,9 +230,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -260,9 +260,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
public void testAddLocalMessage() throws Exception { public void testAddLocalMessage() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -303,9 +303,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check whether the contact is in the DB (which it's not) // Check whether the contact is in the DB (which it's not)
exactly(18).of(database).startTransaction(); exactly(18).of(database).startTransaction();
@@ -509,9 +509,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check whether the pseudonym is in the DB (which it's not) // Check whether the pseudonym is in the DB (which it's not)
exactly(3).of(database).startTransaction(); exactly(3).of(database).startTransaction();
@@ -561,9 +561,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check whether the group is in the DB (which it's not) // Check whether the group is in the DB (which it's not)
exactly(8).of(database).startTransaction(); exactly(8).of(database).startTransaction();
@@ -666,9 +666,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check whether the message is in the DB (which it's not) // Check whether the message is in the DB (which it's not)
exactly(11).of(database).startTransaction(); exactly(11).of(database).startTransaction();
@@ -801,9 +801,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// startTransaction() // startTransaction()
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -896,13 +896,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
@Test @Test
public void testGenerateAck() throws Exception { public void testGenerateAck() throws Exception {
final Collection<MessageId> messagesToAck = Arrays.asList(messageId, Collection<MessageId> messagesToAck = Arrays.asList(messageId,
messageId1); messageId1);
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -931,14 +931,14 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
@Test @Test
public void testGenerateBatch() throws Exception { public void testGenerateBatch() throws Exception {
final byte[] raw1 = new byte[size]; byte[] raw1 = new byte[size];
final Collection<MessageId> ids = Arrays.asList(messageId, messageId1); Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
final Collection<byte[]> messages = Arrays.asList(raw, raw1); Collection<byte[]> messages = Arrays.asList(raw, raw1);
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -975,13 +975,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
@Test @Test
public void testGenerateOffer() throws Exception { public void testGenerateOffer() throws Exception {
final MessageId messageId1 = new MessageId(TestUtils.getRandomId()); MessageId messageId1 = new MessageId(TestUtils.getRandomId());
final Collection<MessageId> ids = Arrays.asList(messageId, messageId1); Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1013,13 +1013,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
@Test @Test
public void testGenerateRequest() throws Exception { public void testGenerateRequest() throws Exception {
final MessageId messageId1 = new MessageId(TestUtils.getRandomId()); MessageId messageId1 = new MessageId(TestUtils.getRandomId());
final Collection<MessageId> ids = Arrays.asList(messageId, messageId1); Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1048,14 +1048,14 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
@Test @Test
public void testGenerateRequestedBatch() throws Exception { public void testGenerateRequestedBatch() throws Exception {
final byte[] raw1 = new byte[size]; byte[] raw1 = new byte[size];
final Collection<MessageId> ids = Arrays.asList(messageId, messageId1); Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
final Collection<byte[]> messages = Arrays.asList(raw, raw1); Collection<byte[]> messages = Arrays.asList(raw, raw1);
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1095,9 +1095,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
public void testReceiveAck() throws Exception { public void testReceiveAck() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1128,9 +1128,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
public void testReceiveMessage() throws Exception { public void testReceiveMessage() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1183,9 +1183,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
public void testReceiveDuplicateMessage() throws Exception { public void testReceiveDuplicateMessage() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1220,9 +1220,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
public void testReceiveMessageWithoutVisibleGroup() throws Exception { public void testReceiveMessageWithoutVisibleGroup() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1248,14 +1248,14 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
@Test @Test
public void testReceiveOffer() throws Exception { public void testReceiveOffer() throws Exception {
final MessageId messageId1 = new MessageId(TestUtils.getRandomId()); MessageId messageId1 = new MessageId(TestUtils.getRandomId());
final MessageId messageId2 = new MessageId(TestUtils.getRandomId()); MessageId messageId2 = new MessageId(TestUtils.getRandomId());
final MessageId messageId3 = new MessageId(TestUtils.getRandomId()); MessageId messageId3 = new MessageId(TestUtils.getRandomId());
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1304,9 +1304,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
public void testReceiveRequest() throws Exception { public void testReceiveRequest() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1338,9 +1338,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
public void testChangingVisibilityCallsListeners() throws Exception { public void testChangingVisibilityCallsListeners() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1379,9 +1379,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -1409,14 +1409,14 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
@Test @Test
public void testTransportKeys() throws Exception { public void testTransportKeys() throws Exception {
final TransportKeys transportKeys = createTransportKeys(); TransportKeys transportKeys = createTransportKeys();
final Map<ContactId, TransportKeys> keys = Collections.singletonMap( Map<ContactId, TransportKeys> keys = Collections.singletonMap(
contactId, transportKeys); contactId, transportKeys);
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// startTransaction() // startTransaction()
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -1472,19 +1472,19 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
@Test @Test
public void testMergeSettings() throws Exception { public void testMergeSettings() throws Exception {
final Settings before = new Settings(); Settings before = new Settings();
before.put("foo", "bar"); before.put("foo", "bar");
before.put("baz", "bam"); before.put("baz", "bam");
final Settings update = new Settings(); Settings update = new Settings();
update.put("baz", "qux"); update.put("baz", "qux");
final Settings merged = new Settings(); Settings merged = new Settings();
merged.put("foo", "bar"); merged.put("foo", "bar");
merged.put("baz", "qux"); merged.put("baz", "qux");
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// startTransaction() // startTransaction()
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -1547,9 +1547,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -1572,9 +1572,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
public void testCannotAddLocalIdentityAsContact() throws Exception { public void testCannotAddLocalIdentityAsContact() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -1607,9 +1607,9 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
public void testCannotAddDuplicateContact() throws Exception { public void testCannotAddDuplicateContact() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -1643,12 +1643,12 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testMessageDependencies() throws Exception { public void testMessageDependencies() throws Exception {
final int shutdownHandle = 12345; int shutdownHandle = 12345;
Mockery context = new Mockery(); Mockery context = new Mockery();
final Database<Object> database = context.mock(Database.class); Database<Object> database = context.mock(Database.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class); ShutdownManager shutdown = context.mock(ShutdownManager.class);
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
final MessageId messageId2 = new MessageId(TestUtils.getRandomId()); MessageId messageId2 = new MessageId(TestUtils.getRandomId());
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// open() // open()
oneOf(database).open(); oneOf(database).open();
@@ -1703,7 +1703,7 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
Transaction transaction = db.startTransaction(false); Transaction transaction = db.startTransaction(false);
try { try {
db.addLocalMessage(transaction, message, metadata, true); db.addLocalMessage(transaction, message, metadata, true);
Collection<MessageId> dependencies = new ArrayList<MessageId>(2); Collection<MessageId> dependencies = new ArrayList<>(2);
dependencies.add(messageId1); dependencies.add(messageId1);
dependencies.add(messageId2); dependencies.add(messageId2);
db.addMessageDependencies(transaction, message, dependencies); db.addMessageDependencies(transaction, message, dependencies);

View File

@@ -464,28 +464,25 @@ public class H2DatabaseTest extends BrambleTestCase {
@Test @Test
public void testCloseWaitsForCommit() throws Exception { public void testCloseWaitsForCommit() throws Exception {
final CountDownLatch closing = new CountDownLatch(1); CountDownLatch closing = new CountDownLatch(1);
final CountDownLatch closed = new CountDownLatch(1); CountDownLatch closed = new CountDownLatch(1);
final AtomicBoolean transactionFinished = new AtomicBoolean(false); AtomicBoolean transactionFinished = new AtomicBoolean(false);
final AtomicBoolean error = new AtomicBoolean(false); AtomicBoolean error = new AtomicBoolean(false);
final Database<Connection> db = open(false); Database<Connection> db = open(false);
// Start a transaction // Start a transaction
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// In another thread, close the database // In another thread, close the database
Thread close = new Thread() { Thread close = new Thread(() -> {
@Override try {
public void run() { closing.countDown();
try { db.close();
closing.countDown(); if (!transactionFinished.get()) error.set(true);
db.close(); closed.countDown();
if (!transactionFinished.get()) error.set(true); } catch (Exception e) {
closed.countDown(); error.set(true);
} catch (Exception e) {
error.set(true);
}
} }
}; });
close.start(); close.start();
closing.await(); closing.await();
// Do whatever the transaction needs to do // Do whatever the transaction needs to do
@@ -501,28 +498,25 @@ public class H2DatabaseTest extends BrambleTestCase {
@Test @Test
public void testCloseWaitsForAbort() throws Exception { public void testCloseWaitsForAbort() throws Exception {
final CountDownLatch closing = new CountDownLatch(1); CountDownLatch closing = new CountDownLatch(1);
final CountDownLatch closed = new CountDownLatch(1); CountDownLatch closed = new CountDownLatch(1);
final AtomicBoolean transactionFinished = new AtomicBoolean(false); AtomicBoolean transactionFinished = new AtomicBoolean(false);
final AtomicBoolean error = new AtomicBoolean(false); AtomicBoolean error = new AtomicBoolean(false);
final Database<Connection> db = open(false); Database<Connection> db = open(false);
// Start a transaction // Start a transaction
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
// In another thread, close the database // In another thread, close the database
Thread close = new Thread() { Thread close = new Thread(() -> {
@Override try {
public void run() { closing.countDown();
try { db.close();
closing.countDown(); if (!transactionFinished.get()) error.set(true);
db.close(); closed.countDown();
if (!transactionFinished.get()) error.set(true); } catch (Exception e) {
closed.countDown(); error.set(true);
} catch (Exception e) {
error.set(true);
}
} }
}; });
close.start(); close.start();
closing.await(); closing.await();
// Do whatever the transaction needs to do // Do whatever the transaction needs to do
@@ -870,7 +864,7 @@ public class H2DatabaseTest extends BrambleTestCase {
assertEquals(0, db.countOfferedMessages(txn, contactId)); assertEquals(0, db.countOfferedMessages(txn, contactId));
// Add some offered messages and count them // Add some offered messages and count them
List<MessageId> ids = new ArrayList<MessageId>(); List<MessageId> ids = new ArrayList<>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
MessageId m = new MessageId(TestUtils.getRandomId()); MessageId m = new MessageId(TestUtils.getRandomId());
db.addOfferedMessage(txn, contactId, m); db.addOfferedMessage(txn, contactId, m);

View File

@@ -17,56 +17,50 @@ public class LockFairnessTest extends BrambleTestCase {
@Test @Test
public void testReadersCanShareTheLock() throws Exception { public void testReadersCanShareTheLock() throws Exception {
// Use a fair lock // Use a fair lock
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
final CountDownLatch firstReaderHasLock = new CountDownLatch(1); CountDownLatch firstReaderHasLock = new CountDownLatch(1);
final CountDownLatch firstReaderHasFinished = new CountDownLatch(1); CountDownLatch firstReaderHasFinished = new CountDownLatch(1);
final CountDownLatch secondReaderHasLock = new CountDownLatch(1); CountDownLatch secondReaderHasLock = new CountDownLatch(1);
final CountDownLatch secondReaderHasFinished = new CountDownLatch(1); CountDownLatch secondReaderHasFinished = new CountDownLatch(1);
// First reader // First reader
Thread first = new Thread() { Thread first = new Thread(() -> {
@Override try {
public void run() { // Acquire the lock
lock.readLock().lock();
try { try {
// Acquire the lock // Allow the second reader to acquire the lock
lock.readLock().lock(); firstReaderHasLock.countDown();
try { // Wait for the second reader to acquire the lock
// Allow the second reader to acquire the lock assertTrue(secondReaderHasLock.await(10, SECONDS));
firstReaderHasLock.countDown(); } finally {
// Wait for the second reader to acquire the lock // Release the lock
assertTrue(secondReaderHasLock.await(10, SECONDS)); lock.readLock().unlock();
} finally {
// Release the lock
lock.readLock().unlock();
}
} catch (InterruptedException e) {
fail();
} }
firstReaderHasFinished.countDown(); } catch (InterruptedException e) {
fail();
} }
}; firstReaderHasFinished.countDown();
});
first.start(); first.start();
// Second reader // Second reader
Thread second = new Thread() { Thread second = new Thread(() -> {
@Override try {
public void run() { // Wait for the first reader to acquire the lock
assertTrue(firstReaderHasLock.await(10, SECONDS));
// Acquire the lock
lock.readLock().lock();
try { try {
// Wait for the first reader to acquire the lock // Allow the first reader to release the lock
assertTrue(firstReaderHasLock.await(10, SECONDS)); secondReaderHasLock.countDown();
// Acquire the lock } finally {
lock.readLock().lock(); // Release the lock
try { lock.readLock().unlock();
// Allow the first reader to release the lock
secondReaderHasLock.countDown();
} finally {
// Release the lock
lock.readLock().unlock();
}
} catch (InterruptedException e) {
fail();
} }
secondReaderHasFinished.countDown(); } catch (InterruptedException e) {
fail();
} }
}; secondReaderHasFinished.countDown();
});
second.start(); second.start();
// Wait for both readers to finish // Wait for both readers to finish
assertTrue(firstReaderHasFinished.await(10, SECONDS)); assertTrue(firstReaderHasFinished.await(10, SECONDS));
@@ -76,86 +70,77 @@ public class LockFairnessTest extends BrambleTestCase {
@Test @Test
public void testWritersDoNotStarve() throws Exception { public void testWritersDoNotStarve() throws Exception {
// Use a fair lock // Use a fair lock
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
final CountDownLatch firstReaderHasLock = new CountDownLatch(1); CountDownLatch firstReaderHasLock = new CountDownLatch(1);
final CountDownLatch firstReaderHasFinished = new CountDownLatch(1); CountDownLatch firstReaderHasFinished = new CountDownLatch(1);
final CountDownLatch secondReaderHasFinished = new CountDownLatch(1); CountDownLatch secondReaderHasFinished = new CountDownLatch(1);
final CountDownLatch writerHasFinished = new CountDownLatch(1); CountDownLatch writerHasFinished = new CountDownLatch(1);
final AtomicBoolean secondReaderHasHeldLock = new AtomicBoolean(false); AtomicBoolean secondReaderHasHeldLock = new AtomicBoolean(false);
final AtomicBoolean writerHasHeldLock = new AtomicBoolean(false); AtomicBoolean writerHasHeldLock = new AtomicBoolean(false);
// First reader // First reader
Thread first = new Thread() { Thread first = new Thread(() -> {
@Override try {
public void run() { // Acquire the lock
lock.readLock().lock();
try { try {
// Acquire the lock // Allow the other threads to acquire the lock
lock.readLock().lock(); firstReaderHasLock.countDown();
try { // Wait for both other threads to wait for the lock
// Allow the other threads to acquire the lock while (lock.getQueueLength() < 2) Thread.sleep(10);
firstReaderHasLock.countDown(); // No other thread should have acquired the lock
// Wait for both other threads to wait for the lock assertFalse(secondReaderHasHeldLock.get());
while (lock.getQueueLength() < 2) Thread.sleep(10); assertFalse(writerHasHeldLock.get());
// No other thread should have acquired the lock } finally {
assertFalse(secondReaderHasHeldLock.get()); // Release the lock
assertFalse(writerHasHeldLock.get()); lock.readLock().unlock();
} finally {
// Release the lock
lock.readLock().unlock();
}
} catch (InterruptedException e) {
fail();
} }
firstReaderHasFinished.countDown(); } catch (InterruptedException e) {
fail();
} }
}; firstReaderHasFinished.countDown();
});
first.start(); first.start();
// Writer // Writer
Thread writer = new Thread() { Thread writer = new Thread(() -> {
@Override try {
public void run() { // Wait for the first reader to acquire the lock
assertTrue(firstReaderHasLock.await(10, SECONDS));
// Acquire the lock
lock.writeLock().lock();
try { try {
// Wait for the first reader to acquire the lock writerHasHeldLock.set(true);
assertTrue(firstReaderHasLock.await(10, SECONDS)); // The second reader should not overtake the writer
// Acquire the lock assertFalse(secondReaderHasHeldLock.get());
lock.writeLock().lock(); } finally {
try { lock.writeLock().unlock();
writerHasHeldLock.set(true);
// The second reader should not overtake the writer
assertFalse(secondReaderHasHeldLock.get());
} finally {
lock.writeLock().unlock();
}
} catch (InterruptedException e) {
fail();
} }
writerHasFinished.countDown(); } catch (InterruptedException e) {
fail();
} }
}; writerHasFinished.countDown();
});
writer.start(); writer.start();
// Second reader // Second reader
Thread second = new Thread() { Thread second = new Thread(() -> {
@Override try {
public void run() { // Wait for the first reader to acquire the lock
assertTrue(firstReaderHasLock.await(10, SECONDS));
// Wait for the writer to wait for the lock
while (lock.getQueueLength() < 1) Thread.sleep(10);
// Acquire the lock
lock.readLock().lock();
try { try {
// Wait for the first reader to acquire the lock secondReaderHasHeldLock.set(true);
assertTrue(firstReaderHasLock.await(10, SECONDS)); // The second reader should not overtake the writer
// Wait for the writer to wait for the lock assertTrue(writerHasHeldLock.get());
while (lock.getQueueLength() < 1) Thread.sleep(10); } finally {
// Acquire the lock lock.readLock().unlock();
lock.readLock().lock();
try {
secondReaderHasHeldLock.set(true);
// The second reader should not overtake the writer
assertTrue(writerHasHeldLock.get());
} finally {
lock.readLock().unlock();
}
} catch (InterruptedException e) {
fail();
} }
secondReaderHasFinished.countDown(); } catch (InterruptedException e) {
fail();
} }
}; secondReaderHasFinished.countDown();
});
second.start(); second.start();
// Wait for all the threads to finish // Wait for all the threads to finish
assertTrue(firstReaderHasFinished.await(10, SECONDS)); assertTrue(firstReaderHasFinished.await(10, SECONDS));

View File

@@ -80,8 +80,8 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testGetAuthorStatus() throws DbException { public void testGetAuthorStatus() throws DbException {
final AuthorId authorId = new AuthorId(TestUtils.getRandomId()); AuthorId authorId = new AuthorId(TestUtils.getRandomId());
final Collection<Contact> contacts = new ArrayList<Contact>(); Collection<Contact> contacts = new ArrayList<>();
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
@@ -125,8 +125,8 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
identityManager.getAuthorStatus(localAuthor.getId())); identityManager.getAuthorStatus(localAuthor.getId()));
} }
private void checkAuthorStatusContext(final AuthorId authorId, private void checkAuthorStatusContext(AuthorId authorId,
final Collection<Contact> contacts) throws DbException { Collection<Contact> contacts) throws DbException {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).startTransaction(true); oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));

View File

@@ -65,11 +65,11 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Test @Test
public void testAliceProtocol() throws Exception { public void testAliceProtocol() throws Exception {
// set up // set up
final Payload theirPayload = new Payload(BOB_COMMIT, null); Payload theirPayload = new Payload(BOB_COMMIT, null);
final Payload ourPayload = new Payload(ALICE_COMMIT, null); Payload ourPayload = new Payload(ALICE_COMMIT, null);
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
final SecretKey sharedSecret = TestUtils.getSecretKey(); SecretKey sharedSecret = TestUtils.getSecretKey();
final SecretKey masterSecret = TestUtils.getSecretKey(); SecretKey masterSecret = TestUtils.getSecretKey();
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
@@ -129,11 +129,11 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Test @Test
public void testBobProtocol() throws Exception { public void testBobProtocol() throws Exception {
// set up // set up
final Payload theirPayload = new Payload(ALICE_COMMIT, null); Payload theirPayload = new Payload(ALICE_COMMIT, null);
final Payload ourPayload = new Payload(BOB_COMMIT, null); Payload ourPayload = new Payload(BOB_COMMIT, null);
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
final SecretKey sharedSecret = TestUtils.getSecretKey(); SecretKey sharedSecret = TestUtils.getSecretKey();
final SecretKey masterSecret = TestUtils.getSecretKey(); SecretKey masterSecret = TestUtils.getSecretKey();
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
@@ -192,9 +192,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Test(expected = AbortException.class) @Test(expected = AbortException.class)
public void testAliceProtocolAbortOnBadKey() throws Exception { public void testAliceProtocolAbortOnBadKey() throws Exception {
// set up // set up
final Payload theirPayload = new Payload(BOB_COMMIT, null); Payload theirPayload = new Payload(BOB_COMMIT, null);
final Payload ourPayload = new Payload(ALICE_COMMIT, null); Payload ourPayload = new Payload(ALICE_COMMIT, null);
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
@@ -233,9 +233,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Test(expected = AbortException.class) @Test(expected = AbortException.class)
public void testBobProtocolAbortOnBadKey() throws Exception { public void testBobProtocolAbortOnBadKey() throws Exception {
// set up // set up
final Payload theirPayload = new Payload(ALICE_COMMIT, null); Payload theirPayload = new Payload(ALICE_COMMIT, null);
final Payload ourPayload = new Payload(BOB_COMMIT, null); Payload ourPayload = new Payload(BOB_COMMIT, null);
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
@@ -270,10 +270,10 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Test(expected = AbortException.class) @Test(expected = AbortException.class)
public void testAliceProtocolAbortOnBadConfirm() throws Exception { public void testAliceProtocolAbortOnBadConfirm() throws Exception {
// set up // set up
final Payload theirPayload = new Payload(BOB_COMMIT, null); Payload theirPayload = new Payload(BOB_COMMIT, null);
final Payload ourPayload = new Payload(ALICE_COMMIT, null); Payload ourPayload = new Payload(ALICE_COMMIT, null);
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
final SecretKey sharedSecret = TestUtils.getSecretKey(); SecretKey sharedSecret = TestUtils.getSecretKey();
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
@@ -335,10 +335,10 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Test(expected = AbortException.class) @Test(expected = AbortException.class)
public void testBobProtocolAbortOnBadConfirm() throws Exception { public void testBobProtocolAbortOnBadConfirm() throws Exception {
// set up // set up
final Payload theirPayload = new Payload(ALICE_COMMIT, null); Payload theirPayload = new Payload(ALICE_COMMIT, null);
final Payload ourPayload = new Payload(BOB_COMMIT, null); Payload ourPayload = new Payload(BOB_COMMIT, null);
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
final SecretKey sharedSecret = TestUtils.getSecretKey(); SecretKey sharedSecret = TestUtils.getSecretKey();
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,

View File

@@ -15,13 +15,9 @@ public class ShutdownManagerImplTest extends BrambleTestCase {
@Test @Test
public void testAddAndRemove() { public void testAddAndRemove() {
ShutdownManager s = createShutdownManager(); ShutdownManager s = createShutdownManager();
Set<Integer> handles = new HashSet<Integer>(); Set<Integer> handles = new HashSet<>();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
int handle = s.addShutdownHook(new Runnable() { int handle = s.addShutdownHook(() -> {});
@Override
public void run() {
}
});
// The handles should all be distinct // The handles should all be distinct
assertTrue(handles.add(handle)); assertTrue(handles.add(handle));
} }

View File

@@ -35,7 +35,7 @@ public class ConnectionRegistryImplTest extends BrambleTestCase {
@Test @Test
public void testRegisterAndUnregister() { public void testRegisterAndUnregister() {
Mockery context = new Mockery(); Mockery context = new Mockery();
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
exactly(5).of(eventBus).broadcast(with(any( exactly(5).of(eventBus).broadcast(with(any(
ConnectionOpenedEvent.class))); ConnectionOpenedEvent.class)));

View File

@@ -30,36 +30,36 @@ public class PluginManagerImplTest extends BrambleTestCase {
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor ioExecutor = Executors.newSingleThreadExecutor(); Executor ioExecutor = Executors.newSingleThreadExecutor();
final EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
final PluginConfig pluginConfig = context.mock(PluginConfig.class); PluginConfig pluginConfig = context.mock(PluginConfig.class);
final ConnectionManager connectionManager = ConnectionManager connectionManager =
context.mock(ConnectionManager.class); context.mock(ConnectionManager.class);
final SettingsManager settingsManager = SettingsManager settingsManager =
context.mock(SettingsManager.class); context.mock(SettingsManager.class);
final TransportPropertyManager transportPropertyManager = TransportPropertyManager transportPropertyManager =
context.mock(TransportPropertyManager.class); context.mock(TransportPropertyManager.class);
final UiCallback uiCallback = context.mock(UiCallback.class); UiCallback uiCallback = context.mock(UiCallback.class);
// Two simplex plugin factories: both create plugins, one fails to start // Two simplex plugin factories: both create plugins, one fails to start
final SimplexPluginFactory simplexFactory = SimplexPluginFactory simplexFactory =
context.mock(SimplexPluginFactory.class); context.mock(SimplexPluginFactory.class);
final SimplexPlugin simplexPlugin = context.mock(SimplexPlugin.class); SimplexPlugin simplexPlugin = context.mock(SimplexPlugin.class);
final TransportId simplexId = new TransportId("simplex"); TransportId simplexId = new TransportId("simplex");
final SimplexPluginFactory simplexFailFactory = SimplexPluginFactory simplexFailFactory =
context.mock(SimplexPluginFactory.class, "simplexFailFactory"); context.mock(SimplexPluginFactory.class, "simplexFailFactory");
final SimplexPlugin simplexFailPlugin = SimplexPlugin simplexFailPlugin =
context.mock(SimplexPlugin.class, "simplexFailPlugin"); context.mock(SimplexPlugin.class, "simplexFailPlugin");
final TransportId simplexFailId = new TransportId("simplex1"); TransportId simplexFailId = new TransportId("simplex1");
// Two duplex plugin factories: one creates a plugin, the other fails // Two duplex plugin factories: one creates a plugin, the other fails
final DuplexPluginFactory duplexFactory = DuplexPluginFactory duplexFactory =
context.mock(DuplexPluginFactory.class); context.mock(DuplexPluginFactory.class);
final DuplexPlugin duplexPlugin = context.mock(DuplexPlugin.class); DuplexPlugin duplexPlugin = context.mock(DuplexPlugin.class);
final TransportId duplexId = new TransportId("duplex"); TransportId duplexId = new TransportId("duplex");
final DuplexPluginFactory duplexFailFactory = DuplexPluginFactory duplexFailFactory =
context.mock(DuplexPluginFactory.class, "duplexFailFactory"); context.mock(DuplexPluginFactory.class, "duplexFailFactory");
final TransportId duplexFailId = new TransportId("duplex1"); TransportId duplexFailId = new TransportId("duplex1");
context.checking(new Expectations() {{ context.checking(new Expectations() {{
allowing(simplexPlugin).getId(); allowing(simplexPlugin).getId();

View File

@@ -42,35 +42,35 @@ public class PollerTest extends BrambleTestCase {
public void testConnectOnContactStatusChanged() throws Exception { public void testConnectOnContactStatusChanged() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
context.setImposteriser(ClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
final Executor ioExecutor = new ImmediateExecutor(); Executor ioExecutor = new ImmediateExecutor();
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final ConnectionManager connectionManager = ConnectionManager connectionManager =
context.mock(ConnectionManager.class); context.mock(ConnectionManager.class);
final ConnectionRegistry connectionRegistry = ConnectionRegistry connectionRegistry =
context.mock(ConnectionRegistry.class); context.mock(ConnectionRegistry.class);
final PluginManager pluginManager = context.mock(PluginManager.class); PluginManager pluginManager = context.mock(PluginManager.class);
final SecureRandom random = context.mock(SecureRandom.class); SecureRandom random = context.mock(SecureRandom.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
// Two simplex plugins: one supports polling, the other doesn't // Two simplex plugins: one supports polling, the other doesn't
final SimplexPlugin simplexPlugin = context.mock(SimplexPlugin.class); SimplexPlugin simplexPlugin = context.mock(SimplexPlugin.class);
final SimplexPlugin simplexPlugin1 = SimplexPlugin simplexPlugin1 =
context.mock(SimplexPlugin.class, "simplexPlugin1"); context.mock(SimplexPlugin.class, "simplexPlugin1");
final TransportId simplexId1 = new TransportId("simplex1"); TransportId simplexId1 = new TransportId("simplex1");
final List<SimplexPlugin> simplexPlugins = Arrays.asList(simplexPlugin, List<SimplexPlugin> simplexPlugins = Arrays.asList(simplexPlugin,
simplexPlugin1); simplexPlugin1);
final TransportConnectionWriter simplexWriter = TransportConnectionWriter simplexWriter =
context.mock(TransportConnectionWriter.class); context.mock(TransportConnectionWriter.class);
// Two duplex plugins: one supports polling, the other doesn't // Two duplex plugins: one supports polling, the other doesn't
final DuplexPlugin duplexPlugin = context.mock(DuplexPlugin.class); DuplexPlugin duplexPlugin = context.mock(DuplexPlugin.class);
final TransportId duplexId = new TransportId("duplex"); TransportId duplexId = new TransportId("duplex");
final DuplexPlugin duplexPlugin1 = DuplexPlugin duplexPlugin1 =
context.mock(DuplexPlugin.class, "duplexPlugin1"); context.mock(DuplexPlugin.class, "duplexPlugin1");
final List<DuplexPlugin> duplexPlugins = Arrays.asList(duplexPlugin, List<DuplexPlugin> duplexPlugins = Arrays.asList(duplexPlugin,
duplexPlugin1); duplexPlugin1);
final DuplexTransportConnection duplexConnection = DuplexTransportConnection duplexConnection =
context.mock(DuplexTransportConnection.class); context.mock(DuplexTransportConnection.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -129,20 +129,20 @@ public class PollerTest extends BrambleTestCase {
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
context.setImposteriser(ClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
final Executor ioExecutor = new ImmediateExecutor(); Executor ioExecutor = new ImmediateExecutor();
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final ConnectionManager connectionManager = ConnectionManager connectionManager =
context.mock(ConnectionManager.class); context.mock(ConnectionManager.class);
final ConnectionRegistry connectionRegistry = ConnectionRegistry connectionRegistry =
context.mock(ConnectionRegistry.class); context.mock(ConnectionRegistry.class);
final PluginManager pluginManager = context.mock(PluginManager.class); PluginManager pluginManager = context.mock(PluginManager.class);
final SecureRandom random = context.mock(SecureRandom.class); SecureRandom random = context.mock(SecureRandom.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final DuplexPlugin plugin = context.mock(DuplexPlugin.class); DuplexPlugin plugin = context.mock(DuplexPlugin.class);
final TransportId transportId = new TransportId("id"); TransportId transportId = new TransportId("id");
final DuplexTransportConnection duplexConnection = DuplexTransportConnection duplexConnection =
context.mock(DuplexTransportConnection.class); context.mock(DuplexTransportConnection.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -194,19 +194,19 @@ public class PollerTest extends BrambleTestCase {
public void testRescheduleOnConnectionOpened() throws Exception { public void testRescheduleOnConnectionOpened() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
context.setImposteriser(ClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
final Executor ioExecutor = new ImmediateExecutor(); Executor ioExecutor = new ImmediateExecutor();
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final ConnectionManager connectionManager = ConnectionManager connectionManager =
context.mock(ConnectionManager.class); context.mock(ConnectionManager.class);
final ConnectionRegistry connectionRegistry = ConnectionRegistry connectionRegistry =
context.mock(ConnectionRegistry.class); context.mock(ConnectionRegistry.class);
final PluginManager pluginManager = context.mock(PluginManager.class); PluginManager pluginManager = context.mock(PluginManager.class);
final SecureRandom random = context.mock(SecureRandom.class); SecureRandom random = context.mock(SecureRandom.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final DuplexPlugin plugin = context.mock(DuplexPlugin.class); DuplexPlugin plugin = context.mock(DuplexPlugin.class);
final TransportId transportId = new TransportId("id"); TransportId transportId = new TransportId("id");
context.checking(new Expectations() {{ context.checking(new Expectations() {{
allowing(plugin).getId(); allowing(plugin).getId();
@@ -239,19 +239,19 @@ public class PollerTest extends BrambleTestCase {
public void testRescheduleDoesNotReplaceEarlierTask() throws Exception { public void testRescheduleDoesNotReplaceEarlierTask() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
context.setImposteriser(ClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
final Executor ioExecutor = new ImmediateExecutor(); Executor ioExecutor = new ImmediateExecutor();
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final ConnectionManager connectionManager = ConnectionManager connectionManager =
context.mock(ConnectionManager.class); context.mock(ConnectionManager.class);
final ConnectionRegistry connectionRegistry = ConnectionRegistry connectionRegistry =
context.mock(ConnectionRegistry.class); context.mock(ConnectionRegistry.class);
final PluginManager pluginManager = context.mock(PluginManager.class); PluginManager pluginManager = context.mock(PluginManager.class);
final SecureRandom random = context.mock(SecureRandom.class); SecureRandom random = context.mock(SecureRandom.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final DuplexPlugin plugin = context.mock(DuplexPlugin.class); DuplexPlugin plugin = context.mock(DuplexPlugin.class);
final TransportId transportId = new TransportId("id"); TransportId transportId = new TransportId("id");
context.checking(new Expectations() {{ context.checking(new Expectations() {{
allowing(plugin).getId(); allowing(plugin).getId();
@@ -299,20 +299,20 @@ public class PollerTest extends BrambleTestCase {
public void testPollOnTransportEnabled() throws Exception { public void testPollOnTransportEnabled() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
context.setImposteriser(ClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
final Executor ioExecutor = new ImmediateExecutor(); Executor ioExecutor = new ImmediateExecutor();
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final ConnectionManager connectionManager = ConnectionManager connectionManager =
context.mock(ConnectionManager.class); context.mock(ConnectionManager.class);
final ConnectionRegistry connectionRegistry = ConnectionRegistry connectionRegistry =
context.mock(ConnectionRegistry.class); context.mock(ConnectionRegistry.class);
final PluginManager pluginManager = context.mock(PluginManager.class); PluginManager pluginManager = context.mock(PluginManager.class);
final SecureRandom random = context.mock(SecureRandom.class); SecureRandom random = context.mock(SecureRandom.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final Plugin plugin = context.mock(Plugin.class); Plugin plugin = context.mock(Plugin.class);
final TransportId transportId = new TransportId("id"); TransportId transportId = new TransportId("id");
final List<ContactId> connected = Collections.singletonList(contactId); List<ContactId> connected = Collections.singletonList(contactId);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
allowing(plugin).getId(); allowing(plugin).getId();

View File

@@ -145,11 +145,11 @@ public class LanTcpPluginTest extends BrambleTestCase {
assertEquals(2, split.length); assertEquals(2, split.length);
String addrString = split[0]; String addrString = split[0];
// Listen on the same interface as the plugin // Listen on the same interface as the plugin
final ServerSocket ss = new ServerSocket(); ServerSocket ss = new ServerSocket();
ss.bind(new InetSocketAddress(addrString, 0), 10); ss.bind(new InetSocketAddress(addrString, 0), 10);
int port = ss.getLocalPort(); int port = ss.getLocalPort();
final CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean error = new AtomicBoolean(false); AtomicBoolean error = new AtomicBoolean(false);
new Thread() { new Thread() {
@Override @Override
public void run() { public void run() {
@@ -194,8 +194,7 @@ public class LanTcpPluginTest extends BrambleTestCase {
plugin.createKeyAgreementListener(new byte[COMMIT_LENGTH]); plugin.createKeyAgreementListener(new byte[COMMIT_LENGTH]);
assertNotNull(kal); assertNotNull(kal);
Callable<KeyAgreementConnection> c = kal.listen(); Callable<KeyAgreementConnection> c = kal.listen();
FutureTask<KeyAgreementConnection> f = FutureTask<KeyAgreementConnection> f = new FutureTask<>(c);
new FutureTask<KeyAgreementConnection>(c);
new Thread(f).start(); new Thread(f).start();
// The plugin should have bound a socket and stored the port number // The plugin should have bound a socket and stored the port number
BdfList descriptor = kal.getDescriptor(); BdfList descriptor = kal.getDescriptor();
@@ -240,10 +239,10 @@ public class LanTcpPluginTest extends BrambleTestCase {
assertEquals(2, split.length); assertEquals(2, split.length);
String addrString = split[0]; String addrString = split[0];
// Listen on the same interface as the plugin // Listen on the same interface as the plugin
final ServerSocket ss = new ServerSocket(); ServerSocket ss = new ServerSocket();
ss.bind(new InetSocketAddress(addrString, 0), 10); ss.bind(new InetSocketAddress(addrString, 0), 10);
final CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean error = new AtomicBoolean(false); AtomicBoolean error = new AtomicBoolean(false);
new Thread() { new Thread() {
@Override @Override
public void run() { public void run() {
@@ -291,7 +290,7 @@ public class LanTcpPluginTest extends BrambleTestCase {
private static class Callback implements DuplexPluginCallback { private static class Callback implements DuplexPluginCallback {
private final Map<ContactId, TransportProperties> remote = private final Map<ContactId, TransportProperties> remote =
new Hashtable<ContactId, TransportProperties>(); new Hashtable<>();
private final CountDownLatch propertiesLatch = new CountDownLatch(1); private final CountDownLatch propertiesLatch = new CountDownLatch(1);
private final CountDownLatch connectionsLatch = new CountDownLatch(1); private final CountDownLatch connectionsLatch = new CountDownLatch(1);
private final TransportProperties local = new TransportProperties(); private final TransportProperties local = new TransportProperties();

View File

@@ -0,0 +1,707 @@
package org.briarproject.bramble.properties;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.client.ContactGroupFactory;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataParser;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.properties.TransportPropertyManager.CLIENT_ID;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
private final MetadataParser metadataParser =
context.mock(MetadataParser.class);
private final ContactGroupFactory contactGroupFactory =
context.mock(ContactGroupFactory.class);
private final Clock clock = context.mock(Clock.class);
private final Group localGroup = getGroup();
private final LocalAuthor localAuthor = getLocalAuthor();
private final BdfDictionary fooPropertiesDict = BdfDictionary.of(
new BdfEntry("fooKey1", "fooValue1"),
new BdfEntry("fooKey2", "fooValue2")
);
private final BdfDictionary barPropertiesDict = BdfDictionary.of(
new BdfEntry("barKey1", "barValue1"),
new BdfEntry("barKey2", "barValue2")
);
private final TransportProperties fooProperties, barProperties;
private int nextContactId = 0;
public TransportPropertyManagerImplTest() throws Exception {
fooProperties = new TransportProperties();
for (String key : fooPropertiesDict.keySet())
fooProperties.put(key, fooPropertiesDict.getString(key));
barProperties = new TransportProperties();
for (String key : barPropertiesDict.keySet())
barProperties.put(key, barPropertiesDict.getString(key));
}
private TransportPropertyManagerImpl createInstance() {
context.checking(new Expectations() {{
oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID);
will(returnValue(localGroup));
}});
return new TransportPropertyManagerImpl(db, clientHelper,
metadataParser, contactGroupFactory, clock);
}
@Test
public void testCreatesGroupsAtStartup() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact1 = getContact(true);
Contact contact2 = getContact(true);
List<Contact> contacts = Arrays.asList(contact1, contact2);
Group contactGroup1 = getGroup(), contactGroup2 = getGroup();
context.checking(new Expectations() {{
oneOf(db).addGroup(txn, localGroup);
oneOf(db).getContacts(txn);
will(returnValue(contacts));
// The first contact's group has already been set up
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact1);
will(returnValue(contactGroup1));
oneOf(db).containsGroup(txn, contactGroup1.getId());
will(returnValue(true));
// The second contact's group hasn't been set up
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact2);
will(returnValue(contactGroup2));
oneOf(db).containsGroup(txn, contactGroup2.getId());
will(returnValue(false));
oneOf(db).addGroup(txn, contactGroup2);
oneOf(db).setGroupVisibility(txn, contact2.getId(),
contactGroup2.getId(), SHARED);
}});
// Copy the latest local properties into the group
expectGetLocalProperties(txn);
expectStoreMessage(txn, contactGroup2.getId(), "foo", fooPropertiesDict,
1, true, true);
expectStoreMessage(txn, contactGroup2.getId(), "bar", barPropertiesDict,
1, true, true);
TransportPropertyManagerImpl t = createInstance();
t.createLocalState(txn);
}
@Test
public void testCreatesGroupWhenAddingContact() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact(true);
Group contactGroup = getGroup();
context.checking(new Expectations() {{
// Create the group and share it with the contact
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
will(returnValue(contactGroup));
oneOf(db).containsGroup(txn, contactGroup.getId());
will(returnValue(false));
oneOf(db).addGroup(txn, contactGroup);
oneOf(db).setGroupVisibility(txn, contact.getId(),
contactGroup.getId(), SHARED);
}});
// Copy the latest local properties into the group
expectGetLocalProperties(txn);
expectStoreMessage(txn, contactGroup.getId(), "foo", fooPropertiesDict,
1, true, true);
expectStoreMessage(txn, contactGroup.getId(), "bar", barPropertiesDict,
1, true, true);
TransportPropertyManagerImpl t = createInstance();
t.addingContact(txn, contact);
}
@Test
public void testRemovesGroupWhenRemovingContact() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact(true);
Group contactGroup = getGroup();
context.checking(new Expectations() {{
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
will(returnValue(contactGroup));
oneOf(db).removeGroup(txn, contactGroup);
}});
TransportPropertyManagerImpl t = createInstance();
t.removingContact(txn, contact);
}
@Test
public void testDoesNotDeleteAnythingWhenFirstUpdateIsDelivered()
throws Exception {
Transaction txn = new Transaction(null, false);
GroupId contactGroupId = new GroupId(getRandomId());
long timestamp = 123456789;
Message message = getMessage(contactGroupId, timestamp);
Metadata meta = new Metadata();
BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 2),
new BdfEntry("local", false)
);
Map<MessageId, BdfDictionary> messageMetadata =
new LinkedHashMap<>();
// A remote update for another transport should be ignored
MessageId barUpdateId = new MessageId(getRandomId());
messageMetadata.put(barUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "bar"),
new BdfEntry("version", 1),
new BdfEntry("local", false)
));
// A local update for the same transport should be ignored
MessageId localUpdateId = new MessageId(getRandomId());
messageMetadata.put(localUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", true)
));
context.checking(new Expectations() {{
oneOf(metadataParser).parse(meta);
will(returnValue(metaDictionary));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
will(returnValue(messageMetadata));
}});
TransportPropertyManagerImpl t = createInstance();
assertFalse(t.incomingMessage(txn, message, meta));
}
@Test
public void testDeletesOlderUpdatesWhenUpdateIsDelivered()
throws Exception {
Transaction txn = new Transaction(null, false);
GroupId contactGroupId = new GroupId(getRandomId());
long timestamp = 123456789;
Message message = getMessage(contactGroupId, timestamp);
Metadata meta = new Metadata();
BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 4),
new BdfEntry("local", false)
);
Map<MessageId, BdfDictionary> messageMetadata =
new LinkedHashMap<>();
// Old remote updates for the same transport should be deleted
MessageId fooVersion2 = new MessageId(getRandomId());
messageMetadata.put(fooVersion2, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 2),
new BdfEntry("local", false)
));
MessageId fooVersion1 = new MessageId(getRandomId());
messageMetadata.put(fooVersion1, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", false)
));
MessageId fooVersion3 = new MessageId(getRandomId());
messageMetadata.put(fooVersion3, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 3),
new BdfEntry("local", false)
));
context.checking(new Expectations() {{
oneOf(metadataParser).parse(meta);
will(returnValue(metaDictionary));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
will(returnValue(messageMetadata));
// Versions 1-3 should be deleted
oneOf(db).deleteMessage(txn, fooVersion1);
oneOf(db).deleteMessageMetadata(txn, fooVersion1);
oneOf(db).deleteMessage(txn, fooVersion2);
oneOf(db).deleteMessageMetadata(txn, fooVersion2);
oneOf(db).deleteMessage(txn, fooVersion3);
oneOf(db).deleteMessageMetadata(txn, fooVersion3);
}});
TransportPropertyManagerImpl t = createInstance();
assertFalse(t.incomingMessage(txn, message, meta));
}
@Test
public void testDeletesObsoleteUpdateWhenDelivered() throws Exception {
Transaction txn = new Transaction(null, false);
GroupId contactGroupId = new GroupId(getRandomId());
long timestamp = 123456789;
Message message = getMessage(contactGroupId, timestamp);
Metadata meta = new Metadata();
BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 3),
new BdfEntry("local", false)
);
Map<MessageId, BdfDictionary> messageMetadata =
new LinkedHashMap<>();
// Old remote updates for the same transport should be deleted
MessageId fooVersion2 = new MessageId(getRandomId());
messageMetadata.put(fooVersion2, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 2),
new BdfEntry("local", false)
));
MessageId fooVersion1 = new MessageId(getRandomId());
messageMetadata.put(fooVersion1, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", false)
));
// A newer remote update for the same transport should not be deleted
MessageId fooVersion4 = new MessageId(getRandomId());
messageMetadata.put(fooVersion4, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 4),
new BdfEntry("local", false)
));
context.checking(new Expectations() {{
oneOf(metadataParser).parse(meta);
will(returnValue(metaDictionary));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
will(returnValue(messageMetadata));
// Versions 1 and 2 should be deleted, version 4 should not
oneOf(db).deleteMessage(txn, fooVersion1);
oneOf(db).deleteMessageMetadata(txn, fooVersion1);
oneOf(db).deleteMessage(txn, fooVersion2);
oneOf(db).deleteMessageMetadata(txn, fooVersion2);
// The update being delivered (version 3) should be deleted
oneOf(db).deleteMessage(txn, message.getId());
oneOf(db).deleteMessageMetadata(txn, message.getId());
}});
TransportPropertyManagerImpl t = createInstance();
assertFalse(t.incomingMessage(txn, message, meta));
}
@Test
public void testStoresRemotePropertiesWithVersion0() throws Exception {
Contact contact = getContact(true);
Group contactGroup = getGroup();
Transaction txn = new Transaction(null, false);
Map<TransportId, TransportProperties> properties =
new LinkedHashMap<>();
properties.put(new TransportId("foo"), fooProperties);
properties.put(new TransportId("bar"), barProperties);
context.checking(new Expectations() {{
oneOf(db).getContact(txn, contact.getId());
will(returnValue(contact));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
will(returnValue(contactGroup));
}});
expectStoreMessage(txn, contactGroup.getId(), "foo", fooPropertiesDict,
0, false, false);
expectStoreMessage(txn, contactGroup.getId(), "bar", barPropertiesDict,
0, false, false);
TransportPropertyManagerImpl t = createInstance();
t.addRemoteProperties(txn, contact.getId(), properties);
}
@Test
public void testReturnsLatestLocalProperties() throws Exception {
Transaction txn = new Transaction(null, false);
expectGetLocalProperties(txn);
TransportPropertyManagerImpl t = createInstance();
Map<TransportId, TransportProperties> local = t.getLocalProperties(txn);
assertEquals(2, local.size());
assertEquals(fooProperties, local.get(new TransportId("foo")));
assertEquals(barProperties, local.get(new TransportId("bar")));
}
@Test
public void testReturnsEmptyPropertiesIfNoLocalPropertiesAreFound()
throws Exception {
Transaction txn = new Transaction(null, false);
Map<MessageId, BdfDictionary> messageMetadata =
new LinkedHashMap<>();
// A local update for another transport should be ignored
MessageId barUpdateId = new MessageId(getRandomId());
messageMetadata.put(barUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "bar"),
new BdfEntry("version", 1),
new BdfEntry("local", true)
));
context.checking(new Expectations() {{
oneOf(db).startTransaction(false);
will(returnValue(txn));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(messageMetadata));
oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn);
}});
TransportPropertyManagerImpl t = createInstance();
assertEquals(0, t.getLocalProperties(new TransportId("foo")).size());
}
@Test
public void testReturnsLocalProperties() throws Exception {
Transaction txn = new Transaction(null, false);
Map<MessageId, BdfDictionary> messageMetadata =
new LinkedHashMap<>();
// A local update for another transport should be ignored
MessageId barUpdateId = new MessageId(getRandomId());
messageMetadata.put(barUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "bar"),
new BdfEntry("version", 1),
new BdfEntry("local", true)
));
// A local update for the right transport should be returned
MessageId fooUpdateId = new MessageId(getRandomId());
messageMetadata.put(fooUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", true)
));
BdfList fooUpdate = BdfList.of("foo", 1, fooPropertiesDict);
context.checking(new Expectations() {{
oneOf(db).startTransaction(false);
will(returnValue(txn));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId);
will(returnValue(fooUpdate));
oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn);
}});
TransportPropertyManagerImpl t = createInstance();
assertEquals(fooProperties,
t.getLocalProperties(new TransportId("foo")));
}
@Test
public void testReturnsRemotePropertiesOrEmptyProperties()
throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact1 = getContact(false);
Contact contact2 = getContact(true);
Contact contact3 = getContact(true);
List<Contact> contacts =
Arrays.asList(contact1, contact2, contact3);
Group contactGroup2 = getGroup();
Group contactGroup3 = getGroup();
Map<MessageId, BdfDictionary> messageMetadata3 =
new LinkedHashMap<>();
// A remote update for another transport should be ignored
MessageId barUpdateId = new MessageId(getRandomId());
messageMetadata3.put(barUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "bar"),
new BdfEntry("version", 1),
new BdfEntry("local", false)
));
// A local update for the right transport should be ignored
MessageId localUpdateId = new MessageId(getRandomId());
messageMetadata3.put(localUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", true)
));
// A remote update for the right transport should be returned
MessageId fooUpdateId = new MessageId(getRandomId());
messageMetadata3.put(fooUpdateId, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", false)
));
BdfList fooUpdate = BdfList.of("foo", 1, fooPropertiesDict);
context.checking(new Expectations() {{
oneOf(db).startTransaction(false);
will(returnValue(txn));
oneOf(db).getContacts(txn);
will(returnValue(contacts));
// First contact: skipped because not active
// Second contact: no updates
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact2);
will(returnValue(contactGroup2));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup2.getId());
will(returnValue(Collections.emptyMap()));
// Third contact: returns an update
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact3);
will(returnValue(contactGroup3));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup3.getId());
will(returnValue(messageMetadata3));
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId);
will(returnValue(fooUpdate));
oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn);
}});
TransportPropertyManagerImpl t = createInstance();
Map<ContactId, TransportProperties> properties =
t.getRemoteProperties(new TransportId("foo"));
assertEquals(3, properties.size());
assertEquals(0, properties.get(contact1.getId()).size());
assertEquals(0, properties.get(contact2.getId()).size());
assertEquals(fooProperties, properties.get(contact3.getId()));
}
@Test
public void testMergingUnchangedPropertiesDoesNotCreateUpdate()
throws Exception {
Transaction txn = new Transaction(null, false);
MessageId updateId = new MessageId(getRandomId());
Map<MessageId, BdfDictionary> messageMetadata =
Collections.singletonMap(updateId, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", true)
));
BdfList update = BdfList.of("foo", 1, fooPropertiesDict);
context.checking(new Expectations() {{
oneOf(db).startTransaction(false);
will(returnValue(txn));
// Merge the new properties with the existing properties
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, updateId);
will(returnValue(update));
// Properties are unchanged so we're done
oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn);
}});
TransportPropertyManagerImpl t = createInstance();
t.mergeLocalProperties(new TransportId("foo"), fooProperties);
}
@Test
public void testMergingNewPropertiesCreatesUpdate() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact(true);
Group contactGroup = getGroup();
context.checking(new Expectations() {{
oneOf(db).startTransaction(false);
will(returnValue(txn));
// There are no existing properties to merge with
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(Collections.emptyMap()));
// Store the new properties in the local group, version 1
expectStoreMessage(txn, localGroup.getId(), "foo",
fooPropertiesDict, 1, true, false);
// Store the new properties in each contact's group, version 1
oneOf(db).getContacts(txn);
will(returnValue(Collections.singletonList(contact)));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId());
will(returnValue(Collections.emptyMap()));
expectStoreMessage(txn, contactGroup.getId(), "foo",
fooPropertiesDict, 1, true, true);
oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn);
}});
TransportPropertyManagerImpl t = createInstance();
t.mergeLocalProperties(new TransportId("foo"), fooProperties);
}
@Test
public void testMergingUpdatedPropertiesCreatesUpdate() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact(true);
Group contactGroup = getGroup();
BdfDictionary oldMetadata = BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 1),
new BdfEntry("local", true)
);
MessageId localGroupUpdateId = new MessageId(getRandomId());
Map<MessageId, BdfDictionary> localGroupMessageMetadata =
Collections.singletonMap(localGroupUpdateId, oldMetadata);
MessageId contactGroupUpdateId = new MessageId(getRandomId());
Map<MessageId, BdfDictionary> contactGroupMessageMetadata =
Collections.singletonMap(contactGroupUpdateId, oldMetadata);
BdfList oldUpdate = BdfList.of("foo", 1, BdfDictionary.of(
new BdfEntry("fooKey1", "oldFooValue1")
));
context.checking(new Expectations() {{
oneOf(db).startTransaction(false);
will(returnValue(txn));
// Merge the new properties with the existing properties
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(localGroupMessageMetadata));
oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId);
will(returnValue(oldUpdate));
// Store the merged properties in the local group, version 2
expectStoreMessage(txn, localGroup.getId(), "foo",
fooPropertiesDict, 2, true, false);
// Delete the previous update
oneOf(db).removeMessage(txn, localGroupUpdateId);
// Store the merged properties in each contact's group, version 2
oneOf(db).getContacts(txn);
will(returnValue(Collections.singletonList(contact)));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId());
will(returnValue(contactGroupMessageMetadata));
expectStoreMessage(txn, contactGroup.getId(), "foo",
fooPropertiesDict, 2, true, true);
// Delete the previous update
oneOf(db).removeMessage(txn, contactGroupUpdateId);
oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn);
}});
TransportPropertyManagerImpl t = createInstance();
t.mergeLocalProperties(new TransportId("foo"), fooProperties);
}
private Group getGroup() {
GroupId g = new GroupId(getRandomId());
byte[] descriptor = getRandomBytes(MAX_GROUP_DESCRIPTOR_LENGTH);
return new Group(g, CLIENT_ID, descriptor);
}
private LocalAuthor getLocalAuthor() {
AuthorId id = new AuthorId(getRandomId());
String name = getRandomString(MAX_AUTHOR_NAME_LENGTH);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
byte[] privateKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
long created = System.currentTimeMillis();
return new LocalAuthor(id, name, publicKey, privateKey, created);
}
private Contact getContact(boolean active) {
ContactId c = new ContactId(nextContactId++);
AuthorId a = new AuthorId(getRandomId());
String name = getRandomString(MAX_AUTHOR_NAME_LENGTH);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
return new Contact(c, new Author(a, name, publicKey),
localAuthor.getId(), true, active);
}
private Message getMessage(GroupId g, long timestamp) {
MessageId messageId = new MessageId(getRandomId());
byte[] raw = getRandomBytes(MAX_MESSAGE_BODY_LENGTH);
return new Message(messageId, g, timestamp, raw);
}
private void expectGetLocalProperties(Transaction txn)
throws Exception {
Map<MessageId, BdfDictionary> messageMetadata =
new LinkedHashMap<>();
// The only update for transport "foo" should be returned
MessageId fooVersion999 = new MessageId(getRandomId());
messageMetadata.put(fooVersion999, BdfDictionary.of(
new BdfEntry("transportId", "foo"),
new BdfEntry("version", 999)
));
// An old update for transport "bar" should be deleted
MessageId barVersion2 = new MessageId(getRandomId());
messageMetadata.put(barVersion2, BdfDictionary.of(
new BdfEntry("transportId", "bar"),
new BdfEntry("version", 2)
));
// An even older update for transport "bar" should be deleted
MessageId barVersion1 = new MessageId(getRandomId());
messageMetadata.put(barVersion1, BdfDictionary.of(
new BdfEntry("transportId", "bar"),
new BdfEntry("version", 1)
));
// The latest update for transport "bar" should be returned
MessageId barVersion3 = new MessageId(getRandomId());
messageMetadata.put(barVersion3, BdfDictionary.of(
new BdfEntry("transportId", "bar"),
new BdfEntry("version", 3)
));
BdfList fooUpdate = BdfList.of("foo", 999, fooPropertiesDict);
BdfList barUpdate = BdfList.of("bar", 3, barPropertiesDict);
context.checking(new Expectations() {{
// Find the latest local update for each transport
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(messageMetadata));
oneOf(db).removeMessage(txn, barVersion1);
oneOf(db).removeMessage(txn, barVersion2);
// Retrieve and parse the latest local properties
oneOf(clientHelper).getMessageAsList(txn, fooVersion999);
will(returnValue(fooUpdate));
oneOf(clientHelper).getMessageAsList(txn, barVersion3);
will(returnValue(barUpdate));
}});
}
private void expectStoreMessage(Transaction txn, GroupId g,
String transportId, BdfDictionary properties, long version,
boolean local, boolean shared) throws Exception {
long timestamp = 123456789;
BdfList body = BdfList.of(transportId, version, properties);
Message message = getMessage(g, timestamp);
BdfDictionary meta = BdfDictionary.of(
new BdfEntry("transportId", transportId),
new BdfEntry("version", version),
new BdfEntry("local", local)
);
context.checking(new Expectations() {{
oneOf(clock).currentTimeMillis();
will(returnValue(timestamp));
oneOf(clientHelper).createMessage(g, timestamp, body);
will(returnValue(message));
oneOf(clientHelper).addLocalMessage(txn, message, meta, shared);
}});
}
}

View File

@@ -6,10 +6,10 @@ import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.sync.Ack; import org.briarproject.bramble.api.sync.Ack;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.RecordWriter;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.ImmediateExecutor; import org.briarproject.bramble.test.ImmediateExecutor;
import org.briarproject.bramble.test.TestUtils; import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.api.sync.RecordWriter;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.Mockery; import org.jmock.Mockery;
import org.junit.Test; import org.junit.Test;
@@ -44,10 +44,10 @@ public class SimplexOutgoingSessionTest extends BrambleTestCase {
@Test @Test
public void testNothingToSend() throws Exception { public void testNothingToSend() throws Exception {
final SimplexOutgoingSession session = new SimplexOutgoingSession(db, SimplexOutgoingSession session = new SimplexOutgoingSession(db,
dbExecutor, eventBus, contactId, maxLatency, recordWriter); dbExecutor, eventBus, contactId, maxLatency, recordWriter);
final Transaction noAckTxn = new Transaction(null, false); Transaction noAckTxn = new Transaction(null, false);
final Transaction noMsgTxn = new Transaction(null, false); Transaction noMsgTxn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Add listener // Add listener
@@ -80,14 +80,14 @@ public class SimplexOutgoingSessionTest extends BrambleTestCase {
@Test @Test
public void testSomethingToSend() throws Exception { public void testSomethingToSend() throws Exception {
final Ack ack = new Ack(Collections.singletonList(messageId)); Ack ack = new Ack(Collections.singletonList(messageId));
final byte[] raw = new byte[1234]; byte[] raw = new byte[1234];
final SimplexOutgoingSession session = new SimplexOutgoingSession(db, SimplexOutgoingSession session = new SimplexOutgoingSession(db,
dbExecutor, eventBus, contactId, maxLatency, recordWriter); dbExecutor, eventBus, contactId, maxLatency, recordWriter);
final Transaction ackTxn = new Transaction(null, false); Transaction ackTxn = new Transaction(null, false);
final Transaction noAckTxn = new Transaction(null, false); Transaction noAckTxn = new Transaction(null, false);
final Transaction msgTxn = new Transaction(null, false); Transaction msgTxn = new Transaction(null, false);
final Transaction noMsgTxn = new Transaction(null, false); Transaction noMsgTxn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Add listener // Add listener

View File

@@ -92,9 +92,9 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testStartAndStop() throws Exception { public void testStartAndStop() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, true); Transaction txn1 = new Transaction(null, true);
final Transaction txn2 = new Transaction(null, true); Transaction txn2 = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// validateOutstandingMessages() // validateOutstandingMessages()
@@ -126,13 +126,13 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testMessagesAreValidatedAtStartup() throws Exception { public void testMessagesAreValidatedAtStartup() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, true); Transaction txn1 = new Transaction(null, true);
final Transaction txn2 = new Transaction(null, false); Transaction txn2 = new Transaction(null, false);
final Transaction txn3 = new Transaction(null, true); Transaction txn3 = new Transaction(null, true);
final Transaction txn4 = new Transaction(null, false); Transaction txn4 = new Transaction(null, false);
final Transaction txn5 = new Transaction(null, true); Transaction txn5 = new Transaction(null, true);
final Transaction txn6 = new Transaction(null, true); Transaction txn6 = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Get messages to validate // Get messages to validate
@@ -217,11 +217,11 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testPendingMessagesAreDeliveredAtStartup() throws Exception { public void testPendingMessagesAreDeliveredAtStartup() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, true); Transaction txn1 = new Transaction(null, true);
final Transaction txn2 = new Transaction(null, false); Transaction txn2 = new Transaction(null, false);
final Transaction txn3 = new Transaction(null, false); Transaction txn3 = new Transaction(null, false);
final Transaction txn4 = new Transaction(null, true); Transaction txn4 = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Get messages to validate // Get messages to validate
@@ -303,11 +303,11 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testMessagesAreSharedAtStartup() throws Exception { public void testMessagesAreSharedAtStartup() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, true); Transaction txn1 = new Transaction(null, true);
final Transaction txn2 = new Transaction(null, true); Transaction txn2 = new Transaction(null, true);
final Transaction txn3 = new Transaction(null, false); Transaction txn3 = new Transaction(null, false);
final Transaction txn4 = new Transaction(null, false); Transaction txn4 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// No messages to validate // No messages to validate
@@ -355,9 +355,9 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testIncomingMessagesAreShared() throws Exception { public void testIncomingMessagesAreShared() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
final Transaction txn2 = new Transaction(null, false); Transaction txn2 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group
@@ -405,12 +405,12 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testValidationContinuesAfterNoSuchMessageException() public void testValidationContinuesAfterNoSuchMessageException()
throws Exception { throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, true); Transaction txn1 = new Transaction(null, true);
final Transaction txn2 = new Transaction(null, true); Transaction txn2 = new Transaction(null, true);
final Transaction txn3 = new Transaction(null, false); Transaction txn3 = new Transaction(null, false);
final Transaction txn4 = new Transaction(null, true); Transaction txn4 = new Transaction(null, true);
final Transaction txn5 = new Transaction(null, true); Transaction txn5 = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Get messages to validate // Get messages to validate
@@ -476,12 +476,12 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testValidationContinuesAfterNoSuchGroupException() public void testValidationContinuesAfterNoSuchGroupException()
throws Exception { throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, true); Transaction txn1 = new Transaction(null, true);
final Transaction txn2 = new Transaction(null, true); Transaction txn2 = new Transaction(null, true);
final Transaction txn3 = new Transaction(null, false); Transaction txn3 = new Transaction(null, false);
final Transaction txn4 = new Transaction(null, true); Transaction txn4 = new Transaction(null, true);
final Transaction txn5 = new Transaction(null, true); Transaction txn5 = new Transaction(null, true);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Get messages to validate // Get messages to validate
@@ -551,8 +551,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testNonLocalMessagesAreValidatedWhenAdded() throws Exception { public void testNonLocalMessagesAreValidatedWhenAdded() throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group
@@ -591,8 +591,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testMessagesWithUndeliveredDependenciesArePending() public void testMessagesWithUndeliveredDependenciesArePending()
throws Exception { throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group
@@ -624,8 +624,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testMessagesWithDeliveredDependenciesGetDelivered() public void testMessagesWithDeliveredDependenciesGetDelivered()
throws Exception { throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group
@@ -663,9 +663,9 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testMessagesWithInvalidDependenciesAreInvalid() public void testMessagesWithInvalidDependenciesAreInvalid()
throws Exception { throws Exception {
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
final Transaction txn2 = new Transaction(null, false); Transaction txn2 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group
@@ -716,19 +716,18 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testRecursiveInvalidation() throws Exception { public void testRecursiveInvalidation() throws Exception {
final MessageId messageId3 = new MessageId(TestUtils.getRandomId()); MessageId messageId3 = new MessageId(TestUtils.getRandomId());
final MessageId messageId4 = new MessageId(TestUtils.getRandomId()); MessageId messageId4 = new MessageId(TestUtils.getRandomId());
final Map<MessageId, State> twoDependents = Map<MessageId, State> twoDependents = new LinkedHashMap<>();
new LinkedHashMap<MessageId, State>();
twoDependents.put(messageId1, PENDING); twoDependents.put(messageId1, PENDING);
twoDependents.put(messageId2, PENDING); twoDependents.put(messageId2, PENDING);
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
final Transaction txn2 = new Transaction(null, false); Transaction txn2 = new Transaction(null, false);
final Transaction txn3 = new Transaction(null, false); Transaction txn3 = new Transaction(null, false);
final Transaction txn4 = new Transaction(null, false); Transaction txn4 = new Transaction(null, false);
final Transaction txn5 = new Transaction(null, false); Transaction txn5 = new Transaction(null, false);
final Transaction txn6 = new Transaction(null, false); Transaction txn6 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group
@@ -820,27 +819,25 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testPendingDependentsGetDelivered() throws Exception { public void testPendingDependentsGetDelivered() throws Exception {
final MessageId messageId3 = new MessageId(TestUtils.getRandomId()); MessageId messageId3 = new MessageId(TestUtils.getRandomId());
final MessageId messageId4 = new MessageId(TestUtils.getRandomId()); MessageId messageId4 = new MessageId(TestUtils.getRandomId());
final Message message3 = new Message(messageId3, groupId, timestamp, Message message3 = new Message(messageId3, groupId, timestamp,
raw); raw);
final Message message4 = new Message(messageId4, groupId, timestamp, Message message4 = new Message(messageId4, groupId, timestamp,
raw); raw);
final Map<MessageId, State> twoDependents = Map<MessageId, State> twoDependents = new LinkedHashMap<>();
new LinkedHashMap<MessageId, State>();
twoDependents.put(messageId1, PENDING); twoDependents.put(messageId1, PENDING);
twoDependents.put(messageId2, PENDING); twoDependents.put(messageId2, PENDING);
final Map<MessageId, State> twoDependencies = Map<MessageId, State> twoDependencies = new LinkedHashMap<>();
new LinkedHashMap<MessageId, State>();
twoDependencies.put(messageId1, DELIVERED); twoDependencies.put(messageId1, DELIVERED);
twoDependencies.put(messageId2, DELIVERED); twoDependencies.put(messageId2, DELIVERED);
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
final Transaction txn2 = new Transaction(null, false); Transaction txn2 = new Transaction(null, false);
final Transaction txn3 = new Transaction(null, false); Transaction txn3 = new Transaction(null, false);
final Transaction txn4 = new Transaction(null, false); Transaction txn4 = new Transaction(null, false);
final Transaction txn5 = new Transaction(null, false); Transaction txn5 = new Transaction(null, false);
final Transaction txn6 = new Transaction(null, false); Transaction txn6 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group
@@ -979,13 +976,12 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testOnlyReadyPendingDependentsGetDelivered() throws Exception { public void testOnlyReadyPendingDependentsGetDelivered() throws Exception {
final Map<MessageId, State> twoDependencies = Map<MessageId, State> twoDependencies = new LinkedHashMap<>();
new LinkedHashMap<MessageId, State>();
twoDependencies.put(messageId, DELIVERED); twoDependencies.put(messageId, DELIVERED);
twoDependencies.put(messageId2, UNKNOWN); twoDependencies.put(messageId2, UNKNOWN);
final Transaction txn = new Transaction(null, true); Transaction txn = new Transaction(null, true);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
final Transaction txn2 = new Transaction(null, false); Transaction txn2 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Load the group // Load the group

View File

@@ -38,7 +38,7 @@ public class LinuxSecureRandomSpiTest extends BrambleTestCase {
System.err.println("WARNING: Skipping test, can't run on this OS"); System.err.println("WARNING: Skipping test, can't run on this OS");
return; return;
} }
Set<Bytes> seeds = new HashSet<Bytes>(); Set<Bytes> seeds = new HashSet<>();
LinuxSecureRandomSpi engine = new LinuxSecureRandomSpi(); LinuxSecureRandomSpi engine = new LinuxSecureRandomSpi();
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
byte[] seed = engine.engineGenerateSeed(SEED_BYTES); byte[] seed = engine.engineGenerateSeed(SEED_BYTES);

View File

@@ -58,21 +58,21 @@ public class KeyManagerImplTest extends BrambleTestCase {
@Before @Before
public void testStartService() throws Exception { public void testStartService() throws Exception {
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
AuthorId remoteAuthorId = new AuthorId(getRandomId()); AuthorId remoteAuthorId = new AuthorId(getRandomId());
Author remoteAuthor = new Author(remoteAuthorId, "author", Author remoteAuthor = new Author(remoteAuthorId, "author",
getRandomBytes(42)); getRandomBytes(42));
AuthorId localAuthorId = new AuthorId(getRandomId()); AuthorId localAuthorId = new AuthorId(getRandomId());
final Collection<Contact> contacts = new ArrayList<Contact>(); Collection<Contact> contacts = new ArrayList<>();
contacts.add(new Contact(contactId, remoteAuthor, localAuthorId, true, contacts.add(new Contact(contactId, remoteAuthor, localAuthorId, true,
true)); true));
contacts.add(new Contact(inactiveContactId, remoteAuthor, localAuthorId, contacts.add(new Contact(inactiveContactId, remoteAuthor, localAuthorId,
true, false)); true, false));
final SimplexPluginFactory pluginFactory = SimplexPluginFactory pluginFactory =
context.mock(SimplexPluginFactory.class); context.mock(SimplexPluginFactory.class);
final Collection<SimplexPluginFactory> factories = Collections Collection<SimplexPluginFactory> factories = Collections
.singletonList(pluginFactory); .singletonList(pluginFactory);
final int maxLatency = 1337; int maxLatency = 1337;
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(pluginConfig).getSimplexFactories(); oneOf(pluginConfig).getSimplexFactories();
@@ -100,9 +100,9 @@ public class KeyManagerImplTest extends BrambleTestCase {
@Test @Test
public void testAddContact() throws Exception { public void testAddContact() throws Exception {
final SecretKey secretKey = getSecretKey(); SecretKey secretKey = getSecretKey();
final long timestamp = 42L; long timestamp = 42L;
final boolean alice = true; boolean alice = true;
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(transportKeyManager) oneOf(transportKeyManager)

View File

@@ -14,7 +14,7 @@ public class StreamReaderImplTest extends BrambleTestCase {
@Test @Test
public void testEmptyFramesAreSkipped() throws Exception { public void testEmptyFramesAreSkipped() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamDecrypter decrypter = context.mock(StreamDecrypter.class); StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class))); oneOf(decrypter).readFrame(with(any(byte[].class)));
will(returnValue(0)); // Empty frame will(returnValue(0)); // Empty frame
@@ -37,7 +37,7 @@ public class StreamReaderImplTest extends BrambleTestCase {
@Test @Test
public void testEmptyFramesAreSkippedWithBuffer() throws Exception { public void testEmptyFramesAreSkippedWithBuffer() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamDecrypter decrypter = context.mock(StreamDecrypter.class); StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class))); oneOf(decrypter).readFrame(with(any(byte[].class)));
will(returnValue(0)); // Empty frame will(returnValue(0)); // Empty frame
@@ -63,7 +63,7 @@ public class StreamReaderImplTest extends BrambleTestCase {
@Test @Test
public void testMultipleReadsPerFrame() throws Exception { public void testMultipleReadsPerFrame() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamDecrypter decrypter = context.mock(StreamDecrypter.class); StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class))); oneOf(decrypter).readFrame(with(any(byte[].class)));
will(returnValue(MAX_PAYLOAD_LENGTH)); // Nice long frame will(returnValue(MAX_PAYLOAD_LENGTH)); // Nice long frame
@@ -85,7 +85,7 @@ public class StreamReaderImplTest extends BrambleTestCase {
@Test @Test
public void testMultipleReadsPerFrameWithOffsets() throws Exception { public void testMultipleReadsPerFrameWithOffsets() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamDecrypter decrypter = context.mock(StreamDecrypter.class); StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class))); oneOf(decrypter).readFrame(with(any(byte[].class)));
will(returnValue(MAX_PAYLOAD_LENGTH)); // Nice long frame will(returnValue(MAX_PAYLOAD_LENGTH)); // Nice long frame

View File

@@ -14,7 +14,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
@Test @Test
public void testCloseWithoutWritingWritesFinalFrame() throws Exception { public void testCloseWithoutWritingWritesFinalFrame() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Write an empty final frame // Write an empty final frame
oneOf(encrypter).writeFrame(with(any(byte[].class)), with(0), oneOf(encrypter).writeFrame(with(any(byte[].class)), with(0),
@@ -31,7 +31,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
public void testFlushWithoutBufferedDataWritesFrameAndFlushes() public void testFlushWithoutBufferedDataWritesFrameAndFlushes()
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Write a non-final frame with an empty payload // Write a non-final frame with an empty payload
@@ -58,7 +58,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
public void testFlushWithBufferedDataWritesFrameAndFlushes() public void testFlushWithBufferedDataWritesFrameAndFlushes()
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Write a non-final frame with one payload byte // Write a non-final frame with one payload byte
@@ -85,7 +85,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
@Test @Test
public void testSingleByteWritesWriteFullFrame() throws Exception { public void testSingleByteWritesWriteFullFrame() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Write a full non-final frame // Write a full non-final frame
@@ -109,7 +109,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
@Test @Test
public void testMultiByteWritesWriteFullFrames() throws Exception { public void testMultiByteWritesWriteFullFrames() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Write two full non-final frames // Write two full non-final frames
@@ -140,7 +140,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
@Test @Test
public void testLargeMultiByteWriteWritesFullFrames() throws Exception { public void testLargeMultiByteWriteWritesFullFrames() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Write two full non-final frames // Write two full non-final frames

View File

@@ -56,21 +56,20 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
@Test @Test
public void testKeysAreRotatedAtStartup() throws Exception { public void testKeysAreRotatedAtStartup() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final Map<ContactId, TransportKeys> loaded = Map<ContactId, TransportKeys> loaded = new LinkedHashMap<>();
new LinkedHashMap<ContactId, TransportKeys>(); TransportKeys shouldRotate = createTransportKeys(900, 0);
final TransportKeys shouldRotate = createTransportKeys(900, 0); TransportKeys shouldNotRotate = createTransportKeys(1000, 0);
final TransportKeys shouldNotRotate = createTransportKeys(1000, 0);
loaded.put(contactId, shouldRotate); loaded.put(contactId, shouldRotate);
loaded.put(contactId1, shouldNotRotate); loaded.put(contactId1, shouldNotRotate);
final TransportKeys rotated = createTransportKeys(1000, 0); TransportKeys rotated = createTransportKeys(1000, 0);
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Get the current time (1 ms after start of rotation period 1000) // Get the current time (1 ms after start of rotation period 1000)
@@ -109,17 +108,17 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
@Test @Test
public void testKeysAreRotatedWhenAddingContact() throws Exception { public void testKeysAreRotatedWhenAddingContact() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final boolean alice = true; boolean alice = true;
final TransportKeys transportKeys = createTransportKeys(999, 0); TransportKeys transportKeys = createTransportKeys(999, 0);
final TransportKeys rotated = createTransportKeys(1000, 0); TransportKeys rotated = createTransportKeys(1000, 0);
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(crypto).deriveTransportKeys(transportId, masterKey, 999, oneOf(crypto).deriveTransportKeys(transportId, masterKey, 999,
@@ -156,14 +155,14 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
public void testOutgoingStreamContextIsNullIfContactIsNotFound() public void testOutgoingStreamContextIsNullIfContactIsNotFound()
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
TransportKeyManager TransportKeyManager
transportKeyManager = new TransportKeyManagerImpl(db, transportKeyManager = new TransportKeyManagerImpl(db,
@@ -177,18 +176,18 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
public void testOutgoingStreamContextIsNullIfStreamCounterIsExhausted() public void testOutgoingStreamContextIsNullIfStreamCounterIsExhausted()
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final boolean alice = true; boolean alice = true;
// The stream counter has been exhausted // The stream counter has been exhausted
final TransportKeys transportKeys = createTransportKeys(1000, TransportKeys transportKeys = createTransportKeys(1000,
MAX_32_BIT_UNSIGNED + 1); MAX_32_BIT_UNSIGNED + 1);
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000, oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000,
@@ -225,18 +224,18 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
@Test @Test
public void testOutgoingStreamCounterIsIncremented() throws Exception { public void testOutgoingStreamCounterIsIncremented() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final boolean alice = true; boolean alice = true;
// The stream counter can be used one more time before being exhausted // The stream counter can be used one more time before being exhausted
final TransportKeys transportKeys = createTransportKeys(1000, TransportKeys transportKeys = createTransportKeys(1000,
MAX_32_BIT_UNSIGNED); MAX_32_BIT_UNSIGNED);
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000, oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000,
@@ -286,16 +285,16 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
public void testIncomingStreamContextIsNullIfTagIsNotFound() public void testIncomingStreamContextIsNullIfTagIsNotFound()
throws Exception { throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final boolean alice = true; boolean alice = true;
final TransportKeys transportKeys = createTransportKeys(1000, 0); TransportKeys transportKeys = createTransportKeys(1000, 0);
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000, oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000,
@@ -333,18 +332,18 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
@Test @Test
public void testTagIsNotRecognisedTwice() throws Exception { public void testTagIsNotRecognisedTwice() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final boolean alice = true; boolean alice = true;
final TransportKeys transportKeys = createTransportKeys(1000, 0); TransportKeys transportKeys = createTransportKeys(1000, 0);
// Keep a copy of the tags // Keep a copy of the tags
final List<byte[]> tags = new ArrayList<byte[]>(); List<byte[]> tags = new ArrayList<>();
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000, oneOf(crypto).deriveTransportKeys(transportId, masterKey, 1000,
@@ -403,19 +402,19 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
@Test @Test
public void testKeysAreRotatedToCurrentPeriod() throws Exception { public void testKeysAreRotatedToCurrentPeriod() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final DatabaseComponent db = context.mock(DatabaseComponent.class); DatabaseComponent db = context.mock(DatabaseComponent.class);
final CryptoComponent crypto = context.mock(CryptoComponent.class); CryptoComponent crypto = context.mock(CryptoComponent.class);
final Executor dbExecutor = context.mock(Executor.class); Executor dbExecutor = context.mock(Executor.class);
final ScheduledExecutorService scheduler = ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class); context.mock(ScheduledExecutorService.class);
final Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
final TransportKeys transportKeys = createTransportKeys(1000, 0); TransportKeys transportKeys = createTransportKeys(1000, 0);
final Map<ContactId, TransportKeys> loaded = Map<ContactId, TransportKeys> loaded =
Collections.singletonMap(contactId, transportKeys); Collections.singletonMap(contactId, transportKeys);
final TransportKeys rotated = createTransportKeys(1001, 0); TransportKeys rotated = createTransportKeys(1001, 0);
final Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
final Transaction txn1 = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Get the current time (the start of rotation period 1000) // Get the current time (the start of rotation period 1000)

View File

@@ -1,22 +1,55 @@
apply plugin: 'java' apply plugin: 'java-library'
sourceCompatibility = 1.7 sourceCompatibility = 1.8
targetCompatibility = 1.7 targetCompatibility = 1.8
apply plugin: 'net.ltgt.apt'
apply plugin: 'idea'
apply plugin: 'witness' apply plugin: 'witness'
dependencies { dependencies {
compile project(':bramble-core') implementation project(path: ':bramble-core', configuration: 'default')
compile fileTree(dir: 'libs', include: '*.jar') implementation fileTree(dir: 'libs', include: '*.jar')
compile 'net.java.dev.jna:jna:4.4.0' implementation 'net.java.dev.jna:jna:4.4.0'
compile 'net.java.dev.jna:jna-platform:4.4.0' implementation 'net.java.dev.jna:jna-platform:4.4.0'
testCompile project(path: ':bramble-core', configuration: 'testOutput') apt 'com.google.dagger:dagger-compiler:2.0.2'
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation project(path: ':bramble-core', configuration: 'testOutput')
testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation "org.hamcrest:hamcrest-library:1.3"
testImplementation "org.hamcrest:hamcrest-core:1.3"
} }
dependencyVerification { dependencyVerification {
verify = [ verify = [
'net.java.dev.jna:jna:c4dadeeecaa90c8847902082aee5eb107fcf59c5d0e63a17fcaf273c0e2d2bd1', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'net.java.dev.jna:jna-platform:e9dda9e884fc107eb6367710540789a12dfa8ad28be9326b22ca6e352e325499', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.java.dev.jna:jna-platform:4.4.0:jna-platform-4.4.0.jar:e9dda9e884fc107eb6367710540789a12dfa8ad28be9326b22ca6e352e325499',
'net.java.dev.jna:jna:4.4.0:jna-4.4.0.jar:c4dadeeecaa90c8847902082aee5eb107fcf59c5d0e63a17fcaf273c0e2d2bd1',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
] ]
} }

View File

@@ -110,20 +110,16 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
public void run() { public void run() {
try { try {
// Load user32.dll // Load user32.dll
final User32 user32 = (User32) Native.loadLibrary("user32", User32 user32 = (User32) Native.loadLibrary("user32",
User32.class, options); User32.class, options);
// Create a callback to handle the WM_QUERYENDSESSION message // Create a callback to handle the WM_QUERYENDSESSION message
WindowProc proc = new WindowProc() { WindowProc proc = (hwnd, msg, wp, lp) -> {
@Override if (msg == WM_QUERYENDSESSION) {
public LRESULT callback(HWND hwnd, int msg, WPARAM wp, // It's safe to delay returning from this message
LPARAM lp) { runShutdownHooks();
if (msg == WM_QUERYENDSESSION) {
// It's safe to delay returning from this message
runShutdownHooks();
}
// Pass the message to the default window procedure
return user32.DefWindowProc(hwnd, msg, wp, lp);
} }
// Pass the message to the default window procedure
return user32.DefWindowProc(hwnd, msg, wp, lp);
}; };
// Create a native window // Create a native window
HWND hwnd = user32.CreateWindowEx(0, "STATIC", "", WS_MINIMIZE, HWND hwnd = user32.CreateWindowEx(0, "STATIC", "", WS_MINIMIZE,

View File

@@ -41,9 +41,9 @@ public class DesktopPluginModule extends PluginModule {
backoffFactory, shutdownManager); backoffFactory, shutdownManager);
SimplexPluginFactory removable = SimplexPluginFactory removable =
new RemovableDrivePluginFactory(ioExecutor); new RemovableDrivePluginFactory(ioExecutor);
final Collection<SimplexPluginFactory> simplex = Collection<SimplexPluginFactory> simplex =
Collections.singletonList(removable); Collections.singletonList(removable);
final Collection<DuplexPluginFactory> duplex = Collection<DuplexPluginFactory> duplex =
Arrays.asList(bluetooth, modem, lan, wan); Arrays.asList(bluetooth, modem, lan, wan);
@NotNullByDefault @NotNullByDefault
PluginConfig pluginConfig = new PluginConfig() { PluginConfig pluginConfig = new PluginConfig() {

View File

@@ -108,33 +108,30 @@ class BluetoothPlugin implements DuplexPlugin {
} }
private void bind() { private void bind() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override if (!running) return;
public void run() { // Advertise the Bluetooth address to contacts
if (!running) return; TransportProperties p = new TransportProperties();
// Advertise the Bluetooth address to contacts p.put(PROP_ADDRESS, localDevice.getBluetoothAddress());
TransportProperties p = new TransportProperties(); callback.mergeLocalProperties(p);
p.put(PROP_ADDRESS, localDevice.getBluetoothAddress()); // Bind a server socket to accept connections from contacts
callback.mergeLocalProperties(p); String url = makeUrl("localhost", getUuid());
// Bind a server socket to accept connections from contacts StreamConnectionNotifier ss;
String url = makeUrl("localhost", getUuid()); try {
StreamConnectionNotifier ss; ss = (StreamConnectionNotifier) Connector.open(url);
try { } catch (IOException e) {
ss = (StreamConnectionNotifier) Connector.open(url); if (LOG.isLoggable(WARNING))
} catch (IOException e) { LOG.log(WARNING, e.toString(), e);
if (LOG.isLoggable(WARNING)) return;
LOG.log(WARNING, e.toString(), e);
return;
}
if (!running) {
tryToClose(ss);
return;
}
socket = ss;
backoff.reset();
callback.transportEnabled();
acceptContactConnections(ss);
} }
if (!running) {
tryToClose(ss);
return;
}
socket = ss;
backoff.reset();
callback.transportEnabled();
acceptContactConnections(ss);
}); });
} }
@@ -207,33 +204,31 @@ class BluetoothPlugin implements DuplexPlugin {
} }
@Override @Override
public void poll(final Collection<ContactId> connected) { public void poll(Collection<ContactId> connected) {
if (!running) return; if (!running) return;
backoff.increment(); backoff.increment();
// Try to connect to known devices in parallel // Try to connect to known devices in parallel
Map<ContactId, TransportProperties> remote = Map<ContactId, TransportProperties> remote =
callback.getRemoteProperties(); callback.getRemoteProperties();
for (Entry<ContactId, TransportProperties> e : remote.entrySet()) { for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
final ContactId c = e.getKey(); ContactId c = e.getKey();
if (connected.contains(c)) continue; if (connected.contains(c)) continue;
final String address = e.getValue().get(PROP_ADDRESS); String address = e.getValue().get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) continue; if (StringUtils.isNullOrEmpty(address)) continue;
final String uuid = e.getValue().get(PROP_UUID); String uuid = e.getValue().get(PROP_UUID);
if (StringUtils.isNullOrEmpty(uuid)) continue; if (StringUtils.isNullOrEmpty(uuid)) continue;
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override if (!running) return;
public void run() { StreamConnection s = connect(makeUrl(address, uuid));
if (!running) return; if (s != null) {
StreamConnection s = connect(makeUrl(address, uuid)); backoff.reset();
if (s != null) { callback.outgoingConnectionCreated(c, wrapSocket(s));
backoff.reset();
callback.outgoingConnectionCreated(c, wrapSocket(s));
}
} }
}); });
} }
} }
@Nullable
private StreamConnection connect(String url) { private StreamConnection connect(String url) {
if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + url); if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + url);
try { try {
@@ -275,7 +270,7 @@ class BluetoothPlugin implements DuplexPlugin {
// Make the device discoverable if possible // Make the device discoverable if possible
makeDeviceDiscoverable(); makeDeviceDiscoverable();
// Bind a server socket for receiving key agreementconnections // Bind a server socket for receiving key agreementconnections
final StreamConnectionNotifier ss; StreamConnectionNotifier ss;
try { try {
ss = (StreamConnectionNotifier) Connector.open(url); ss = (StreamConnectionNotifier) Connector.open(url);
} catch (IOException e) { } catch (IOException e) {
@@ -341,16 +336,13 @@ class BluetoothPlugin implements DuplexPlugin {
@Override @Override
public Callable<KeyAgreementConnection> listen() { public Callable<KeyAgreementConnection> listen() {
return new Callable<KeyAgreementConnection>() { return () -> {
@Override StreamConnection s = ss.acceptAndOpen();
public KeyAgreementConnection call() throws Exception { if (LOG.isLoggable(INFO))
StreamConnection s = ss.acceptAndOpen(); LOG.info(ID.getString() + ": Incoming connection");
if (LOG.isLoggable(INFO)) return new KeyAgreementConnection(
LOG.info(ID.getString() + ": Incoming connection"); new BluetoothTransportConnection(
return new KeyAgreementConnection( BluetoothPlugin.this, s), ID);
new BluetoothTransportConnection(
BluetoothPlugin.this, s), ID);
}
}; };
} }

View File

@@ -13,6 +13,8 @@ import java.util.List;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import javax.annotation.Nullable;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
abstract class UnixRemovableDriveMonitor implements RemovableDriveMonitor, abstract class UnixRemovableDriveMonitor implements RemovableDriveMonitor,
@@ -34,13 +36,12 @@ JNotifyListener {
protected abstract String[] getPathsToWatch(); protected abstract String[] getPathsToWatch();
@Nullable
private static Throwable tryLoad() { private static Throwable tryLoad() {
try { try {
Class.forName("net.contentobjects.jnotify.JNotify"); Class.forName("net.contentobjects.jnotify.JNotify");
return null; return null;
} catch (UnsatisfiedLinkError e) { } catch (UnsatisfiedLinkError | ClassNotFoundException e) {
return e;
} catch (ClassNotFoundException e) {
return e; return e;
} }
} }

View File

@@ -390,15 +390,12 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
lock.unlock(); lock.unlock();
} }
} else if (s.equals("RING")) { } else if (s.equals("RING")) {
ioExecutor.execute(new Runnable() { ioExecutor.execute(() -> {
@Override try {
public void run() { answer();
try { } catch (IOException e) {
answer(); if (LOG.isLoggable(WARNING))
} catch (IOException e) { LOG.log(WARNING, e.toString(), e);
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
}
} }
}); });
} }

View File

@@ -26,10 +26,10 @@ public class PollingRemovableDriveMonitorTest extends BrambleTestCase {
@Test @Test
public void testOneCallbackPerFile() throws Exception { public void testOneCallbackPerFile() throws Exception {
// Create a finder that returns no files the first time, then two files // Create a finder that returns no files the first time, then two files
final File file1 = new File("foo"); File file1 = new File("foo");
final File file2 = new File("bar"); File file2 = new File("bar");
@NotNullByDefault @NotNullByDefault
final RemovableDriveFinder finder = new RemovableDriveFinder() { RemovableDriveFinder finder = new RemovableDriveFinder() {
private AtomicBoolean firstCall = new AtomicBoolean(true); private AtomicBoolean firstCall = new AtomicBoolean(true);
@@ -40,8 +40,8 @@ public class PollingRemovableDriveMonitorTest extends BrambleTestCase {
} }
}; };
// Create a callback that waits for two files // Create a callback that waits for two files
final CountDownLatch latch = new CountDownLatch(2); CountDownLatch latch = new CountDownLatch(2);
final List<File> detected = new ArrayList<>(); List<File> detected = new ArrayList<>();
@NotNullByDefault @NotNullByDefault
Callback callback = new Callback() { Callback callback = new Callback() {
@@ -57,7 +57,7 @@ public class PollingRemovableDriveMonitorTest extends BrambleTestCase {
} }
}; };
// Create the monitor and start it // Create the monitor and start it
final RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor( RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor(
Executors.newCachedThreadPool(), finder, 1); Executors.newCachedThreadPool(), finder, 1);
monitor.start(callback); monitor.start(callback);
// Wait for the monitor to detect the files // Wait for the monitor to detect the files
@@ -72,7 +72,7 @@ public class PollingRemovableDriveMonitorTest extends BrambleTestCase {
@Test @Test
public void testExceptionCallback() throws Exception { public void testExceptionCallback() throws Exception {
// Create a finder that throws an exception the second time it's polled // Create a finder that throws an exception the second time it's polled
final RemovableDriveFinder finder = new RemovableDriveFinder() { RemovableDriveFinder finder = new RemovableDriveFinder() {
private AtomicBoolean firstCall = new AtomicBoolean(true); private AtomicBoolean firstCall = new AtomicBoolean(true);
@@ -83,7 +83,7 @@ public class PollingRemovableDriveMonitorTest extends BrambleTestCase {
} }
}; };
// Create a callback that waits for an exception // Create a callback that waits for an exception
final CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
@NotNullByDefault @NotNullByDefault
Callback callback = new Callback() { Callback callback = new Callback() {
@@ -98,7 +98,7 @@ public class PollingRemovableDriveMonitorTest extends BrambleTestCase {
} }
}; };
// Create the monitor and start it // Create the monitor and start it
final RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor( RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor(
Executors.newCachedThreadPool(), finder, 1); Executors.newCachedThreadPool(), finder, 1);
monitor.start(callback); monitor.start(callback);
assertTrue(latch.await(10, SECONDS)); assertTrue(latch.await(10, SECONDS));

View File

@@ -41,17 +41,17 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
@Test @Test
public void testWriterIsNullIfNoDrivesAreFound() throws Exception { public void testWriterIsNullIfNoDrivesAreFound() throws Exception {
final List<File> drives = Collections.emptyList(); List<File> drives = Collections.emptyList();
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -71,21 +71,21 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
@Test @Test
public void testWriterIsNullIfNoDriveIsChosen() throws Exception { public void testWriterIsNullIfNoDriveIsChosen() throws Exception {
final File drive1 = new File(testDir, "1"); File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2"); File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<>(); List<File> drives = new ArrayList<>();
drives.add(drive1); drives.add(drive1);
drives.add(drive2); drives.add(drive2);
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -110,21 +110,21 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
@Test @Test
public void testWriterIsNullIfOutputDirDoesNotExist() throws Exception { public void testWriterIsNullIfOutputDirDoesNotExist() throws Exception {
final File drive1 = new File(testDir, "1"); File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2"); File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<>(); List<File> drives = new ArrayList<>();
drives.add(drive1); drives.add(drive1);
drives.add(drive2); drives.add(drive2);
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -149,9 +149,9 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
@Test @Test
public void testWriterIsNullIfOutputDirIsAFile() throws Exception { public void testWriterIsNullIfOutputDirIsAFile() throws Exception {
final File drive1 = new File(testDir, "1"); File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2"); File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<>(); List<File> drives = new ArrayList<>();
drives.add(drive1); drives.add(drive1);
drives.add(drive2); drives.add(drive2);
// Create drive1 as a file rather than a directory // Create drive1 as a file rather than a directory
@@ -160,12 +160,12 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -190,9 +190,9 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
@Test @Test
public void testWriterIsNotNullIfOutputDirIsADir() throws Exception { public void testWriterIsNotNullIfOutputDirIsADir() throws Exception {
final File drive1 = new File(testDir, "1"); File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2"); File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<>(); List<File> drives = new ArrayList<>();
drives.add(drive1); drives.add(drive1);
drives.add(drive2); drives.add(drive2);
// Create drive1 as a directory // Create drive1 as a directory
@@ -201,12 +201,12 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -234,9 +234,9 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
@Test @Test
public void testWritingToWriter() throws Exception { public void testWritingToWriter() throws Exception {
final File drive1 = new File(testDir, "1"); File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2"); File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<>(); List<File> drives = new ArrayList<>();
drives.add(drive1); drives.add(drive1);
drives.add(drive2); drives.add(drive2);
// Create drive1 as a directory // Create drive1 as a directory
@@ -245,12 +245,12 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -292,12 +292,12 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -318,12 +318,12 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final Executor executor = context.mock(Executor.class); Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor, RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
@@ -344,11 +344,11 @@ public class RemovableDrivePluginTest extends BrambleTestCase {
Mockery context = new Mockery() {{ Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser()); setThreadingPolicy(new Synchroniser());
}}; }};
final SimplexPluginCallback callback = SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class); context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder = RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class); context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor = RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{

View File

@@ -61,10 +61,10 @@ public class UnixRemovableDriveMonitorTest extends BrambleTestCase {
return; return;
} }
// Create a callback that will wait for two files before stopping // Create a callback that will wait for two files before stopping
final List<File> detected = new ArrayList<>(); List<File> detected = new ArrayList<>();
final CountDownLatch latch = new CountDownLatch(2); CountDownLatch latch = new CountDownLatch(2);
@NotNullByDefault @NotNullByDefault
final Callback callback = new Callback() { Callback callback = new Callback() {
@Override @Override
public void driveInserted(File f) { public void driveInserted(File f) {
@@ -99,7 +99,7 @@ public class UnixRemovableDriveMonitorTest extends BrambleTestCase {
TestUtils.deleteTestDirectory(testDir); TestUtils.deleteTestDirectory(testDir);
} }
private RemovableDriveMonitor createMonitor(final File dir) { private RemovableDriveMonitor createMonitor(File dir) {
@NotNullByDefault @NotNullByDefault
RemovableDriveMonitor monitor = new UnixRemovableDriveMonitor() { RemovableDriveMonitor monitor = new UnixRemovableDriveMonitor() {
@Override @Override

View File

@@ -21,12 +21,12 @@ public class ModemPluginTest extends BrambleTestCase {
@Test @Test
public void testModemCreation() throws Exception { public void testModemCreation() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final ModemFactory modemFactory = context.mock(ModemFactory.class); ModemFactory modemFactory = context.mock(ModemFactory.class);
final SerialPortList serialPortList = SerialPortList serialPortList =
context.mock(SerialPortList.class); context.mock(SerialPortList.class);
final ModemPlugin plugin = new ModemPlugin(modemFactory, ModemPlugin plugin = new ModemPlugin(modemFactory,
serialPortList, null, 0); serialPortList, null, 0);
final Modem modem = context.mock(Modem.class); Modem modem = context.mock(Modem.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(serialPortList).getPortNames(); oneOf(serialPortList).getPortNames();
will(returnValue(new String[] { "foo", "bar", "baz" })); will(returnValue(new String[] { "foo", "bar", "baz" }));
@@ -53,20 +53,20 @@ public class ModemPluginTest extends BrambleTestCase {
@Test @Test
public void testCreateConnection() throws Exception { public void testCreateConnection() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final ModemFactory modemFactory = context.mock(ModemFactory.class); ModemFactory modemFactory = context.mock(ModemFactory.class);
final SerialPortList serialPortList = SerialPortList serialPortList =
context.mock(SerialPortList.class); context.mock(SerialPortList.class);
final DuplexPluginCallback callback = DuplexPluginCallback callback =
context.mock(DuplexPluginCallback.class); context.mock(DuplexPluginCallback.class);
final ModemPlugin plugin = new ModemPlugin(modemFactory, ModemPlugin plugin = new ModemPlugin(modemFactory,
serialPortList, callback, 0); serialPortList, callback, 0);
final Modem modem = context.mock(Modem.class); Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties(); TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336); local.put("iso3166", ISO_1336);
final TransportProperties remote = new TransportProperties(); TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336); remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER); remote.put("number", NUMBER);
final ContactId contactId = new ContactId(234); ContactId contactId = new ContactId(234);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// start() // start()
oneOf(serialPortList).getPortNames(); oneOf(serialPortList).getPortNames();
@@ -92,20 +92,20 @@ public class ModemPluginTest extends BrambleTestCase {
@Test @Test
public void testCreateConnectionWhenDialReturnsFalse() throws Exception { public void testCreateConnectionWhenDialReturnsFalse() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final ModemFactory modemFactory = context.mock(ModemFactory.class); ModemFactory modemFactory = context.mock(ModemFactory.class);
final SerialPortList serialPortList = SerialPortList serialPortList =
context.mock(SerialPortList.class); context.mock(SerialPortList.class);
final DuplexPluginCallback callback = DuplexPluginCallback callback =
context.mock(DuplexPluginCallback.class); context.mock(DuplexPluginCallback.class);
final ModemPlugin plugin = new ModemPlugin(modemFactory, ModemPlugin plugin = new ModemPlugin(modemFactory,
serialPortList, callback, 0); serialPortList, callback, 0);
final Modem modem = context.mock(Modem.class); Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties(); TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336); local.put("iso3166", ISO_1336);
final TransportProperties remote = new TransportProperties(); TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336); remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER); remote.put("number", NUMBER);
final ContactId contactId = new ContactId(234); ContactId contactId = new ContactId(234);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// start() // start()
oneOf(serialPortList).getPortNames(); oneOf(serialPortList).getPortNames();
@@ -131,20 +131,20 @@ public class ModemPluginTest extends BrambleTestCase {
@Test @Test
public void testCreateConnectionWhenDialThrowsException() throws Exception { public void testCreateConnectionWhenDialThrowsException() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final ModemFactory modemFactory = context.mock(ModemFactory.class); ModemFactory modemFactory = context.mock(ModemFactory.class);
final SerialPortList serialPortList = SerialPortList serialPortList =
context.mock(SerialPortList.class); context.mock(SerialPortList.class);
final DuplexPluginCallback callback = DuplexPluginCallback callback =
context.mock(DuplexPluginCallback.class); context.mock(DuplexPluginCallback.class);
final ModemPlugin plugin = new ModemPlugin(modemFactory, ModemPlugin plugin = new ModemPlugin(modemFactory,
serialPortList, callback, 0); serialPortList, callback, 0);
final Modem modem = context.mock(Modem.class); Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties(); TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336); local.put("iso3166", ISO_1336);
final TransportProperties remote = new TransportProperties(); TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336); remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER); remote.put("number", NUMBER);
final ContactId contactId = new ContactId(234); ContactId contactId = new ContactId(234);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// start() // start()
oneOf(serialPortList).getPortNames(); oneOf(serialPortList).getPortNames();

View File

@@ -2,59 +2,166 @@ apply plugin: 'com.android.application'
apply plugin: 'witness' apply plugin: 'witness'
dependencies { dependencies {
def supportVersion = '23.2.1' implementation project(path: ':briar-core', configuration: 'default')
compile project(':briar-core') implementation project(path: ':bramble-core', configuration: 'default')
compile project(':bramble-android') implementation project(path: ':bramble-android', configuration: 'default')
compile "com.android.support:support-v4:$supportVersion"
compile("com.android.support:appcompat-v7:$supportVersion") { def supportVersion = '27.0.1'
implementation "com.android.support:support-v4:$supportVersion"
implementation("com.android.support:appcompat-v7:$supportVersion") {
exclude module: 'support-v4' exclude module: 'support-v4'
} }
compile("com.android.support:preference-v14:$supportVersion") { implementation("com.android.support:preference-v14:$supportVersion") {
exclude module: 'support-v4' exclude module: 'support-v4'
} }
compile("com.android.support:design:$supportVersion") { implementation("com.android.support:design:$supportVersion") {
exclude module: 'support-v4' exclude module: 'support-v4'
exclude module: 'recyclerview-v7' exclude module: 'recyclerview-v7'
} }
compile "com.android.support:cardview-v7:$supportVersion" implementation "com.android.support:cardview-v7:$supportVersion"
compile "com.android.support:support-annotations:$supportVersion" implementation "com.android.support:support-annotations:$supportVersion"
compile('ch.acra:acra:4.8.5') { implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation('ch.acra:acra:4.8.5') {
exclude module: 'support-v4' exclude module: 'support-v4'
exclude module: 'support-annotations' exclude module: 'support-annotations'
} }
compile 'info.guardianproject.panic:panic:0.5' implementation 'info.guardianproject.panic:panic:0.5'
compile 'info.guardianproject.trustedintents:trustedintents:0.2' implementation 'info.guardianproject.trustedintents:trustedintents:0.2'
compile 'de.hdodenhof:circleimageview:2.1.0' implementation 'de.hdodenhof:circleimageview:2.1.0'
compile 'com.google.zxing:core:3.3.0' implementation 'com.google.zxing:core:3.3.0'
compile 'com.jpardogo.materialtabstrip:library:1.1.0' implementation 'com.jpardogo.materialtabstrip:library:1.1.0'
compile 'com.github.bumptech.glide:glide:3.8.0' implementation 'com.github.bumptech.glide:glide:3.8.0'
compile 'uk.co.samuelwall:material-tap-target-prompt:1.9.2' implementation 'uk.co.samuelwall:material-tap-target-prompt:2.1.0'
provided 'javax.annotation:jsr250-api:1.0' annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
testCompile project(path: ':bramble-core', configuration: 'testOutput') compileOnly 'javax.annotation:jsr250-api:1.0'
testCompile 'org.robolectric:robolectric:3.0'
testCompile 'org.mockito:mockito-core:2.8.9' testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation project(path: ':bramble-core', configuration: 'testOutput')
testImplementation 'org.robolectric:robolectric:3.5.1'
testImplementation 'org.robolectric:shadows-support-v4:3.0'
testImplementation 'org.mockito:mockito-core:2.8.9'
testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation "org.hamcrest:hamcrest-library:1.3"
testImplementation "org.hamcrest:hamcrest-core:1.3"
} }
dependencyVerification { dependencyVerification {
verify = [ verify = [
'ch.acra:acra:afd5b28934d5166b55f261c85685ad59e8a4ebe9ca1960906afaa8c76d8dc9eb', 'android.arch.core:common:1.0.0:common-1.0.0.jar:5192934cd73df32e2c15722ed7fc488dde90baaec9ae030010dd1a80fb4e74e1',
'info.guardianproject.panic:panic:a7ed9439826db2e9901649892cf9afbe76f00991b768d8f4c26332d7c9406cb2', 'android.arch.lifecycle:common:1.0.0:common-1.0.0.jar:86bf301a20ad0cd0a391e22a52e6fbf90575c096ff83233fa9fd0d52b3219121',
'info.guardianproject.trustedintents:trustedintents:6221456d8821a8d974c2acf86306900237cf6afaaa94a4c9c44e161350f80f3e', 'android.arch.lifecycle:runtime:1.0.0:runtime-1.0.0.aar:e4e34e5d02bd102e8d39ddbc29f9ead8a15a61e367993d02238196ac48509ad8',
'de.hdodenhof:circleimageview:bcbc588e19e6dcf8c120b1957776bfe229efba5d2fbe5da7156372eeacf65503', 'backport-util-concurrent:backport-util-concurrent:3.1:backport-util-concurrent-3.1.jar:f5759b7fcdfc83a525a036deedcbd32e5b536b625ebc282426f16ca137eb5902',
'com.google.zxing:core:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.jpardogo.materialtabstrip:library:24d19232b319f8c73e25793432357919a7ed972186f57a3b2c9093ea74ad8311', 'ch.acra:acra:4.8.5:acra-4.8.5.aar:afd5b28934d5166b55f261c85685ad59e8a4ebe9ca1960906afaa8c76d8dc9eb',
'com.github.bumptech.glide:glide:750d9e7b940dc0ee48f8680623b55d46e14e8727acc922d7b156e57e7c549655', 'classworlds:classworlds:1.1-alpha-2:classworlds-1.1-alpha-2.jar:2bf4e59f3acd106fea6145a9a88fe8956509f8b9c0fdd11eb96fee757269e3f3',
'uk.co.samuelwall:material-tap-target-prompt:5d4951124366bc5c52e57beaa294db7611f0aa2a8d80e0163e1383e1966ba5b2', 'com.almworks.sqlite4java:sqlite4java:0.282:sqlite4java-0.282.jar:9e1d8dd83ca6003f841e3af878ce2dc7c22497493a7bb6d1b62ec1b0d0a83c05',
'com.android.support:appcompat-v7:00f9d93acacd6731f309724054bf51492814b4b2869f16d7d5c0038dcb8c9a0d', 'com.android.support.constraint:constraint-layout-solver:1.0.2:constraint-layout-solver-1.0.2.jar:8c62525a9bc5cff5633a96cb9b32fffeccaf41b8841aa87fc22607070dea9b8d',
'com.android.support:preference-v14:44881bb46094e86d0bc2426f205419674a5b4eb514b44b5a4659b5de29f71eb7', 'com.android.support.constraint:constraint-layout:1.0.2:constraint-layout-1.0.2.aar:b0c688cc2b7172608f8153a689d746da40f71e52d7e2fe2bfd9df2f92db77085',
'com.android.support:design:003e0c0bea0a6891f8b2bc43f20ae7af2a49a17363e5bb10df5ee0bae12fa686', 'com.android.support:animated-vector-drawable:27.0.1:animated-vector-drawable-27.0.1.aar:365050110411c86c7eec86101b49ab53557ffe6667f60b19055f1d35c38a577b',
'com.android.support:cardview-v7:4595f1c4a28cfa083b6c0920ad4d49e1c2ca4b8302a955e548f68eb63b74931b', 'com.android.support:appcompat-v7:27.0.1:appcompat-v7-27.0.1.aar:1402c29a49db30346c21a7d40634461765b3ab826f5dd95bc4dcc76787b21851',
'com.android.support:animated-vector-drawable:06d1963b85aa917099d7757e6a7b3e4dc06889413dc747f625ae8683606db3a1', 'com.android.support:cardview-v7:27.0.1:cardview-v7-27.0.1.aar:43fccd44086c51eaa9d78be2fcf0dfea1556c8876a6fd325ea8d24e860054202',
'com.android.support:support-vector-drawable:799bafe4c3de812386f0b291f744d5d6876452722dd40189b9ab87dbbf594ea1', 'com.android.support:design:27.0.1:design-27.0.1.aar:0e7c694bd5385e82d193e33b7289f769ce6ff05e277443daf5bffc3d852ef448',
'com.android.support:recyclerview-v7:44040a888e23e0c93162a3377cfe06751080e3c22d369ab0d4301ef60d63b0fe', 'com.android.support:preference-v14:27.0.1:preference-v14-27.0.1.aar:beed3ee97ae0d2541bd0adac6c84bb7d7b7580399f24e8efb9bc624161b164df',
'com.android.support:preference-v7:775101bd07bd052e455761c5c5d9523d7ad59f2f320e3e8cbde241fd6b1d6025', 'com.android.support:preference-v7:27.0.1:preference-v7-27.0.1.aar:d87ba6ae7c834fd68ef09cbc0f064975627ba14189dbef639c34080691366da9',
'com.android.support:recyclerview-v7:27.0.1:recyclerview-v7-27.0.1.aar:99ae2863287df800f239617d09cafc58b95f7a5365db32e3761394fa01ab12c9',
'com.android.support:support-annotations:27.0.1:support-annotations-27.0.1.jar:240912b779fe7413bdd97c94ac2a92d1fb29bd53c4d50c6982e5942b01278ac0',
'com.android.support:support-compat:27.0.1:support-compat-27.0.1.aar:70dfd92561421e5ae113dfc4045fc94c90caca9912839b3d08c793aa391aedcc',
'com.android.support:support-core-ui:27.0.1:support-core-ui-27.0.1.aar:91614f829f8a6f1fc2d28efc58ea2735212225ab02cdf768b3dd9af72371d5f0',
'com.android.support:support-core-utils:27.0.1:support-core-utils-27.0.1.aar:b33c5a5d67b8bfa6c8829875661779279157bf23e6042179820eaf1745034a72',
'com.android.support:support-fragment:27.0.1:support-fragment-27.0.1.aar:05a859783ae4a285c6d5c9865e1242b86f5bfb69a30455ca6c8495f24c09d9ed',
'com.android.support:support-media-compat:27.0.1:support-media-compat-27.0.1.aar:bc1c0252c1d071a1676fd280a792cf0717833fb3afd0ef73070ddc51ef921ad7',
'com.android.support:support-v4:27.0.1:support-v4-27.0.1.aar:afd802f1926475f40c5b6b42855c9a626a854298908dafdb455deb6dab2640f2',
'com.android.support:support-vector-drawable:27.0.1:support-vector-drawable-27.0.1.aar:67154ea191f735496502214bc6da6195738829a8e9d59e8042a1e030a2c7f19c',
'com.android.support:transition:27.0.1:transition-27.0.1.aar:8a46d152391bd1598d1778ae889b3aeaff77a17d0caaa29446df6e26a28c4e4b',
'com.github.bumptech.glide:glide:3.8.0:glide-3.8.0.jar:750d9e7b940dc0ee48f8680623b55d46e14e8727acc922d7b156e57e7c549655',
'com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:2.1:accessibility-test-framework-2.1.jar:7b0aa6ed7553597ce0610684a9f7eca8021eee218f2e2f427c04a7fbf5f920bd',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.google.guava:guava:20.0:guava-20.0.jar:36a666e3b71ae7f0f0dca23654b67e086e6c93d192f60ba5dfd5519db6c288c8',
'com.google.protobuf:protobuf-java:2.6.1:protobuf-java-2.6.1.jar:55aa554843983f431df5616112cf688d38aa17c132357afd1c109435bfdac4e6',
'com.google.zxing:core:3.3.0:core-3.3.0.jar:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.ibm.icu:icu4j:53.1:icu4j-53.1.jar:e37a4467bac5cdeb02c5c4b8e5063d2f4e67b69e3c7df6d6b610f13185572bab',
'com.jpardogo.materialtabstrip:library:1.1.0:library-1.1.0.aar:24d19232b319f8c73e25793432357919a7ed972186f57a3b2c9093ea74ad8311',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'com.rometools:rome-utils:1.7.3:rome-utils-1.7.3.jar:f774a80e7e1bc9db5426b62333ab362537f901636cd0812dc84cb5ee2668acf9',
'com.rometools:rome:1.7.3:rome-1.7.3.jar:077367bf8fa01b211c9da712c2aa862724195773c5693fd4d97d61d6457e96c6',
'com.squareup.okhttp3:okhttp:3.8.0:okhttp-3.8.0.jar:19e1db51787716ff0046fa19e408fb34ed32a6274baa0c07475bf724b4eb6800',
'com.squareup.okio:okio:1.13.0:okio-1.13.0.jar:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850',
'com.thoughtworks.xstream:xstream:1.4.8:xstream-1.4.8.jar:a219a1abf948400b669d08be73a6f9209fb720d237e5ff74c223bffe5f9df93d',
'de.hdodenhof:circleimageview:2.1.0:circleimageview-2.1.0.aar:bcbc588e19e6dcf8c120b1957776bfe229efba5d2fbe5da7156372eeacf65503',
'info.guardianproject.panic:panic:0.5:panic-0.5.jar:a7ed9439826db2e9901649892cf9afbe76f00991b768d8f4c26332d7c9406cb2',
'info.guardianproject.trustedintents:trustedintents:0.2:trustedintents-0.2.jar:6221456d8821a8d974c2acf86306900237cf6afaaa94a4c9c44e161350f80f3e',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'nekohtml:nekohtml:1.9.6.2:nekohtml-1.9.6.2.jar:fdff6cfa9ed9cc911c842a5d2395f209ec621ef1239d46810e9e495809d3ae09',
'nekohtml:xercesMinimal:1.9.6.2:xercesMinimal-1.9.6.2.jar:95b8b357d19f63797dd7d67622fd3f18374d64acbc6584faba1c7759a31e8438',
'net.bytebuddy:byte-buddy-agent:1.6.14:byte-buddy-agent-1.6.14.jar:c141a2d6809c3eeff4a43d25992826abccebdd4b793af3e7a5f346e88ae73a33',
'net.bytebuddy:byte-buddy:1.6.14:byte-buddy-1.6.14.jar:917758b3c651e278a15a029ba1d42dbf802d8b0e1fe2aa4b81c5750c64f461c1',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.apache.maven.wagon:wagon-file:1.0-beta-6:wagon-file-1.0-beta-6.jar:7298feeb36ff14dd933c38e62585fb9973fea32fb3c4bc5379428cb1aac5dd3c',
'org.apache.maven.wagon:wagon-http-lightweight:1.0-beta-6:wagon-http-lightweight-1.0-beta-6.jar:be214032de23c6b520b79c1ccdb160948e0c67ed7c11984b7ec4ca5537867b4e',
'org.apache.maven.wagon:wagon-http-shared:1.0-beta-6:wagon-http-shared-1.0-beta-6.jar:f095c882716d49269a806685dcb256fa6a36389b2713ac56bb758bf8693565a2',
'org.apache.maven.wagon:wagon-provider-api:1.0-beta-6:wagon-provider-api-1.0-beta-6.jar:e116f32edcb77067289a3148143f2c0c97b27cf9a1342f8108ee37dec4868861',
'org.apache.maven:maven-ant-tasks:2.1.3:maven-ant-tasks-2.1.3.jar:f16b5ea711dfe0323454b880180aa832420ec039936e4aa75fb978748634808a',
'org.apache.maven:maven-artifact-manager:2.2.1:maven-artifact-manager-2.2.1.jar:d1e247c4ed3952385fd704ac9db2a222247cfe7d20508b4f3c76b90f857952ed',
'org.apache.maven:maven-artifact:2.2.1:maven-artifact-2.2.1.jar:d53062ffe8677a4f5e1ad3a1d1fa37ed600fab39166d39be7ed204635c5f839b',
'org.apache.maven:maven-error-diagnostics:2.2.1:maven-error-diagnostics-2.2.1.jar:b3005544708f8583e455c22b09a4940596a057108bccdadb9db4d8e048091fed',
'org.apache.maven:maven-model:2.2.1:maven-model-2.2.1.jar:153b32f474fd676ec36ad807c508885005139140fc92168bb76bf6be31f8efb8',
'org.apache.maven:maven-plugin-registry:2.2.1:maven-plugin-registry-2.2.1.jar:4ad0673155d7e0e5cf6d13689802d8d507f38e5ea00a6d2fb92aef206108213d',
'org.apache.maven:maven-profile:2.2.1:maven-profile-2.2.1.jar:ecaffef655fea6b138f0855a12f7dbb59fc0d6bffb5c1bfd31803cccb49ea08c',
'org.apache.maven:maven-project:2.2.1:maven-project-2.2.1.jar:24ddb65b7a6c3befb6267ce5f739f237c84eba99389265c30df67c3dd8396a40',
'org.apache.maven:maven-repository-metadata:2.2.1:maven-repository-metadata-2.2.1.jar:5fe283f47b0e7f7d95a4252af3fa7a0db4d8f080cd9df308608c0472b8f168a1',
'org.apache.maven:maven-settings:2.2.1:maven-settings-2.2.1.jar:9a9f556713a404e770c9dbdaed7eb086078014c989291960c76fdde6db4192f7',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.bouncycastle:bcprov-jdk15on:1.52:bcprov-jdk15on-1.52.jar:0dc4d181e4d347893c2ddbd2e6cd5d7287fc651c03648fa64b2341c7366b1773',
'org.codehaus.plexus:plexus-container-default:1.0-alpha-9-stable-1:plexus-container-default-1.0-alpha-9-stable-1.jar:7c758612888782ccfe376823aee7cdcc7e0cdafb097f7ef50295a0b0c3a16edf',
'org.codehaus.plexus:plexus-interpolation:1.11:plexus-interpolation-1.11.jar:fd9507feb858fa620d1b4aa4b7039fdea1a77e09d3fd28cfbddfff468d9d8c28',
'org.codehaus.plexus:plexus-utils:1.5.15:plexus-utils-1.5.15.jar:2ca121831e597b4d8f2cb22d17c5c041fc23a7777ceb6bfbdd4dfb34bbe7d997',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jacoco:org.jacoco.agent:0.7.4.201502262128:org.jacoco.agent-0.7.4.201502262128-runtime.jar:e357a0f1d573c2f702a273992b1b6cb661734f66311854efb3778a888515c5b5',
'org.jacoco:org.jacoco.agent:0.7.4.201502262128:org.jacoco.agent-0.7.4.201502262128.jar:47b4bec6df11a1118da3953da8b9fa1e7079d6fec857faa1a3cf912e53a6fd4e',
'org.jacoco:org.jacoco.ant:0.7.4.201502262128:org.jacoco.ant-0.7.4.201502262128.jar:013ce2a68ba57a3c59215ae0dec4df3498c078062a38c3b94c841fc14450f283',
'org.jacoco:org.jacoco.core:0.7.4.201502262128:org.jacoco.core-0.7.4.201502262128.jar:ec4c74554312fac5116350164786f91b35c9e082fa4ea598bfa42b5db05d7abb',
'org.jacoco:org.jacoco.report:0.7.4.201502262128:org.jacoco.report-0.7.4.201502262128.jar:7a3554c605e088e7e323b1084656243f0444fa353e2f2dee1f1a4204eb64ff09',
'org.jdom:jdom2:2.0.6:jdom2-2.0.6.jar:1345f11ba606d15603d6740551a8c21947c0215640770ec67271fe78bea97cf5',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.jsoup:jsoup:1.10.3:jsoup-1.10.3.jar:a0784e793d7f518eb1defb47b428da011cd483c5da32d49c569bf491e4f1579a',
'org.mockito:mockito-core:2.8.9:mockito-core-2.8.9.jar:a2bb9b8b40d81bb02ccb84259524c0f4911f73c6577bfc7ddd940b8fc729b6e6',
'org.objenesis:objenesis:2.5:objenesis-2.5.jar:293328e1b0d31ed30bb89fca542b6c52fac00989bb0e62eb9d98d630c4dd6b7c',
'org.ow2.asm:asm-commons:5.0.1:asm-commons-5.0.1.jar:fb1cb7fa27d892712ced8fbf8d027eb5052ecd3999dba1ba47824357accb40e7',
'org.ow2.asm:asm-debug-all:5.0.1:asm-debug-all-5.0.1.jar:4734de5b515a454b0096db6971fb068e5f70e6f10bbee2b3bd2fdfe5d978ed57',
'org.ow2.asm:asm-tree:5.0.1:asm-tree-5.0.1.jar:ff2aceed10da9930a44f6c8f81c6372d5e55eb59c4e0ea9d37f77dfd765fa9fa',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.robolectric:annotations:3.5.1:annotations-3.5.1.jar:14db0f7d2299c5400ff7764bb37b4fa80306582d8965fdf6999091723e2384ce',
'org.robolectric:junit:3.5.1:junit-3.5.1.jar:b2e81b7d5a22755f2ea76aa9bbbd4359d61c4cb9577193ccfbb8f97378ed293b',
'org.robolectric:resources:3.5.1:resources-3.5.1.jar:22a5564590c8bfd8df7efb2b0c7d9942b46a0beb59ba38899d59c1270f293b1c',
'org.robolectric:robolectric:3.5.1:robolectric-3.5.1.jar:603cf898f93b854f18021fab452aca3fe482368eeb2e720988ae82212ebcf4b6',
'org.robolectric:sandbox:3.5.1:sandbox-3.5.1.jar:beff8c3c1e840e0f7f78aadef170f347bae349f098babfc176765f499a4bcbb5',
'org.robolectric:shadowapi:3.5.1:shadowapi-3.5.1.jar:6d574f9ae0922791eb8f06979f0010997d4b862c7aec96d485ae797ddfc13278',
'org.robolectric:shadows-framework:3.5.1:shadows-framework-3.5.1.jar:597b54cc1a494799d783921c6ac04352f33e94fca8e00f299d4ca192db79e3fc',
'org.robolectric:shadows-support-v4:3.0:shadows-support-v4-3.0.jar:66bcc3257b037d72998e860d67b1bc58215b7eeac8ad860fcc3e613332d88619',
'org.robolectric:utils:3.5.1:utils-3.5.1.jar:d7d77326867e6d903156ebb18c244819b26aebe3aa82a1c57081081a0b6c4f63',
'org.slf4j:slf4j-api:1.7.16:slf4j-api-1.7.16.jar:e56288031f5e60652c06e7bb6e9fa410a61231ab54890f7b708fc6adc4107c5b',
'uk.co.samuelwall:material-tap-target-prompt:2.1.0:material-tap-target-prompt-2.1.0.aar:6df17e7c371f9264bfe440506f91205dd47566869c1528891943a04a26c96a94',
'xmlpull:xmlpull:1.1.3.1:xmlpull-1.1.3.1.jar:34e08ee62116071cbb69c0ed70d15a7a5b208d62798c59f2120bb8929324cb63',
'xpp3:xpp3_min:1.1.4c:xpp3_min-1.1.4c.jar:bfc90e9e32d0eab1f397fb974b5f150a815188382ac41f372a7149d5bc178008',
] ]
} }
@@ -72,14 +179,14 @@ def getGitHash = { ->
} }
android { android {
compileSdkVersion 23 compileSdkVersion 27
buildToolsVersion "23.0.3" buildToolsVersion '26.0.2'
defaultConfig { defaultConfig {
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 22 targetSdkVersion 26
versionCode 1611 versionCode 1612
versionName "0.16.11" versionName "0.16.12"
applicationId "org.briarproject.briar.beta" applicationId "org.briarproject.briar.beta"
resValue "string", "app_package", "org.briarproject.briar.beta" resValue "string", "app_package", "org.briarproject.briar.beta"
resValue "string", "app_name", "Briar Beta" resValue "string", "app_name", "Briar Beta"
@@ -103,8 +210,14 @@ android {
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_8
}
testOptions {
unitTests {
includeAndroidResources = true
}
} }
aaptOptions { aaptOptions {

View File

@@ -15,6 +15,7 @@
<uses-permission android:name="android.permission.READ_LOGS"/> <uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<application <application
android:name="org.briarproject.briar.android.BriarApplicationImpl" android:name="org.briarproject.briar.android.BriarApplicationImpl"

View File

@@ -26,6 +26,7 @@ import org.briarproject.briar.BriarCoreEagerSingletons;
import org.briarproject.briar.BriarCoreModule; import org.briarproject.briar.BriarCoreModule;
import org.briarproject.briar.android.reporting.BriarReportSender; import org.briarproject.briar.android.reporting.BriarReportSender;
import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.android.DozeWatchdog;
import org.briarproject.briar.api.android.ScreenFilterMonitor; import org.briarproject.briar.api.android.ScreenFilterMonitor;
import org.briarproject.briar.api.blog.BlogManager; import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.blog.BlogPostFactory; import org.briarproject.briar.api.blog.BlogPostFactory;
@@ -140,6 +141,8 @@ public interface AndroidComponent
TestDataCreator testDataCreator(); TestDataCreator testDataCreator();
DozeWatchdog dozeWatchdog();
@IoExecutor @IoExecutor
Executor ioExecutor(); Executor ioExecutor();

View File

@@ -44,7 +44,6 @@ import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@@ -138,16 +137,13 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void stopService() throws ServiceException { public void stopService() throws ServiceException {
// Clear all notifications // Clear all notifications
Future<Void> f = androidExecutor.runOnUiThread(new Callable<Void>() { Future<Void> f = androidExecutor.runOnUiThread(() -> {
@Override clearContactNotification();
public Void call() { clearGroupMessageNotification();
clearContactNotification(); clearForumPostNotification();
clearGroupMessageNotification(); clearBlogPostNotification();
clearForumPostNotification(); clearIntroductionSuccessNotification();
clearBlogPostNotification(); return null;
clearIntroductionSuccessNotification();
return null;
}
}); });
try { try {
f.get(); f.get();
@@ -236,44 +232,35 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
} }
private void loadSettings() { private void loadSettings() {
dbExecutor.execute(new Runnable() { dbExecutor.execute(() -> {
@Override try {
public void run() { settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
try { } catch (DbException e) {
settings = settingsManager.getSettings(SETTINGS_NAMESPACE); if (LOG.isLoggable(WARNING))
} catch (DbException e) { LOG.log(WARNING, e.toString(), e);
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
}
} }
}); });
} }
private void showContactNotification(final ContactId c) { private void showContactNotification(ContactId c) {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(() -> {
@Override if (blockContacts) return;
public void run() { if (c.equals(blockedContact)) return;
if (blockContacts) return; Integer count = contactCounts.get(c);
if (c.equals(blockedContact)) return; if (count == null) contactCounts.put(c, 1);
Integer count = contactCounts.get(c); else contactCounts.put(c, count + 1);
if (count == null) contactCounts.put(c, 1); contactTotal++;
else contactCounts.put(c, count + 1); updateContactNotification(true);
contactTotal++;
updateContactNotification(true);
}
}); });
} }
@Override @Override
public void clearContactNotification(final ContactId c) { public void clearContactNotification(ContactId c) {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(() -> {
@Override Integer count = contactCounts.remove(c);
public void run() { if (count == null) return; // Already cleared
Integer count = contactCounts.remove(c); contactTotal -= count;
if (count == null) return; // Already cleared updateContactNotification(false);
contactTotal -= count;
updateContactNotification(false);
}
}); });
} }
@@ -358,40 +345,30 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void clearAllContactNotifications() { public void clearAllContactNotifications() {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(
@Override (Runnable) this::clearContactNotification);
public void run() {
clearContactNotification();
}
});
} }
@UiThread @UiThread
private void showGroupMessageNotification(final GroupId g) { private void showGroupMessageNotification(GroupId g) {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(() -> {
@Override if (blockGroups) return;
public void run() { if (g.equals(blockedGroup)) return;
if (blockGroups) return; Integer count = groupCounts.get(g);
if (g.equals(blockedGroup)) return; if (count == null) groupCounts.put(g, 1);
Integer count = groupCounts.get(g); else groupCounts.put(g, count + 1);
if (count == null) groupCounts.put(g, 1); groupTotal++;
else groupCounts.put(g, count + 1); updateGroupMessageNotification(true);
groupTotal++;
updateGroupMessageNotification(true);
}
}); });
} }
@Override @Override
public void clearGroupMessageNotification(final GroupId g) { public void clearGroupMessageNotification(GroupId g) {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(() -> {
@Override Integer count = groupCounts.remove(g);
public void run() { if (count == null) return; // Already cleared
Integer count = groupCounts.remove(g); groupTotal -= count;
if (count == null) return; // Already cleared updateGroupMessageNotification(false);
groupTotal -= count;
updateGroupMessageNotification(false);
}
}); });
} }
@@ -445,40 +422,30 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void clearAllGroupMessageNotifications() { public void clearAllGroupMessageNotifications() {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(
@Override (Runnable) this::clearGroupMessageNotification);
public void run() {
clearGroupMessageNotification();
}
});
} }
@UiThread @UiThread
private void showForumPostNotification(final GroupId g) { private void showForumPostNotification(GroupId g) {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(() -> {
@Override if (blockForums) return;
public void run() { if (g.equals(blockedGroup)) return;
if (blockForums) return; Integer count = forumCounts.get(g);
if (g.equals(blockedGroup)) return; if (count == null) forumCounts.put(g, 1);
Integer count = forumCounts.get(g); else forumCounts.put(g, count + 1);
if (count == null) forumCounts.put(g, 1); forumTotal++;
else forumCounts.put(g, count + 1); updateForumPostNotification(true);
forumTotal++;
updateForumPostNotification(true);
}
}); });
} }
@Override @Override
public void clearForumPostNotification(final GroupId g) { public void clearForumPostNotification(GroupId g) {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(() -> {
@Override Integer count = forumCounts.remove(g);
public void run() { if (count == null) return; // Already cleared
Integer count = forumCounts.remove(g); forumTotal -= count;
if (count == null) return; // Already cleared updateForumPostNotification(false);
forumTotal -= count;
updateForumPostNotification(false);
}
}); });
} }
@@ -532,40 +499,30 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void clearAllForumPostNotifications() { public void clearAllForumPostNotifications() {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(
@Override (Runnable) this::clearForumPostNotification);
public void run() {
clearForumPostNotification();
}
});
} }
@UiThread @UiThread
private void showBlogPostNotification(final GroupId g) { private void showBlogPostNotification(GroupId g) {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(() -> {
@Override if (blockBlogs) return;
public void run() { if (g.equals(blockedGroup)) return;
if (blockBlogs) return; Integer count = blogCounts.get(g);
if (g.equals(blockedGroup)) return; if (count == null) blogCounts.put(g, 1);
Integer count = blogCounts.get(g); else blogCounts.put(g, count + 1);
if (count == null) blogCounts.put(g, 1); blogTotal++;
else blogCounts.put(g, count + 1); updateBlogPostNotification(true);
blogTotal++;
updateBlogPostNotification(true);
}
}); });
} }
@Override @Override
public void clearBlogPostNotification(final GroupId g) { public void clearBlogPostNotification(GroupId g) {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(() -> {
@Override Integer count = blogCounts.remove(g);
public void run() { if (count == null) return; // Already cleared
Integer count = blogCounts.remove(g); blogTotal -= count;
if (count == null) return; // Already cleared updateBlogPostNotification(false);
blogTotal -= count;
updateBlogPostNotification(false);
}
}); });
} }
@@ -606,22 +563,15 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void clearAllBlogPostNotifications() { public void clearAllBlogPostNotifications() {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(
@Override (Runnable) this::clearBlogPostNotification);
public void run() {
clearBlogPostNotification();
}
});
} }
private void showIntroductionNotification() { private void showIntroductionNotification() {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(() -> {
@Override if (blockIntroductions) return;
public void run() { introductionTotal++;
if (blockIntroductions) return; updateIntroductionNotification();
introductionTotal++;
updateIntroductionNotification();
}
}); });
} }
@@ -656,71 +606,41 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void clearAllIntroductionNotifications() { public void clearAllIntroductionNotifications() {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(
@Override this::clearIntroductionSuccessNotification);
public void run() { }
clearIntroductionSuccessNotification();
} @Override
public void blockNotification(GroupId g) {
androidExecutor.runOnUiThread((Runnable) () -> blockedGroup = g);
}
@Override
public void unblockNotification(GroupId g) {
androidExecutor.runOnUiThread(() -> {
if (g.equals(blockedGroup)) blockedGroup = null;
}); });
} }
@Override @Override
public void blockNotification(final GroupId g) { public void blockContactNotification(ContactId c) {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread((Runnable) () -> blockedContact = c);
@Override
public void run() {
blockedGroup = g;
}
});
} }
@Override @Override
public void unblockNotification(final GroupId g) { public void unblockContactNotification(ContactId c) {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread(() -> {
@Override if (c.equals(blockedContact)) blockedContact = null;
public void run() {
if (g.equals(blockedGroup)) blockedGroup = null;
}
});
}
@Override
public void blockContactNotification(final ContactId c) {
androidExecutor.runOnUiThread(new Runnable() {
@Override
public void run() {
blockedContact = c;
}
});
}
@Override
public void unblockContactNotification(final ContactId c) {
androidExecutor.runOnUiThread(new Runnable() {
@Override
public void run() {
if (c.equals(blockedContact)) blockedContact = null;
}
}); });
} }
@Override @Override
public void blockAllBlogPostNotifications() { public void blockAllBlogPostNotifications() {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread((Runnable) () -> blockBlogs = true);
@Override
public void run() {
blockBlogs = true;
}
});
} }
@Override @Override
public void unblockAllBlogPostNotifications() { public void unblockAllBlogPostNotifications() {
androidExecutor.runOnUiThread(new Runnable() { androidExecutor.runOnUiThread((Runnable) () -> blockBlogs = false);
@Override
public void run() {
blockBlogs = false;
}
});
} }
} }

Some files were not shown because too many files have changed in this diff Show More