Use generics to check tdlib functions return types
This commit is contained in:
parent
6deb99f517
commit
646330ae19
@ -37,7 +37,7 @@ final class AuthorizationStateWaitCodeHandler implements GenericUpdateHandler<Up
|
||||
authorizationState.codeInfo.type
|
||||
);
|
||||
String code = clientInteraction.onParameterRequest(InputParameter.ASK_CODE, parameterInfo);
|
||||
Function response = new CheckAuthenticationCode(code);
|
||||
CheckAuthenticationCode response = new CheckAuthenticationCode(code);
|
||||
client.send(response, ok -> {
|
||||
if (ok.getConstructor() == Error.CONSTRUCTOR) {
|
||||
throw new TelegramError((Error) ok);
|
||||
|
@ -36,7 +36,7 @@ final class AuthorizationStateWaitPasswordHandler implements GenericUpdateHandle
|
||||
authorizationState.recoveryEmailAddressPattern
|
||||
);
|
||||
String password = clientInteraction.onParameterRequest(InputParameter.ASK_PASSWORD, parameterInfo);
|
||||
Function response = new CheckAuthenticationPassword(password);
|
||||
CheckAuthenticationPassword response = new CheckAuthenticationPassword(password);
|
||||
client.send(response, ok -> {
|
||||
if (ok.getConstructor() == Error.CONSTRUCTOR) {
|
||||
throw new TelegramError((Error) ok);
|
||||
|
@ -71,14 +71,19 @@ final class ConsoleInteractiveAuthenticationData implements AuthenticationData {
|
||||
.askParameter("login", "Do you want to login using a bot [token], a [phone] number, or a [qr] code? [token/phone/qr]")
|
||||
.trim()
|
||||
.toLowerCase(Locale.ROOT);
|
||||
if ("phone".equals(choice)) {
|
||||
mode = "PHONE";
|
||||
} else if ("token".equals(choice)) {
|
||||
mode = "TOKEN";
|
||||
} else if ("qr".equals(choice)) {
|
||||
mode = "QR";
|
||||
} else {
|
||||
mode = null;
|
||||
switch (choice) {
|
||||
case "phone":
|
||||
mode = "PHONE";
|
||||
break;
|
||||
case "token":
|
||||
mode = "TOKEN";
|
||||
break;
|
||||
case "qr":
|
||||
mode = "QR";
|
||||
break;
|
||||
default:
|
||||
mode = null;
|
||||
break;
|
||||
}
|
||||
} while (mode == null);
|
||||
|
||||
|
@ -49,7 +49,8 @@ public final class SimpleTelegramClient implements Authenticable {
|
||||
private AuthenticationData authenticationData;
|
||||
|
||||
private final Map<String, Set<CommandHandler>> commandHandlers = new ConcurrentHashMap<>();
|
||||
private final Set<ResultHandler> updateHandlers = new ConcurrentHashMap<ResultHandler, Object>()
|
||||
private final Set<ResultHandler<TdApi.Update>> updateHandlers
|
||||
= new ConcurrentHashMap<ResultHandler<TdApi.Update>, Object>()
|
||||
.keySet(new Object());
|
||||
private final Set<ExceptionHandler> updateExceptionHandlers = new ConcurrentHashMap<ExceptionHandler, Object>()
|
||||
.keySet(new Object());
|
||||
@ -87,7 +88,7 @@ public final class SimpleTelegramClient implements Authenticable {
|
||||
|
||||
private void handleUpdate(TdApi.Object update) {
|
||||
boolean handled = false;
|
||||
for (ResultHandler updateHandler : updateHandlers) {
|
||||
for (ResultHandler<TdApi.Update> updateHandler : updateHandlers) {
|
||||
updateHandler.onResult(update);
|
||||
handled = true;
|
||||
}
|
||||
@ -208,7 +209,7 @@ public final class SimpleTelegramClient implements Authenticable {
|
||||
/**
|
||||
* Send a function and get the result
|
||||
*/
|
||||
public <T extends TdApi.Object> void send(TdApi.Function function, GenericResultHandler<T> resultHandler) {
|
||||
public <R extends TdApi.Object> void send(TdApi.Function<R> function, GenericResultHandler<R> resultHandler) {
|
||||
client.send(function, result -> resultHandler.onResult(Result.of(result)), this::handleResultHandlingException);
|
||||
}
|
||||
|
||||
@ -217,7 +218,7 @@ public final class SimpleTelegramClient implements Authenticable {
|
||||
* <strong>Please note that only some functions can be executed using this method.</strong>
|
||||
* If you want to execute a function please use {@link #send(Function, GenericResultHandler)}!
|
||||
*/
|
||||
public <T extends TdApi.Object> Result<T> execute(TdApi.Function function) {
|
||||
public <R extends TdApi.Object> Result<R> execute(TdApi.Function<R> function) {
|
||||
return Result.of(client.execute(function));
|
||||
}
|
||||
|
||||
|
@ -35,12 +35,6 @@ public final class Init {
|
||||
*/
|
||||
public synchronized static void start() throws CantLoadLibrary {
|
||||
if (!started) {
|
||||
Os os = LoadLibrary.getOs();
|
||||
|
||||
if (os == Os.WINDOWS) {
|
||||
// Since 3.0.0, libraries for windows are statically compiled into tdjni.dll
|
||||
}
|
||||
|
||||
LoadLibrary.load("tdjni");
|
||||
ConstructorDetector.init();
|
||||
started = true;
|
||||
|
@ -4,7 +4,6 @@ import it.tdlight.jni.TdApi;
|
||||
import java.time.Duration;
|
||||
import org.reactivestreams.Publisher;
|
||||
|
||||
@SuppressWarnings("ReactiveStreamsPublisherImplementation")
|
||||
public interface ReactiveTelegramClient {
|
||||
|
||||
/**
|
||||
@ -20,7 +19,7 @@ public interface ReactiveTelegramClient {
|
||||
* @return a publisher that will emit exactly one item, or an error
|
||||
* @throws NullPointerException if query is null.
|
||||
*/
|
||||
Publisher<TdApi.Object> send(TdApi.Function query, Duration timeout);
|
||||
<R extends TdApi.Object> Publisher<TdApi.Object> send(TdApi.Function<R> query, Duration timeout);
|
||||
|
||||
/**
|
||||
* Synchronously executes a TDLib request. Only a few marked accordingly requests can be executed synchronously.
|
||||
@ -29,7 +28,7 @@ public interface ReactiveTelegramClient {
|
||||
* @return request result or {@link TdApi.Error}.
|
||||
* @throws NullPointerException if query is null.
|
||||
*/
|
||||
TdApi.Object execute(TdApi.Function query);
|
||||
<R extends TdApi.Object> TdApi.Object execute(TdApi.Function<R> query);
|
||||
|
||||
void setListener(SignalListener listener);
|
||||
|
||||
|
@ -1,16 +1,18 @@
|
||||
package it.tdlight.common;
|
||||
|
||||
import it.tdlight.jni.TdApi;
|
||||
import it.tdlight.jni.TdApi.Object;
|
||||
|
||||
/**
|
||||
* Interface for handler for results of queries to TDLib and incoming updates from TDLib.
|
||||
*/
|
||||
public interface ResultHandler {
|
||||
@SuppressWarnings("unused")
|
||||
public interface ResultHandler<R extends TdApi.Object> {
|
||||
|
||||
/**
|
||||
* Callback called on result of query to TDLib or incoming update from TDLib.
|
||||
*
|
||||
* @param object Result of query or update of type TdApi.Update about new events.
|
||||
* @param object Result of type r, error of type TdApi.Error, or update of type TdApi.Update.
|
||||
*/
|
||||
void onResult(Object object);
|
||||
void onResult(TdApi.Object object);
|
||||
}
|
@ -22,7 +22,7 @@ public interface TelegramClient {
|
||||
* @param updateExceptionHandler Handler in which the errors from updates are received
|
||||
* @param defaultExceptionHandler Handler that receives exceptions triggered in a handler
|
||||
*/
|
||||
default void initialize(ResultHandler updateHandler,
|
||||
default void initialize(ResultHandler<TdApi.Update> updateHandler,
|
||||
ExceptionHandler updateExceptionHandler,
|
||||
ExceptionHandler defaultExceptionHandler) {
|
||||
this.initialize((UpdatesHandler) updates -> updates.forEach(updateHandler::onResult),
|
||||
@ -41,7 +41,8 @@ public interface TelegramClient {
|
||||
* resultHandler. If it is null, then defaultExceptionHandler will be called.
|
||||
* @throws NullPointerException if query is null.
|
||||
*/
|
||||
void send(TdApi.Function query, ResultHandler resultHandler, ExceptionHandler exceptionHandler);
|
||||
<R extends TdApi.Object> void send(TdApi.Function<R> query, ResultHandler<R> resultHandler,
|
||||
ExceptionHandler exceptionHandler);
|
||||
|
||||
/**
|
||||
* Sends a request to the TDLib with an empty ExceptionHandler.
|
||||
@ -51,7 +52,7 @@ public interface TelegramClient {
|
||||
* TdApi.Error as parameter. If it is null, then defaultExceptionHandler will be called.
|
||||
* @throws NullPointerException if query is null.
|
||||
*/
|
||||
default void send(TdApi.Function query, ResultHandler resultHandler) {
|
||||
default <R extends TdApi.Object> void send(TdApi.Function<R> query, ResultHandler<R> resultHandler) {
|
||||
send(query, resultHandler, null);
|
||||
}
|
||||
|
||||
@ -62,5 +63,5 @@ public interface TelegramClient {
|
||||
* @return request result or {@link TdApi.Error}.
|
||||
* @throws NullPointerException if query is null.
|
||||
*/
|
||||
TdApi.Object execute(TdApi.Function query);
|
||||
<R extends TdApi.Object> TdApi.Object execute(TdApi.Function<R> query);
|
||||
}
|
||||
|
@ -2,17 +2,18 @@ package it.tdlight.common.internal;
|
||||
|
||||
import it.tdlight.common.ExceptionHandler;
|
||||
import it.tdlight.common.ResultHandler;
|
||||
import it.tdlight.jni.TdApi;
|
||||
|
||||
public final class Handler {
|
||||
private final ResultHandler resultHandler;
|
||||
public final class Handler<R extends TdApi.Object> {
|
||||
private final ResultHandler<R> resultHandler;
|
||||
private final ExceptionHandler exceptionHandler;
|
||||
|
||||
public Handler(ResultHandler resultHandler, ExceptionHandler exceptionHandler) {
|
||||
public Handler(ResultHandler<R> resultHandler, ExceptionHandler exceptionHandler) {
|
||||
this.resultHandler = resultHandler;
|
||||
this.exceptionHandler = exceptionHandler;
|
||||
}
|
||||
|
||||
public ResultHandler getResultHandler() {
|
||||
public ResultHandler<R> getResultHandler() {
|
||||
return resultHandler;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@ import it.tdlight.common.UpdatesHandler;
|
||||
import it.tdlight.jni.TdApi;
|
||||
import it.tdlight.jni.TdApi.Error;
|
||||
import it.tdlight.jni.TdApi.Function;
|
||||
import it.tdlight.jni.TdApi.Object;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import java.util.Objects;
|
||||
@ -24,13 +23,13 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient
|
||||
private static final Marker TG_MARKER = MarkerFactory.getMarker("TG");
|
||||
private static final Logger logger = LoggerFactory.getLogger(TelegramClient.class);
|
||||
|
||||
private final ConcurrentHashMap<Long, Handler> handlers = new ConcurrentHashMap<Long, Handler>();
|
||||
private final ConcurrentHashMap<Long, Handler<?>> handlers = new ConcurrentHashMap<>();
|
||||
|
||||
private final Thread shutdownHook = new Thread(this::onJVMShutdown);
|
||||
|
||||
private volatile Integer clientId = null;
|
||||
private final InternalClientManager clientManager;
|
||||
private Handler updateHandler;
|
||||
private Handler<TdApi.Update> updateHandler;
|
||||
private MultiHandler updatesHandler;
|
||||
private ExceptionHandler defaultExceptionHandler;
|
||||
|
||||
@ -47,10 +46,10 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEvents(boolean isClosed, long[] eventIds, Object[] events) {
|
||||
public void handleEvents(boolean isClosed, long[] eventIds, TdApi.Object[] events) {
|
||||
if (updatesHandler != null) {
|
||||
LongArrayList idsToFilter = new LongArrayList(eventIds);
|
||||
ObjectArrayList<Object> eventsToFilter = new ObjectArrayList<>(events);
|
||||
ObjectArrayList<TdApi.Object> eventsToFilter = new ObjectArrayList<>(events);
|
||||
|
||||
for (int i = eventIds.length - 1; i >= 0; i--) {
|
||||
if (eventIds[i] != 0) {
|
||||
@ -58,9 +57,9 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient
|
||||
eventsToFilter.remove(i);
|
||||
|
||||
long eventId = eventIds[i];
|
||||
Object event = events[i];
|
||||
TdApi.Object event = events[i];
|
||||
|
||||
Handler handler = handlers.remove(eventId);
|
||||
Handler<?> handler = handlers.remove(eventId);
|
||||
handleResponse(eventId, event, handler);
|
||||
}
|
||||
}
|
||||
@ -90,9 +89,7 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient
|
||||
} catch (IllegalStateException ignored) {
|
||||
logger.trace(TG_MARKER, "Can't remove shutdown hook because the JVM is already shutting down");
|
||||
}
|
||||
handlers.forEach((eventId, handler) -> {
|
||||
handleResponse(eventId, new Error(500, "Instance closed"), handler);
|
||||
});
|
||||
handlers.forEach((eventId, handler) -> handleResponse(eventId, new Error(500, "Instance closed"), handler));
|
||||
handlers.clear();
|
||||
logger.info(TG_MARKER, "Client closed {}", clientId);
|
||||
}
|
||||
@ -100,7 +97,7 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient
|
||||
/**
|
||||
* Handles only a response (not an update!)
|
||||
*/
|
||||
private void handleResponse(long eventId, Object event, Handler handler) {
|
||||
private void handleResponse(long eventId, TdApi.Object event, Handler<?> handler) {
|
||||
if (handler != null) {
|
||||
try {
|
||||
handler.getResultHandler().onResult(event);
|
||||
@ -115,10 +112,10 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient
|
||||
/**
|
||||
* Handles a response or an update
|
||||
*/
|
||||
private void handleEvent(long eventId, Object event) {
|
||||
private void handleEvent(long eventId, TdApi.Object event) {
|
||||
logger.trace(TG_MARKER, "Received response {}: {}", eventId, event);
|
||||
if (updatesHandler != null || updateHandler == null) throw new IllegalStateException();
|
||||
Handler handler = eventId == 0 ? updateHandler : handlers.remove(eventId);
|
||||
Handler<?> handler = eventId == 0 ? updateHandler : handlers.remove(eventId);
|
||||
handleResponse(eventId, event, handler);
|
||||
}
|
||||
|
||||
@ -144,10 +141,10 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(ResultHandler updateHandler,
|
||||
public void initialize(ResultHandler<TdApi.Update> updateHandler,
|
||||
ExceptionHandler updateExceptionHandler,
|
||||
ExceptionHandler defaultExceptionHandler) {
|
||||
this.updateHandler = new Handler(updateHandler, updateExceptionHandler);
|
||||
this.updateHandler = new Handler<>(updateHandler, updateExceptionHandler);
|
||||
this.updatesHandler = null;
|
||||
this.defaultExceptionHandler = defaultExceptionHandler;
|
||||
createAndRegisterClient();
|
||||
@ -164,25 +161,27 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Function query, ResultHandler resultHandler, ExceptionHandler exceptionHandler) {
|
||||
public <R extends TdApi.Object> void send(Function<R> query, ResultHandler<R> resultHandler,
|
||||
ExceptionHandler exceptionHandler) {
|
||||
logger.trace(TG_MARKER, "Trying to send {}", query);
|
||||
if (isClosedAndMaybeThrow(query)) {
|
||||
resultHandler.onResult(new TdApi.Ok());
|
||||
}
|
||||
if (clientId == null) {
|
||||
ExceptionHandler handler = exceptionHandler == null ? defaultExceptionHandler : exceptionHandler;
|
||||
handler.onException(new IllegalStateException("Can't send a request to TDLib before calling \"initialize\" function!"));
|
||||
handler.onException(new IllegalStateException(
|
||||
"Can't send a request to TDLib before calling \"initialize\" function!"));
|
||||
return;
|
||||
}
|
||||
long queryId = clientManager.getNextQueryId();
|
||||
if (resultHandler != null) {
|
||||
handlers.put(queryId, new Handler(resultHandler, exceptionHandler));
|
||||
handlers.put(queryId, new Handler<>(resultHandler, exceptionHandler));
|
||||
}
|
||||
NativeClientAccess.send(clientId, queryId, query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(Function query) {
|
||||
public <R extends TdApi.Object> TdApi.Object execute(Function<R> query) {
|
||||
logger.trace(TG_MARKER, "Trying to execute {}", query);
|
||||
if (isClosedAndMaybeThrow(query)) {
|
||||
return new TdApi.Ok();
|
||||
@ -206,7 +205,7 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient
|
||||
* @param function function used to check if the check will be enforced or not. Can be null
|
||||
* @return true if closed
|
||||
*/
|
||||
private boolean isClosedAndMaybeThrow(Function function) {
|
||||
private boolean isClosedAndMaybeThrow(Function<?> function) {
|
||||
boolean closed = isClosed.get();
|
||||
if (closed) {
|
||||
if (function != null && function.getConstructor() == TdApi.Close.CONSTRUCTOR) {
|
||||
|
@ -20,6 +20,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.reactivestreams.Subscriber;
|
||||
import org.reactivestreams.Subscription;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -30,13 +31,13 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti
|
||||
|
||||
private static final Marker TG_MARKER = MarkerFactory.getMarker("TG");
|
||||
private static final Logger logger = LoggerFactory.getLogger(InternalReactiveClient.class);
|
||||
private static final Handler EMPTY_HANDLER = new Handler(r -> {}, ex -> {});
|
||||
private static final Handler<?> EMPTY_HANDLER = new Handler<>(r -> {}, ex -> {});
|
||||
|
||||
private final ConcurrentHashMap<Long, Handler> handlers = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<Long, Handler<?>> handlers = new ConcurrentHashMap<>();
|
||||
private final Set<Long> timedOutHandlers = new ConcurrentHashMap<Long, Object>().keySet(new Object());
|
||||
private final ScheduledExecutorService timers = Executors.newSingleThreadScheduledExecutor();
|
||||
private final ExceptionHandler defaultExceptionHandler;
|
||||
private final Handler updateHandler;
|
||||
private final Handler<TdApi.Update> updateHandler;
|
||||
|
||||
private final Thread shutdownHook = new Thread(this::onJVMShutdown);
|
||||
|
||||
@ -48,7 +49,7 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti
|
||||
|
||||
public InternalReactiveClient(InternalClientManager clientManager) {
|
||||
this.clientManager = clientManager;
|
||||
this.updateHandler = new Handler(this::onUpdateFromHandler, this::onUpdateException);
|
||||
this.updateHandler = new Handler<>(this::onUpdateFromHandler, this::onUpdateException);
|
||||
this.defaultExceptionHandler = this::onDefaultException;
|
||||
Runtime.getRuntime().addShutdownHook(shutdownHook);
|
||||
}
|
||||
@ -105,7 +106,7 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti
|
||||
/**
|
||||
* Handles only a response (not an update!)
|
||||
*/
|
||||
private void handleResponse(long eventId, TdApi.Object event, Handler handler) {
|
||||
private void handleResponse(long eventId, TdApi.Object event, Handler<?> handler) {
|
||||
if (handler != null) {
|
||||
try {
|
||||
if (eventId == 0) {
|
||||
@ -137,7 +138,7 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti
|
||||
* Handles a response or an update
|
||||
*/
|
||||
private void handleEvent(long eventId, TdApi.Object event) {
|
||||
Handler handler = eventId == 0 ? updateHandler : handlers.remove(eventId);
|
||||
Handler<?> handler = eventId == 0 ? updateHandler : handlers.remove(eventId);
|
||||
handleResponse(eventId, event, handler);
|
||||
}
|
||||
|
||||
@ -151,7 +152,6 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"ReactiveStreamsSubscriberImplementation", "Convert2Diamond"})
|
||||
public void createAndRegisterClient() {
|
||||
if (clientId != null) {
|
||||
throw new UnsupportedOperationException("Can't initialize the same client twice!");
|
||||
@ -164,7 +164,7 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti
|
||||
}
|
||||
|
||||
@Override
|
||||
public Publisher<TdApi.Object> send(Function query, Duration responseTimeout) {
|
||||
public <R extends TdApi.Object> Publisher<TdApi.Object> send(Function<R> query, Duration responseTimeout) {
|
||||
return subscriber -> {
|
||||
Subscription subscription = new Subscription() {
|
||||
|
||||
@ -202,7 +202,7 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti
|
||||
}
|
||||
}, responseTimeout.toMillis(), TimeUnit.MILLISECONDS);
|
||||
|
||||
handlers.put(queryId, new Handler(result -> {
|
||||
handlers.put(queryId, new Handler<>(result -> {
|
||||
logger.trace(TG_MARKER,
|
||||
"Client {} is replying the query id {}: request: {} result: {}",
|
||||
clientId,
|
||||
@ -243,7 +243,7 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti
|
||||
}
|
||||
|
||||
@Override
|
||||
public TdApi.Object execute(Function query) {
|
||||
public <R extends TdApi.Object> TdApi.Object execute(Function<R> query) {
|
||||
if (isClosedAndMaybeThrow(query)) {
|
||||
return new TdApi.Ok();
|
||||
}
|
||||
@ -324,7 +324,7 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti
|
||||
* @param function function used to check if the check will be enforced or not. Can be null
|
||||
* @return true if closed
|
||||
*/
|
||||
private boolean isClosedAndMaybeThrow(Function function) {
|
||||
private boolean isClosedAndMaybeThrow(Function<?> function) {
|
||||
boolean closed = alreadyReceivedClosed.get();
|
||||
if (closed) {
|
||||
if (function != null && function.getConstructor() == TdApi.Close.CONSTRUCTOR) {
|
||||
|
@ -10,11 +10,11 @@ final class NativeClientAccess extends NativeClient {
|
||||
return NativeClientAccess.createNativeClient();
|
||||
}
|
||||
|
||||
public static TdApi.Object execute(Function function) {
|
||||
public static <R extends TdApi.Object> TdApi.Object execute(Function<R> function) {
|
||||
return NativeClientAccess.nativeClientExecute(function);
|
||||
}
|
||||
|
||||
public static void send(int nativeClientId, long eventId, TdApi.Function function) {
|
||||
public static <R extends TdApi.Object> void send(int nativeClientId, long eventId, TdApi.Function<R> function) {
|
||||
NativeClientAccess.nativeClientSend(nativeClientId, eventId, function);
|
||||
}
|
||||
|
||||
|
@ -185,9 +185,10 @@ public final class ResponseReceiver extends Thread implements AutoCloseable {
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private int[] generateSortIndex(int from, int to, int[] data) {
|
||||
int[] sortedIndices = Arrays.copyOfRange(originalSortingSource, from, to);
|
||||
it.unimi.dsi.fastutil.Arrays.mergeSort(from, to, (o1, o2) -> {
|
||||
return Integer.compare(data[sortedIndices[o1]], data[sortedIndices[o2]]);
|
||||
}, new IntSwapper(sortedIndices));
|
||||
it.unimi.dsi.fastutil.Arrays.mergeSort(from, to,
|
||||
(o1, o2) -> Integer.compare(data[sortedIndices[o1]], data[sortedIndices[o2]]),
|
||||
new IntSwapper(sortedIndices)
|
||||
);
|
||||
return sortedIndices;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
package it.tdlight.common.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An exception that is thrown when the LoadLibrary class fails to load the library.
|
||||
*/
|
||||
@ -25,6 +27,18 @@ public final class CantLoadLibrary extends Exception {
|
||||
* Creates a new CantLoadLibrary exception.
|
||||
*/
|
||||
CantLoadLibrary() {
|
||||
super("FATAL: Init failed when loading TDLib native libraries, execution can't continue");
|
||||
super("Init failed when loading TDLib native libraries, execution can't continue");
|
||||
}
|
||||
|
||||
public CantLoadLibrary(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CantLoadLibrary(String message, Exception cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public CantLoadLibrary(Exception cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
|
@ -73,18 +73,16 @@ public final class LoadLibrary {
|
||||
Os os = getOs();
|
||||
|
||||
if (arch == Arch.UNKNOWN) {
|
||||
throw (CantLoadLibrary) new CantLoadLibrary().initCause(new IllegalStateException(
|
||||
"Arch: \"" + System.getProperty("os.arch") + "\" is unknown"));
|
||||
throw new CantLoadLibrary("Arch: \"" + System.getProperty("os.arch") + "\" is unknown");
|
||||
}
|
||||
|
||||
if (os == Os.UNKNOWN) {
|
||||
throw (CantLoadLibrary) new CantLoadLibrary().initCause(new IllegalStateException(
|
||||
"Os: \"" + System.getProperty("os.name") + "\" is unknown"));
|
||||
throw new CantLoadLibrary("Os: \"" + System.getProperty("os.name") + "\" is unknown");
|
||||
}
|
||||
|
||||
try {
|
||||
loadJarLibrary(libname, arch, os);
|
||||
} catch (IOException | CantLoadLibrary | UnsatisfiedLinkError e) {
|
||||
} catch (CantLoadLibrary | UnsatisfiedLinkError e) {
|
||||
if (loadSysLibrary(libname)) {
|
||||
return;
|
||||
}
|
||||
@ -102,8 +100,13 @@ public final class LoadLibrary {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void loadJarLibrary(String libname, Arch arch, Os os) throws IOException, CantLoadLibrary {
|
||||
Path tempPath = Files.createDirectories(librariesPath.resolve("version-" + libsVersion).resolve(libname));
|
||||
private static void loadJarLibrary(String libname, Arch arch, Os os) throws CantLoadLibrary {
|
||||
Path tempPath;
|
||||
try {
|
||||
tempPath = Files.createDirectories(librariesPath.resolve("version-" + libsVersion).resolve(libname));
|
||||
} catch (IOException e) {
|
||||
throw new CantLoadLibrary("Can't create temporary files", e);
|
||||
}
|
||||
Path tempFile = Paths.get(tempPath.toString(), libname + getExt(os));
|
||||
Class<?> classForResource = null;
|
||||
switch (os) {
|
||||
@ -177,7 +180,7 @@ public final class LoadLibrary {
|
||||
break;
|
||||
}
|
||||
if (classForResource == null) {
|
||||
throw new IOException("Native libraries for platform " + os + "-" + arch + " not found!");
|
||||
throw new CantLoadLibrary("Native libraries for platform " + os + "-" + arch + " not found!");
|
||||
}
|
||||
InputStream libInputStream;
|
||||
try {
|
||||
@ -185,12 +188,20 @@ public final class LoadLibrary {
|
||||
.getDeclaredMethod("getLibraryAsStream")
|
||||
.invoke(InputStream.class));
|
||||
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | NullPointerException e) {
|
||||
throw new IOException("Native libraries for platform " + os + "-" + arch + " not found!", e);
|
||||
throw new CantLoadLibrary("Native libraries for platform " + os + "-" + arch + " not found!", e);
|
||||
}
|
||||
if (Files.notExists(tempFile)) {
|
||||
Files.copy(libInputStream, tempFile);
|
||||
try {
|
||||
Files.copy(libInputStream, tempFile);
|
||||
} catch (IOException e) {
|
||||
throw new CantLoadLibrary("Can't copy native libraries into temporary files", e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
libInputStream.close();
|
||||
} catch (IOException e) {
|
||||
throw new CantLoadLibrary("Can't load the native libraries", e);
|
||||
}
|
||||
libInputStream.close();
|
||||
System.load(tempFile.toFile().getAbsolutePath());
|
||||
}
|
||||
|
||||
@ -269,19 +280,4 @@ public final class LoadLibrary {
|
||||
return ".so";
|
||||
}
|
||||
}
|
||||
|
||||
private static String createPath(String... path) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append("/");
|
||||
|
||||
for (int i = 0; i < path.length; i++) {
|
||||
stringBuilder.append(path[i]);
|
||||
|
||||
if (i < path.length - 1) {
|
||||
stringBuilder.append("/");
|
||||
}
|
||||
}
|
||||
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package it.tdlight.common.utils;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
public class SpinWaitSupport {
|
||||
|
||||
@ -10,5 +11,7 @@ public class SpinWaitSupport {
|
||||
}
|
||||
|
||||
public static void onSpinWait() {
|
||||
// park for 10ms
|
||||
LockSupport.parkNanos(10 * 1000L * 1000L);
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,11 @@ public class NativeClient {
|
||||
|
||||
protected static native int createNativeClient();
|
||||
|
||||
protected static native void nativeClientSend(int nativeClientId, long eventId, TdApi.Function function);
|
||||
protected static native <R extends TdApi.Object> void nativeClientSend(int nativeClientId, long eventId,
|
||||
TdApi.Function<R> function);
|
||||
|
||||
protected static native int nativeClientReceive(int[] clientIds, long[] eventIds, TdApi.Object[] events,
|
||||
double timeout);
|
||||
|
||||
protected static native TdApi.Object nativeClientExecute(TdApi.Function function);
|
||||
protected static native <R extends TdApi.Object> TdApi.Object nativeClientExecute(TdApi.Function<R> function);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<revision>1.0.0.0-SNAPSHOT</revision>
|
||||
<api-version>3.3.162</api-version>
|
||||
<api-version>3.3.163</api-version>
|
||||
<natives-version>3.3.164</natives-version>
|
||||
</properties>
|
||||
<repositories>
|
||||
|
@ -8,7 +8,7 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<revision>1.0.0.0-SNAPSHOT</revision>
|
||||
<api-version>3.3.162</api-version>
|
||||
<api-version>3.3.163</api-version>
|
||||
<natives-version>3.3.164</natives-version>
|
||||
</properties>
|
||||
<repositories>
|
||||
|
Loading…
Reference in New Issue
Block a user