Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions android/src/main/java/io/ably/lib/realtime/Channel.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import io.ably.lib.types.AblyException;
import io.ably.lib.types.ChannelOptions;
import io.ably.lib.push.PushChannel;
import io.ably.lib.objects.LiveObjectsPlugin;


public class Channel extends ChannelBase {
/**
Expand All @@ -12,8 +14,8 @@ public class Channel extends ChannelBase {
*/
public final PushChannel push;

Channel(AblyRealtime ably, String name, ChannelOptions options) throws AblyException {
super(ably, name, options);
Channel(AblyRealtime ably, String name, ChannelOptions options, LiveObjectsPlugin liveObjectsPlugin) throws AblyException {
super(ably, name, options, liveObjectsPlugin);
this.push = ((io.ably.lib.rest.AblyRest) ably).channels.get(name, options).push;
}

Expand Down
5 changes: 3 additions & 2 deletions java/src/main/java/io/ably/lib/realtime/Channel.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package io.ably.lib.realtime;

import io.ably.lib.objects.LiveObjectsPlugin;
import io.ably.lib.types.AblyException;
import io.ably.lib.types.ChannelOptions;

public class Channel extends ChannelBase {
Channel(AblyRealtime ably, String name, ChannelOptions options) throws AblyException {
super(ably, name, options);
Channel(AblyRealtime ably, String name, ChannelOptions options, LiveObjectsPlugin liveObjectsPlugin) throws AblyException {
super(ably, name, options, liveObjectsPlugin);
}

public interface MessageListener extends ChannelBase.MessageListener {}
Expand Down
8 changes: 8 additions & 0 deletions lib/src/main/java/io/ably/lib/objects/LiveObjects.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.ably.lib.objects;

import io.ably.lib.types.Callback;

public interface LiveObjects {
Long getRoot();
void getRootAsync(Callback<Long> callback);
}
5 changes: 5 additions & 0 deletions lib/src/main/java/io/ably/lib/objects/LiveObjectsPlugin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.ably.lib.objects;

public interface LiveObjectsPlugin {
LiveObjects getInstance(String channelName);
}
25 changes: 24 additions & 1 deletion lib/src/main/java/io/ably/lib/realtime/AblyRealtime.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package io.ably.lib.realtime;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.ably.lib.network.HttpEngineFactory;
import io.ably.lib.objects.LiveObjects;
import io.ably.lib.objects.LiveObjectsPlugin;
import io.ably.lib.rest.AblyRest;
import io.ably.lib.rest.Auth;
import io.ably.lib.transport.ConnectionManager;
Expand Down Expand Up @@ -40,6 +44,13 @@ public class AblyRealtime extends AblyRest {
*/
public final Channels channels;

/**
* A nullable reference to the LiveObjects plugin.
* <p>
* This field is initialized only if the LiveObjects plugin is present in the classpath.
*/
private final LiveObjectsPlugin liveObjectsPlugin;

/**
* Constructs a Realtime client object using an Ably API key or token string.
* <p>
Expand Down Expand Up @@ -72,6 +83,8 @@ public AblyRealtime(ClientOptions options) throws AblyException {
}
}

liveObjectsPlugin = tryInitializeLiveObjectsPlugin();

if(options.autoConnect) connection.connect();
}

Expand Down Expand Up @@ -168,6 +181,16 @@ public interface Channels extends ReadOnlyMap<String, Channel> {
void release(String channelName);
}

private LiveObjectsPlugin tryInitializeLiveObjectsPlugin() {
try {
Class<?> liveObjectsImplementation = Class.forName("io.ably.lib.objects.DefaultLiveObjectsPlugin");
return (LiveObjectsPlugin) liveObjectsImplementation.getDeclaredConstructor().newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException |
InvocationTargetException e) {
return null;
}
}

private class InternalChannels extends InternalMap<String, Channel> implements Channels, ConnectionManager.Channels {
/**
* Get the named channel; if it does not already exist,
Expand All @@ -187,7 +210,7 @@ public Channel get(final String channelName, final ChannelOptions channelOptions
// We're not using computeIfAbsent because that requires Java 1.8.
// Hence there's the slight inefficiency of creating newChannel when it may not be
// needed because there is an existingChannel.
final Channel newChannel = new Channel(AblyRealtime.this, channelName, channelOptions);
final Channel newChannel = new Channel(AblyRealtime.this, channelName, channelOptions, liveObjectsPlugin);
final Channel existingChannel = map.putIfAbsent(channelName, newChannel);

if (existingChannel != null) {
Expand Down
22 changes: 21 additions & 1 deletion lib/src/main/java/io/ably/lib/realtime/ChannelBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import io.ably.lib.http.Http;
import io.ably.lib.http.HttpCore;
import io.ably.lib.http.HttpUtils;
import io.ably.lib.objects.LiveObjects;
import io.ably.lib.objects.LiveObjectsPlugin;
import io.ably.lib.transport.ConnectionManager;
import io.ably.lib.transport.ConnectionManager.QueuedMessage;
import io.ably.lib.transport.Defaults;
Expand Down Expand Up @@ -91,6 +93,23 @@ public abstract class ChannelBase extends EventEmitter<ChannelEvent, ChannelStat
*/
private boolean released = false;

private final LiveObjectsPlugin liveObjectsPlugin;
private LiveObjects objects;

public LiveObjects getObjects() throws AblyException {
if (liveObjectsPlugin == null) {
throw AblyException.fromErrorInfo(
new ErrorInfo("LiveObjects plugin hasn't been installed, add runtimeOnly('io.ably:live-objects:<ably-version>') to your dependency tree", 400, 40000)
);
}

if (objects == null) {
objects = liveObjectsPlugin.getInstance(name);
}

return objects;
}

/***
* internal
*
Expand Down Expand Up @@ -1285,7 +1304,7 @@ else if(stateChange.current.equals(failureState)) {
}
}

ChannelBase(AblyRealtime ably, String name, ChannelOptions options) throws AblyException {
ChannelBase(AblyRealtime ably, String name, ChannelOptions options, LiveObjectsPlugin liveObjectsPlugin) throws AblyException {
Log.v(TAG, "RealtimeChannel(); channel = " + name);
this.ably = ably;
this.name = name;
Expand All @@ -1295,6 +1314,7 @@ else if(stateChange.current.equals(failureState)) {
this.attachResume = false;
state = ChannelState.initialized;
this.decodingContext = new DecodingContext();
this.liveObjectsPlugin = liveObjectsPlugin;
}

void onChannelMessage(ProtocolMessage msg) {
Expand Down
21 changes: 21 additions & 0 deletions live-objects/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
plugins {
`java-library`
alias(libs.plugins.kotlin.jvm)
}

repositories {
mavenCentral()
}

dependencies {
implementation(project(":java"))
testImplementation(kotlin("test"))
}

tasks.test {
useJUnitPlatform()
}

kotlin {
explicitApi()
}
4 changes: 4 additions & 0 deletions live-objects/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
POM_ARTIFACT_ID=live-objects
POM_NAME=Live Objects plugin for Ably Pub/Sub SDK
POM_DESCRIPTION=Live Objects plugin for Ably Pub/Sub SDK
POM_PACKAGING=jar
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.ably.lib.objects

import io.ably.lib.types.Callback

internal class DefaultLiveObjects(private val channelName: String): LiveObjects {

override fun getRoot(): Long = channelName.length.toLong()

override fun getRootAsync(callback: Callback<Long>) {
callback.onSuccess(channelName.length.toLong())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.ably.lib.objects

public class DefaultLiveObjectsPlugin(): LiveObjectsPlugin {
override fun greetings(): String = "Hello from Live Objects module"

override fun getInstance(channelName: String): LiveObjects = DefaultLiveObjects(channelName)

}
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ include("network-client-core")
include("network-client-default")
include("network-client-okhttp")
include("pubsub-adapter")
include("live-objects")
Loading