All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.objectbox.sync.server.SyncServerImpl Maven / Gradle / Ivy

There is a newer version: 4.0.3
Show newest version
/*
 * Copyright 2019-2024 ObjectBox Ltd. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.objectbox.sync.server;

import javax.annotation.Nullable;

import io.objectbox.annotation.apihint.Internal;
import io.objectbox.sync.SyncCredentials;
import io.objectbox.sync.SyncCredentials.CredentialsType;
import io.objectbox.sync.SyncCredentialsToken;
import io.objectbox.sync.listener.SyncChangeListener;

/**
 * Internal sync server implementation. Use {@link SyncServer} to access functionality,
 * this class may change without notice.
 */
@Internal
public class SyncServerImpl implements SyncServer {

    private final String url;
    private volatile long handle;

    @Nullable
    private volatile SyncChangeListener syncChangeListener;

    SyncServerImpl(SyncServerBuilder builder) {
        this.url = builder.url;

        long storeHandle = builder.boxStore.getNativeStore();
        long handle = nativeCreate(storeHandle, url, builder.certificatePath);
        if (handle == 0) {
            throw new RuntimeException("Failed to create sync server: handle is zero.");
        }
        this.handle = handle;

        for (SyncCredentials credentials : builder.credentials) {
            if (!(credentials instanceof SyncCredentialsToken)) {
                throw new IllegalArgumentException("Sync credentials of type " + credentials.getType() + " are not supported");
            }
            SyncCredentialsToken credentialsInternal = (SyncCredentialsToken) credentials;
            // The core API used by nativeSetAuthenticator only supports the NONE and SHARED_SECRET types
            // (however, protocol v3 versions do also add SHARED_SECRET_SIPPED if SHARED_SECRET is given).
            final CredentialsType type = credentialsInternal.getType() == CredentialsType.SHARED_SECRET_SIPPED
                    ? CredentialsType.SHARED_SECRET
                    : credentialsInternal.getType();
            nativeSetAuthenticator(handle, type.id, credentialsInternal.getTokenBytes());
            credentialsInternal.clear(); // Clear immediately, not needed anymore.
        }

        for (PeerInfo peer : builder.peers) {
            SyncCredentialsToken credentialsInternal = (SyncCredentialsToken) peer.credentials;
            nativeAddPeer(handle, peer.url, credentialsInternal.getTypeId(), credentialsInternal.getTokenBytes());
        }

        if (builder.changeListener != null) {
            setSyncChangeListener(builder.changeListener);
        }
    }

    private long getHandle() {
        long handle = this.handle;
        if (handle == 0) {
            throw new IllegalStateException("SyncServer already closed");
        }
        return handle;
    }

    @Override
    public String getUrl() {
        return url;
    }

    @Override
    public int getPort() {
        return nativeGetPort(getHandle());
    }

    @Override
    public boolean isRunning() {
        return nativeIsRunning(getHandle());
    }

    @Override
    public String getStatsString() {
        return nativeGetStatsString(getHandle());
    }

    @Override
    public void setSyncChangeListener(@Nullable SyncChangeListener changesListener) {
        this.syncChangeListener = changesListener;
        nativeSetSyncChangesListener(getHandle(), changesListener);
    }

    @Override
    public void start() {
        nativeStart(getHandle());
    }

    @Override
    public void stop() {
        nativeStop(getHandle());
    }

    @Override
    public void close() {
        long handleToDelete = handle;
        handle = 0;
        if (handleToDelete != 0) {
            nativeDelete(handleToDelete);
        }
    }

    /**
     * Users of this class should explicitly call {@link #close()} instead to avoid expensive finalization.
     */
    @SuppressWarnings("deprecation") // finalize()
    @Override
    protected void finalize() throws Throwable {
        close();
        super.finalize();
    }

    private static native long nativeCreate(long storeHandle, String uri, @Nullable String certificatePath);

    private native void nativeDelete(long handle);

    private native void nativeStart(long handle);

    private native void nativeStop(long handle);

    private native boolean nativeIsRunning(long handle);

    private native int nativeGetPort(long handle);

    private native void nativeSetAuthenticator(long handle, long credentialsType, @Nullable byte[] credentials);

    private native void nativeAddPeer(long handle, String uri, long credentialsType, @Nullable byte[] credentials);

    private native String nativeGetStatsString(long handle);

    private native void nativeSetSyncChangesListener(long handle, @Nullable SyncChangeListener changesListener);

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy