2323
2424import io .objectbox .BoxStore ;
2525import io .objectbox .annotation .apihint .Experimental ;
26+ import io .objectbox .flatbuffers .FlatBufferBuilder ;
27+ import io .objectbox .sync .Credentials ;
2628import io .objectbox .sync .SyncCredentials ;
29+ import io .objectbox .sync .SyncCredentialsToken ;
2730import 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
3437public 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}
0 commit comments