/** * Copyright 2016 Yahoo Inc. * * 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.yahoo.pulsar.client.admin.internal; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; import javax.ws.rs.ClientErrorException; import javax.ws.rs.ServerErrorException; import javax.ws.rs.ServiceUnavailableException; import javax.ws.rs.WebApplicationException; import javax.ws.rs.client.Entity; import javax.ws.rs.client.Invocation.Builder; import javax.ws.rs.client.InvocationCallback; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.yahoo.pulsar.client.admin.PulsarAdminException; import com.yahoo.pulsar.client.admin.PulsarAdminException.ConflictException; import com.yahoo.pulsar.client.admin.PulsarAdminException.ConnectException; import com.yahoo.pulsar.client.admin.PulsarAdminException.GettingAuthenticationDataException; import com.yahoo.pulsar.client.admin.PulsarAdminException.HttpErrorException; import com.yahoo.pulsar.client.admin.PulsarAdminException.NotAllowedException; import com.yahoo.pulsar.client.admin.PulsarAdminException.NotAuthorizedException; import com.yahoo.pulsar.client.admin.PulsarAdminException.NotFoundException; import com.yahoo.pulsar.client.admin.PulsarAdminException.PreconditionFailedException; import com.yahoo.pulsar.client.admin.PulsarAdminException.ServerSideErrorException; import com.yahoo.pulsar.client.api.Authentication; import com.yahoo.pulsar.client.util.FutureUtil; import com.yahoo.pulsar.common.policies.data.ErrorData; public abstract class BaseResource { private static final Logger log = LoggerFactory.getLogger(BaseResource.class); private final Authentication auth; protected BaseResource(Authentication auth) { this.auth = auth; } public Builder request(final WebTarget target) throws PulsarAdminException { try { Builder builder = target.request(MediaType.APPLICATION_JSON); // Add headers for authentication if any if (auth != null && auth.getAuthData().hasDataForHttp()) { for (Map.Entry<String, String> header : auth.getAuthData().getHttpHeaders()) { builder.header(header.getKey(), header.getValue()); } } return builder; } catch (Throwable t) { throw new GettingAuthenticationDataException(t); } } public <T> CompletableFuture<Void> asyncPutRequest(final WebTarget target, Entity<T> entity) { final CompletableFuture<Void> future = new CompletableFuture<>(); try { request(target).async().put(entity, new InvocationCallback<ErrorData>() { @Override public void completed(ErrorData response) { future.complete(null); } @Override public void failed(Throwable throwable) { log.warn("[{}] Failed to perform http put request: {}", target.getUri(), throwable.getMessage()); future.completeExceptionally(getApiException(throwable.getCause())); } }); } catch (PulsarAdminException cae) { future.completeExceptionally(cae); } return future; } public <T> CompletableFuture<Void> asyncPostRequest(final WebTarget target, Entity<T> entity) { final CompletableFuture<Void> future = new CompletableFuture<>(); try { request(target).async().post(entity, new InvocationCallback<ErrorData>() { @Override public void completed(ErrorData response) { future.complete(null); } @Override public void failed(Throwable throwable) { log.warn("[{}] Failed to perform http post request: {}", target.getUri(), throwable.getMessage()); future.completeExceptionally(getApiException(throwable.getCause())); } }); } catch (PulsarAdminException cae) { future.completeExceptionally(cae); } return future; } public <T> Future<T> asyncGetRequest(final WebTarget target, InvocationCallback<T> callback) { try { return request(target).async().get(callback); } catch (PulsarAdminException cae) { return FutureUtil.failedFuture(cae); } } public CompletableFuture<Void> asyncDeleteRequest(final WebTarget target) { final CompletableFuture<Void> future = new CompletableFuture<>(); try { request(target).async().delete(new InvocationCallback<ErrorData>() { @Override public void completed(ErrorData response) { future.complete(null); } @Override public void failed(Throwable throwable) { log.warn("[{}] Failed to perform http delete request: {}", target.getUri(), throwable.getMessage()); future.completeExceptionally(getApiException(throwable.getCause())); } }); } catch (PulsarAdminException cae) { future.completeExceptionally(cae); } return future; } public PulsarAdminException getApiException(Throwable e) { if (e instanceof ServiceUnavailableException) { if (e.getCause() instanceof java.net.ConnectException) { return new ConnectException(e.getCause()); } else { return new HttpErrorException(e); } } else if (e instanceof WebApplicationException) { // Handle 5xx exceptions if (e instanceof ServerErrorException) { ServerErrorException see = (ServerErrorException) e; return new ServerSideErrorException(see); } // Handle 4xx exceptions ClientErrorException cee = (ClientErrorException) e; int statusCode = cee.getResponse().getStatus(); switch (statusCode) { case 401: case 403: return new NotAuthorizedException(cee); case 404: return new NotFoundException(cee); case 405: return new NotAllowedException(cee); case 409: return new ConflictException(cee); case 412: return new PreconditionFailedException(cee); default: return new PulsarAdminException(cee); } } else { return new PulsarAdminException(e); } } }