Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.github.jcustenborder.kafka.connect.client.KafkaConnectClientImpl Maven / Gradle / Ivy
/**
* Copyright © 2019 Jeremy Custenborder ([email protected] )
*
* 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 com.github.jcustenborder.kafka.connect.client;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.github.jcustenborder.kafka.connect.client.model.ConnectorInfo;
import com.github.jcustenborder.kafka.connect.client.model.ConnectorPlugin;
import com.github.jcustenborder.kafka.connect.client.model.ConnectorStatus;
import com.github.jcustenborder.kafka.connect.client.model.CreateConnectorRequest;
import com.github.jcustenborder.kafka.connect.client.model.CreateConnectorResponse;
import com.github.jcustenborder.kafka.connect.client.model.ServerInfo;
import com.github.jcustenborder.kafka.connect.client.model.TaskConfig;
import com.github.jcustenborder.kafka.connect.client.model.TaskStatus;
import com.github.jcustenborder.kafka.connect.client.model.ValidateResponse;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
class KafkaConnectClientImpl implements AsyncKafkaConnectClient, KafkaConnectClient {
static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
static final RequestBody EMPTY = RequestBody.create(null, new byte[]{});
static final TypeReference> CONFIG_TYPE = new TypeReference>() {
};
static final TypeReference> CONNECTORS_TYPE = new TypeReference>() {
};
static final TypeReference> TASKCONFIG_TYPE = new TypeReference>() {
};
static final TypeReference> CONNECTOR_PLUGIN_TYPE = new TypeReference>() {
};
private static final Logger log = LoggerFactory.getLogger(KafkaConnectClientImpl.class);
final AbstractSettings settings;
public KafkaConnectClientImpl(AbstractSettings settings) {
this.settings = settings;
}
static HttpUrl addPathSegments(HttpUrl baseUrl, Iterable parts) {
HttpUrl.Builder builder = baseUrl.newBuilder();
for (String part : parts) {
builder = builder.addPathSegment(part);
}
return builder.build();
}
static T get(Future future) throws IOException {
try {
return future.get();
} catch (InterruptedException e) {
throw new IOException(e);
} catch (ExecutionException ex) {
if (ex.getCause() instanceof KafkaConnectException) {
throw (KafkaConnectException) ex.getCause();
} else {
throw new IOException(ex);
}
}
}
HttpUrl baseUrl(String... parts) {
return addPathSegments(this.settings.baseUrl(), Arrays.asList(parts));
}
HttpUrl connectorsUrl(String... parts) {
List segments = new ArrayList<>();
segments.add("connectors");
segments.addAll(Arrays.asList(parts));
return addPathSegments(this.settings.baseUrl(), segments);
}
HttpUrl connectorsPluginsUrl(String... parts) {
List segments = new ArrayList<>();
segments.add("connector-plugins");
segments.addAll(Arrays.asList(parts));
return addPathSegments(this.settings.baseUrl(), segments);
}
void checkConnectorConfig(Map config) {
//TODO: Comeback and do some validation.
// Preconditions.checkNotNull("config", "config cannot be null");
// Preconditions.checkState(config.containsKey("connector.class"), "connector.class must be specified.");
// Preconditions.checkState(config.containsKey("tasks.max"), "tasks.max must be specified.");
}
@Override
public List connectors() throws IOException {
CompletableFuture> future = connectorsAsync();
return get(future);
}
@Override
public CreateConnectorResponse createConnector(CreateConnectorRequest request) throws IOException {
return get(createConnectorAsync(request));
}
@Override
public ConnectorInfo createOrUpdate(String name, Map config) throws IOException {
CompletableFuture future = createOrUpdateAsync(name, config);
return get(future);
}
@Override
public ConnectorInfo info(String name) throws IOException {
CompletableFuture future = infoAsync(name);
return get(future);
}
@Override
public Map config(String name) throws IOException {
CompletableFuture> future = configAsync(name);
return get(future);
}
@Override
public void delete(String name) throws IOException {
CompletableFuture future = deleteAsync(name);
get(future);
}
@Override
public void restart(String name) throws IOException {
CompletableFuture future = restartAsync(name);
get(future);
}
@Override
public void pause(String name) throws IOException {
CompletableFuture future = pauseAsync(name);
get(future);
}
@Override
public void resume(String name) throws IOException {
CompletableFuture future = resumeAsync(name);
get(future);
}
@Override
public ConnectorStatus status(String name) throws IOException {
CompletableFuture future = statusAsync(name);
return get(future);
}
@Override
public TaskStatus status(String name, int taskId) throws IOException {
CompletableFuture future = statusAsync(name, taskId);
return get(future);
}
@Override
public void restart(String name, int taskId) throws IOException {
CompletableFuture future = restartAsync(name, taskId);
get(future);
}
@Override
public List connectorPlugins() throws IOException {
CompletableFuture> future = connectorPluginsAsync();
return get(future);
}
@Override
public ValidateResponse validate(String name, Map config) throws IOException {
CompletableFuture future = validateAsync(name, config);
return get(future);
}
@Override
public ServerInfo serverInfo() throws IOException {
CompletableFuture future = serverInfoAsync();
return get(future);
}
private CompletableFuture executeRequest(Request request, TypeReference type) {
final CompletableFuture futureResult = new CompletableFuture<>();
final TypeReferenceCallback callback = new TypeReferenceCallback<>(
this.settings,
futureResult,
type
);
callback.newCall(request);
return futureResult;
}
private CompletableFuture executeRequest(Request request, Class type) {
final CompletableFuture futureResult = new CompletableFuture<>();
final ClassCallback callback = new ClassCallback<>(
this.settings,
futureResult,
type
);
callback.newCall(request);
return futureResult;
}
Request.Builder newBuilder() {
Request.Builder result = new Request.Builder();
if (this.settings.hasCredentials()) {
result.addHeader("Authorization", this.settings.credentials());
}
return result;
}
@Override
public CompletableFuture> connectorsAsync() {
HttpUrl url = connectorsUrl();
log.trace("connectorsAsync() - url = '{}'", url);
Request request = newBuilder()
.url(url)
.get()
.build();
CompletableFuture> result = executeRequest(request, CONNECTORS_TYPE);
return result;
}
@Override
public CompletableFuture createConnectorAsync(CreateConnectorRequest request) {
HttpUrl url = connectorsUrl();
log.trace("createConnector() url = '{}' request = '{}'", url, request);
Request httpRequest = newBuilder()
.url(url)
.post(body(request))
.build();
return executeRequest(httpRequest, CreateConnectorResponse.class);
}
protected RequestBody body(Object o) {
try {
byte[] body = this.settings.objectMapper().writeValueAsBytes(o);
RequestBody requestBody = RequestBody.create(body, JSON);
return requestBody;
} catch (JsonProcessingException e) {
throw new IllegalStateException(e);
}
}
@Override
public CompletableFuture createOrUpdateAsync(String name, Map config) {
// Preconditions.checkNotNull(name, "name cannot be null");
checkConnectorConfig(config);
HttpUrl connectorUrl = connectorsUrl(name, "config");
log.trace("createOrUpdateAsync() - url = '{}'", connectorUrl);
Request request = newBuilder()
.url(connectorUrl)
.put(body(config))
.build();
return executeRequest(request, ConnectorInfo.class);
}
@Override
public CompletableFuture infoAsync(String name) {
// Preconditions.checkNotNull(name, "name cannot be null");
HttpUrl connectorUrl = connectorsUrl(name);
Request request = newBuilder()
.get()
.url(connectorUrl)
.build();
return executeRequest(request, ConnectorInfo.class);
}
@Override
public CompletableFuture> configAsync(String name) {
HttpUrl url = connectorsUrl(name, "config");
log.trace("connectors() - url = '{}'", url);
Request request = newBuilder()
.url(url)
.get()
.build();
return executeRequest(request, CONFIG_TYPE);
}
@Override
public CompletableFuture deleteAsync(String name) {
// Preconditions.checkNotNull(name, "name cannot be null");
HttpUrl connectorUrl = connectorsUrl(name);
Request request = newBuilder()
.url(connectorUrl)
.delete()
.build();
return executeRequest(request, Void.class);
}
@Override
public CompletableFuture restartAsync(String name) {
HttpUrl connectorUrl = connectorsUrl(name, "restart");
Request request = newBuilder()
.url(connectorUrl)
.post(EMPTY)
.build();
return executeRequest(request, Void.class);
}
@Override
public CompletableFuture pauseAsync(String name) {
HttpUrl connectorUrl = connectorsUrl(name, "pause");
Request request = newBuilder()
.url(connectorUrl)
.put(EMPTY)
.build();
return executeRequest(request, Void.class);
}
@Override
public CompletableFuture resumeAsync(String name) {
HttpUrl connectorUrl = connectorsUrl(name, "resume");
Request request = newBuilder()
.url(connectorUrl)
.put(EMPTY)
.build();
return executeRequest(request, Void.class);
}
@Override
public CompletableFuture statusAsync(String name) {
HttpUrl connectorUrl = connectorsUrl(name, "status");
Request request = newBuilder()
.url(connectorUrl)
.build();
return executeRequest(request, ConnectorStatus.class);
}
@Override
public CompletableFuture statusAsync(String name, int taskId) {
HttpUrl connectorUrl = connectorsUrl(name, "tasks", Integer.toString(taskId), "status");
Request request = newBuilder()
.url(connectorUrl)
.build();
return executeRequest(request, TaskStatus.class);
}
@Override
public CompletableFuture restartAsync(String name, int taskId) {
HttpUrl connectorUrl = connectorsUrl(name, "tasks", Integer.toString(taskId), "restart");
Request request = newBuilder()
.url(connectorUrl)
.post(EMPTY)
.build();
return executeRequest(request, Void.class);
}
@Override
public List taskConfigs(String name) throws IOException {
CompletableFuture> future = taskConfigsAsync(name);
return get(future);
}
@Override
public CompletableFuture> connectorPluginsAsync() {
HttpUrl pluginsUrl = connectorsPluginsUrl();
Request request = newBuilder()
.url(pluginsUrl)
.build();
return executeRequest(request, CONNECTOR_PLUGIN_TYPE);
}
@Override
public CompletableFuture validateAsync(String name, Map config) {
HttpUrl url = connectorsPluginsUrl(
name,
"config",
"validate"
);
Request request = newBuilder()
.url(url)
.put(body(config))
.build();
return executeRequest(request, ValidateResponse.class);
}
@Override
public CompletableFuture serverInfoAsync() {
Request request = newBuilder()
.url(this.settings.baseUrl())
.build();
return executeRequest(request, ServerInfo.class);
}
@Override
public CompletableFuture> taskConfigsAsync(String name) {
HttpUrl connectorUrl = connectorsUrl(name, "tasks");
Request request = newBuilder()
.get()
.url(connectorUrl)
.build();
return executeRequest(request, TASKCONFIG_TYPE);
}
@Override
public void close() throws Exception {
if (this.settings.shutdownSchedulerOnClose()) {
this.settings.scheduler().shutdown();
}
}
}