Skip to content

Commit 33eb12b

Browse files
Server options: create server using new FlatBuffer based options
Also add some API docs.
1 parent 89b2ff9 commit 33eb12b

File tree

4 files changed

+140
-36
lines changed

4 files changed

+140
-36
lines changed

objectbox-java/src/main/java/io/objectbox/BoxStoreBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ public BoxStoreBuilder initialDbFile(Factory<InputStream> initialDbFileFactory)
569569

570570
byte[] buildFlatStoreOptions(String canonicalPath) {
571571
FlatBufferBuilder fbb = new FlatBufferBuilder();
572-
// FlatBuffer default values are set in generated code, e.g. may be different from here, so always store value.
572+
// Always put values, even if they match the default values (defined in the generated classes)
573573
fbb.forceDefaults(true);
574574

575575
// Add non-integer values first...

objectbox-java/src/main/java/io/objectbox/sync/server/PeerInfo.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2020 ObjectBox Ltd. All rights reserved.
2+
* Copyright 2019-2024 ObjectBox Ltd. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,15 +16,18 @@
1616

1717
package io.objectbox.sync.server;
1818

19-
import io.objectbox.annotation.apihint.Experimental;
20-
import io.objectbox.sync.SyncCredentials;
19+
import io.objectbox.annotation.apihint.Internal;
20+
import io.objectbox.sync.SyncCredentialsToken;
2121

22-
@Experimental
22+
/**
23+
* Internal class to keep configuration for a cluster peer.
24+
*/
25+
@Internal
2326
class PeerInfo {
2427
String url;
25-
SyncCredentials credentials;
28+
SyncCredentialsToken credentials;
2629

27-
PeerInfo(String url, SyncCredentials credentials) {
30+
PeerInfo(String url, SyncCredentialsToken credentials) {
2831
this.url = url;
2932
this.credentials = credentials;
3033
}

objectbox-java/src/main/java/io/objectbox/sync/server/SyncServerBuilder.java

Lines changed: 119 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,25 @@
2323

2424
import io.objectbox.BoxStore;
2525
import io.objectbox.annotation.apihint.Experimental;
26+
import io.objectbox.flatbuffers.FlatBufferBuilder;
27+
import io.objectbox.sync.Credentials;
2628
import io.objectbox.sync.SyncCredentials;
29+
import io.objectbox.sync.SyncCredentialsToken;
2730
import io.objectbox.sync.listener.SyncChangeListener;
2831

2932
/**
3033
* Creates a {@link SyncServer} and allows to set additional configuration.
3134
*/
32-
@SuppressWarnings({"unused", "UnusedReturnValue", "WeakerAccess"})
35+
@SuppressWarnings({"unused", "UnusedReturnValue"})
3336
@Experimental
3437
public class SyncServerBuilder {
3538

3639
final BoxStore boxStore;
3740
final String url;
38-
final List<SyncCredentials> credentials = new ArrayList<>();
41+
private final List<SyncCredentialsToken> credentials = new ArrayList<>();
3942
final List<PeerInfo> peers = new ArrayList<>();
4043

41-
@Nullable String certificatePath;
44+
private @Nullable String certificatePath;
4245
SyncChangeListener changeListener;
4346

4447
public SyncServerBuilder(BoxStore boxStore, String url, SyncCredentials authenticatorCredentials) {
@@ -55,7 +58,14 @@ public SyncServerBuilder(BoxStore boxStore, String url, SyncCredentials authenti
5558
authenticatorCredentials(authenticatorCredentials);
5659
}
5760

61+
/**
62+
* Sets the path to a directory that contains a cert.pem and key.pem file to use to establish encrypted
63+
* connections.
64+
* <p>
65+
* Use the "wss://" protocol for the server URL to turn on encrypted connections.
66+
*/
5867
public SyncServerBuilder certificatePath(String certificatePath) {
68+
checkNotNull(certificatePath, "Certificate path must not be null");
5969
this.certificatePath = certificatePath;
6070
return this;
6171
}
@@ -68,7 +78,11 @@ public SyncServerBuilder certificatePath(String certificatePath) {
6878
*/
6979
public SyncServerBuilder authenticatorCredentials(SyncCredentials authenticatorCredentials) {
7080
checkNotNull(authenticatorCredentials, "Authenticator credentials must not be null.");
71-
credentials.add(authenticatorCredentials);
81+
if (!(authenticatorCredentials instanceof SyncCredentialsToken)) {
82+
throw new IllegalArgumentException("Sync credentials of type " + authenticatorCredentials.getType()
83+
+ " are not supported");
84+
}
85+
credentials.add((SyncCredentialsToken) authenticatorCredentials);
7286
return this;
7387
}
7488

@@ -94,7 +108,11 @@ public SyncServerBuilder peer(String url) {
94108
* Adds a server peer, to which this server should connect to as a client using the given credentials.
95109
*/
96110
public SyncServerBuilder peer(String url, SyncCredentials credentials) {
97-
peers.add(new PeerInfo(url, credentials));
111+
if (!(credentials instanceof SyncCredentialsToken)) {
112+
throw new IllegalArgumentException("Sync credentials of type " + credentials.getType()
113+
+ " are not supported");
114+
}
115+
peers.add(new PeerInfo(url, (SyncCredentialsToken) credentials));
98116
return this;
99117
}
100118

@@ -125,4 +143,100 @@ private void checkNotNull(Object object, String message) {
125143
}
126144
}
127145

146+
/**
147+
* From this configuration, builds a {@link SyncServerOptions} FlatBuffer and returns it as bytes.
148+
* <p>
149+
* Clears configured credentials, they can not be used again after this returns.
150+
*/
151+
byte[] buildSyncServerOptions() {
152+
FlatBufferBuilder fbb = new FlatBufferBuilder();
153+
// Always put values, even if they match the default values (defined in the generated classes)
154+
fbb.forceDefaults(true);
155+
156+
// Serialize non-integer values first to get their offset
157+
int urlOffset = fbb.createString(url);
158+
int certificatePathOffset = 0;
159+
if (certificatePath != null) {
160+
certificatePathOffset = fbb.createString(certificatePath);
161+
}
162+
int authenticationMethodsOffset = buildAuthenticationMethods(fbb);
163+
int clusterPeersVectorOffset = buildClusterPeers(fbb);
164+
165+
// TODO Support remaining options
166+
// After collecting all offsets, create options
167+
SyncServerOptions.startSyncServerOptions(fbb);
168+
SyncServerOptions.addUrl(fbb, urlOffset);
169+
SyncServerOptions.addAuthenticationMethods(fbb, authenticationMethodsOffset);
170+
// SyncServerOptions.addSyncFlags();
171+
// SyncServerOptions.addSyncServerFlags();
172+
if (certificatePathOffset > 0) {
173+
SyncServerOptions.addCertificatePath(fbb, certificatePathOffset);
174+
}
175+
// SyncServerOptions.addWorkerThreads();
176+
// SyncServerOptions.addHistorySizeMaxKb();
177+
// SyncServerOptions.addHistorySizeTargetKb();
178+
// SyncServerOptions.addAdminUrl();
179+
// SyncServerOptions.addAdminThreads();
180+
// SyncServerOptions.addClusterId();
181+
if (clusterPeersVectorOffset > 0) {
182+
SyncServerOptions.addClusterPeers(fbb, clusterPeersVectorOffset);
183+
}
184+
// SyncServerOptions.addClusterFlags();
185+
int offset = SyncServerOptions.endSyncServerOptions(fbb);
186+
fbb.finish(offset);
187+
188+
return fbb.sizedByteArray();
189+
}
190+
191+
private int buildAuthenticationMethods(FlatBufferBuilder fbb) {
192+
int[] credentialsOffsets = new int[credentials.size()];
193+
for (int i = 0; i < credentials.size(); i++) {
194+
credentialsOffsets[i] = buildCredentials(fbb, credentials.get(i));
195+
}
196+
return SyncServerOptions.createAuthenticationMethodsVector(fbb, credentialsOffsets);
197+
}
198+
199+
private int buildCredentials(FlatBufferBuilder fbb, SyncCredentialsToken tokenCredentials) {
200+
int tokenBytesOffset = 0;
201+
byte[] tokenBytes = tokenCredentials.getTokenBytes();
202+
if (tokenBytes != null) {
203+
tokenBytesOffset = Credentials.createBytesVector(fbb, tokenBytes);
204+
}
205+
206+
Credentials.startCredentials(fbb);
207+
// TODO Will this still be necessary?
208+
// The core API used by nativeSetAuthenticator only supports the NONE and SHARED_SECRET types
209+
// (however, protocol v3 versions do also add SHARED_SECRET_SIPPED if SHARED_SECRET is given).
210+
final SyncCredentials.CredentialsType type = tokenCredentials.getType() == SyncCredentials.CredentialsType.SHARED_SECRET_SIPPED
211+
? SyncCredentials.CredentialsType.SHARED_SECRET
212+
: tokenCredentials.getType();
213+
Credentials.addType(fbb, type.id);
214+
if (tokenBytesOffset > 0) {
215+
Credentials.addBytes(fbb, tokenBytesOffset);
216+
}
217+
int credentialsOffset = Credentials.endCredentials(fbb);
218+
219+
tokenCredentials.clear(); // Clear immediately, not needed anymore.
220+
221+
return credentialsOffset;
222+
}
223+
224+
private int buildClusterPeers(FlatBufferBuilder fbb) {
225+
if (peers.isEmpty()) {
226+
return 0;
227+
}
228+
229+
int[] peersOffsets = new int[peers.size()];
230+
for (int i = 0; i < peers.size(); i++) {
231+
PeerInfo peer = peers.get(i);
232+
233+
int urlOffset = fbb.createString(peer.url);
234+
int credentialsOffset = buildCredentials(fbb, peer.credentials);
235+
236+
peersOffsets[i] = ClusterPeerConfig.createClusterPeerConfig(fbb, urlOffset, credentialsOffset);
237+
}
238+
239+
return SyncServerOptions.createClusterPeersVector(fbb, peersOffsets);
240+
}
241+
128242
}

objectbox-java/src/main/java/io/objectbox/sync/server/SyncServerImpl.java

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919
import javax.annotation.Nullable;
2020

2121
import io.objectbox.annotation.apihint.Internal;
22-
import io.objectbox.sync.SyncCredentials;
23-
import io.objectbox.sync.SyncCredentials.CredentialsType;
24-
import io.objectbox.sync.SyncCredentialsToken;
2522
import io.objectbox.sync.listener.SyncChangeListener;
2623

2724
/**
@@ -34,38 +31,23 @@ public class SyncServerImpl implements SyncServer {
3431
private final String url;
3532
private volatile long handle;
3633

34+
/**
35+
* Protects listener instance from garbage collection.
36+
*/
37+
@SuppressWarnings("unused")
3738
@Nullable
3839
private volatile SyncChangeListener syncChangeListener;
3940

4041
SyncServerImpl(SyncServerBuilder builder) {
4142
this.url = builder.url;
4243

4344
long storeHandle = builder.boxStore.getNativeStore();
44-
long handle = nativeCreate(storeHandle, url, builder.certificatePath);
45+
long handle = nativeCreateFromFlatOptions(storeHandle, builder.buildSyncServerOptions());
4546
if (handle == 0) {
4647
throw new RuntimeException("Failed to create sync server: handle is zero.");
4748
}
4849
this.handle = handle;
4950

50-
for (SyncCredentials credentials : builder.credentials) {
51-
if (!(credentials instanceof SyncCredentialsToken)) {
52-
throw new IllegalArgumentException("Sync credentials of type " + credentials.getType() + " are not supported");
53-
}
54-
SyncCredentialsToken credentialsInternal = (SyncCredentialsToken) credentials;
55-
// The core API used by nativeSetAuthenticator only supports the NONE and SHARED_SECRET types
56-
// (however, protocol v3 versions do also add SHARED_SECRET_SIPPED if SHARED_SECRET is given).
57-
final CredentialsType type = credentialsInternal.getType() == CredentialsType.SHARED_SECRET_SIPPED
58-
? CredentialsType.SHARED_SECRET
59-
: credentialsInternal.getType();
60-
nativeSetAuthenticator(handle, type.id, credentialsInternal.getTokenBytes());
61-
credentialsInternal.clear(); // Clear immediately, not needed anymore.
62-
}
63-
64-
for (PeerInfo peer : builder.peers) {
65-
SyncCredentialsToken credentialsInternal = (SyncCredentialsToken) peer.credentials;
66-
nativeAddPeer(handle, peer.url, credentialsInternal.getTypeId(), credentialsInternal.getTokenBytes());
67-
}
68-
6951
if (builder.changeListener != null) {
7052
setSyncChangeListener(builder.changeListener);
7153
}
@@ -134,7 +116,12 @@ protected void finalize() throws Throwable {
134116
super.finalize();
135117
}
136118

137-
private static native long nativeCreate(long storeHandle, String uri, @Nullable String certificatePath);
119+
/**
120+
* Creates a native Sync server instance with FlatBuffer {@link SyncServerOptions} {@code flatOptionsByteArray}.
121+
*
122+
* @return The handle of the native server instance.
123+
*/
124+
private static native long nativeCreateFromFlatOptions(long storeHandle, byte[] flatOptionsByteArray);
138125

139126
private native void nativeDelete(long handle);
140127

0 commit comments

Comments
 (0)