
org.apache.brooklyn.rest.client.BrooklynApi Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of brooklyn-rest-client Show documentation
Show all versions of brooklyn-rest-client Show documentation
Client library for Brooklyn REST interface
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.brooklyn.rest.client;
import static com.google.common.base.Preconditions.checkNotNull;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.MalformedURLException;
import java.net.URL;
import javax.annotation.Nullable;
import javax.ws.rs.core.Response;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.jboss.resteasy.client.ClientExecutor;
import org.jboss.resteasy.client.ClientResponse;
import org.jboss.resteasy.client.ProxyFactory;
import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor;
import org.jboss.resteasy.specimpl.BuiltResponse;
import org.jboss.resteasy.util.GenericType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import org.apache.brooklyn.rest.api.AccessApi;
import org.apache.brooklyn.rest.api.ActivityApi;
import org.apache.brooklyn.rest.api.ApplicationApi;
import org.apache.brooklyn.rest.api.CatalogApi;
import org.apache.brooklyn.rest.api.EffectorApi;
import org.apache.brooklyn.rest.api.EntityApi;
import org.apache.brooklyn.rest.api.EntityConfigApi;
import org.apache.brooklyn.rest.api.LocationApi;
import org.apache.brooklyn.rest.api.PolicyApi;
import org.apache.brooklyn.rest.api.PolicyConfigApi;
import org.apache.brooklyn.rest.api.ScriptApi;
import org.apache.brooklyn.rest.api.SensorApi;
import org.apache.brooklyn.rest.api.ServerApi;
import org.apache.brooklyn.rest.api.UsageApi;
import org.apache.brooklyn.rest.api.VersionApi;
import org.apache.brooklyn.rest.client.util.http.BuiltResponsePreservingError;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.net.Urls;
import org.apache.brooklyn.util.os.Os;
import io.swagger.annotations.ApiOperation;
/**
* @author Adam Lowe
*/
@SuppressWarnings("deprecation")
public class BrooklynApi {
private final String target;
private final ClientExecutor clientExecutor;
private final int maxPoolSize;
private final int timeOutInMillis;
private static final Logger LOG = LoggerFactory.getLogger(BrooklynApi.class);
/**
* @deprecated since 0.9.0. Use {@link BrooklynApi#newInstance(String)} instead
*/
@Deprecated
public BrooklynApi(URL endpoint) {
this(checkNotNull(endpoint, "endpoint").toString());
}
/**
* @deprecated since 0.9.0. Use {@link BrooklynApi#newInstance(String)} instead
*/
@Deprecated
public BrooklynApi(String endpoint) {
// username/password cannot be null, but credentials can
this(endpoint, null);
}
/**
* @deprecated since 0.9.0. Use {@link BrooklynApi#newInstance(String, String, String)} instead
*/
@Deprecated
public BrooklynApi(URL endpoint, String username, String password) {
this(endpoint.toString(), new UsernamePasswordCredentials(username, password));
}
/**
* @deprecated since 0.9.0. Use {@link BrooklynApi#newInstance(String, String, String)} instead
*/
@Deprecated
public BrooklynApi(String endpoint, String username, String password) {
this(endpoint, new UsernamePasswordCredentials(username, password));
}
/**
* @deprecated since 0.9.0. Use {@link BrooklynApi#newInstance(String, String, String)} instead
*/
@Deprecated
public BrooklynApi(URL endpoint, @Nullable Credentials credentials) {
this(endpoint.toString(), credentials);
}
/**
* Creates a BrooklynApi using an HTTP connection pool
*
* @deprecated since 0.9.0. Use {@link BrooklynApi#newInstance(String, String, String)} instead
*/
@Deprecated
public BrooklynApi(String endpoint, @Nullable Credentials credentials) {
this(endpoint, credentials, 20, 5000);
}
/**
* Creates a BrooklynApi using a custom ClientExecutor
*
* @param endpoint the Brooklyn endpoint
* @param clientExecutor the ClientExecutor
* @see #getClientExecutor(org.apache.http.auth.Credentials)
*/
public BrooklynApi(URL endpoint, ClientExecutor clientExecutor) {
this.target = addV1SuffixIfNeeded(checkNotNull(endpoint, "endpoint").toString());
this.maxPoolSize = -1;
this.timeOutInMillis = -1;
this.clientExecutor = checkNotNull(clientExecutor, "clientExecutor");
}
/**
* Creates a BrooklynApi using an HTTP connection pool
*
* @param endpoint the Brooklyn endpoint
* @param credentials user credentials or null
* @param maxPoolSize maximum pool size
* @param timeOutInMillis connection timeout in milliseconds
*/
public BrooklynApi(String endpoint, @Nullable Credentials credentials, int maxPoolSize, int timeOutInMillis) {
try {
new URL(checkNotNull(endpoint, "endpoint"));
} catch (MalformedURLException e) {
throw new IllegalArgumentException(e);
}
this.target = addV1SuffixIfNeeded(endpoint);
this.maxPoolSize = maxPoolSize;
this.timeOutInMillis = timeOutInMillis;
this.clientExecutor = getClientExecutor(credentials);
}
private String addV1SuffixIfNeeded(String endpoint) {
if (!endpoint.endsWith("/v1/") && !endpoint.endsWith("/v1")) {
return Urls.mergePaths(endpoint, "v1");
} else {
return endpoint;
}
}
private Supplier connectionManagerSupplier = Suppliers.memoize(new Supplier() {
@Override
public PoolingHttpClientConnectionManager get() {
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
connManager.setMaxTotal(maxPoolSize);
connManager.setDefaultMaxPerRoute(maxPoolSize);
return connManager;
}
});
private Supplier reqConfSupplier = Suppliers.memoize(new Supplier() {
@Override
public RequestConfig get() {
return RequestConfig.custom()
.setConnectTimeout(timeOutInMillis)
.setConnectionRequestTimeout(timeOutInMillis)
.build();
}
});
/**
* Creates a ClientExecutor for this BrooklynApi
*/
protected ClientExecutor getClientExecutor(Credentials credentials) {
CredentialsProvider provider = new BasicCredentialsProvider();
if (credentials != null) provider.setCredentials(AuthScope.ANY, credentials);
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultCredentialsProvider(provider)
.setDefaultRequestConfig(reqConfSupplier.get())
.setConnectionManager(connectionManagerSupplier.get())
.build();
return new ApacheHttpClient4Executor(httpClient);
}
/**
* Creates a BrooklynApi using an HTTP connection pool
*
* @param endpoint the Brooklyn endpoint
* @return a new BrooklynApi instance
*/
public static BrooklynApi newInstance(String endpoint) {
return new BrooklynApi(endpoint, null);
}
/**
* Creates a BrooklynApi using an HTTP connection pool
*
* @param endpoint the Brooklyn endpoint
* @param maxPoolSize maximum connection pool size
* @param timeOutInMillis connection timeout in millisecond
* @return a new BrooklynApi instance
*/
public static BrooklynApi newInstance(String endpoint, int maxPoolSize, int timeOutInMillis) {
return new BrooklynApi(endpoint, null, maxPoolSize, timeOutInMillis);
}
/**
* Creates a BrooklynApi using an HTTP connection pool
*
* @param endpoint the Brooklyn endpoint
* @param username for authentication
* @param password for authentication
* @return a new BrooklynApi instance
*/
public static BrooklynApi newInstance(String endpoint, String username, String password) {
return new BrooklynApi(endpoint, new UsernamePasswordCredentials(username, password));
}
/**
* Creates a BrooklynApi using an HTTP connection pool
*
* @param endpoint the Brooklyn endpoint
* @param username for authentication
* @param password for authentication
* @param maxPoolSize maximum connection pool size
* @param timeOutInMillis connection timeout in millisecond
* @return a new BrooklynApi instance
*/
public static BrooklynApi newInstance(String endpoint, String username, String password, int maxPoolSize, int timeOutInMillis) {
return new BrooklynApi(endpoint, new UsernamePasswordCredentials(username, password), maxPoolSize, timeOutInMillis);
}
@SuppressWarnings("unchecked")
private T proxy(Class clazz) {
final T result0 = ProxyFactory.create(clazz, target, clientExecutor);
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class>[] { clazz }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
Object result1 = method.invoke(result0, args);
Class> type = String.class;
if (result1 instanceof Response) {
Response resp = (Response)result1;
if(isStatusCodeHealthy(resp.getStatus()) && method.isAnnotationPresent(ApiOperation.class)) {
type = getClassFromMethodAnnotationOrDefault(method, type);
}
// wrap the original response so it self-closes
result1 = BuiltResponsePreservingError.copyResponseAndClose(resp, type);
}
return result1;
} catch (Throwable e) {
if (e instanceof InvocationTargetException) {
// throw the original exception
e = ((InvocationTargetException)e).getTargetException();
}
throw Exceptions.propagate(e);
}
}
private boolean isStatusCodeHealthy(int code) { return (code>=200 && code<=299); }
private Class> getClassFromMethodAnnotationOrDefault(Method method, Class> def){
Class> type;
try{
type = method.getAnnotation(ApiOperation.class).response();
} catch (Exception e) {
type = def;
LOG.debug("Unable to get class from annotation: {}. Defaulting to {}", e.getMessage(), def.getName());
Exceptions.propagateIfFatal(e);
}
return type;
}
});
}
public ActivityApi getActivityApi() {
return proxy(ActivityApi.class);
}
public ApplicationApi getApplicationApi() {
return proxy(ApplicationApi.class);
}
public CatalogApi getCatalogApi() {
return proxy(CatalogApi.class);
}
public EffectorApi getEffectorApi() {
return proxy(EffectorApi.class);
}
public EntityConfigApi getEntityConfigApi() {
return proxy(EntityConfigApi.class);
}
public EntityApi getEntityApi() {
return proxy(EntityApi.class);
}
public LocationApi getLocationApi() {
return proxy(LocationApi.class);
}
public PolicyConfigApi getPolicyConfigApi() {
return proxy(PolicyConfigApi.class);
}
public PolicyApi getPolicyApi() {
return proxy(PolicyApi.class);
}
public ScriptApi getScriptApi() {
return proxy(ScriptApi.class);
}
public SensorApi getSensorApi() {
return proxy(SensorApi.class);
}
public ServerApi getServerApi() {
return proxy(ServerApi.class);
}
public UsageApi getUsageApi() {
return proxy(UsageApi.class);
}
public VersionApi getVersionApi() {
return proxy(VersionApi.class);
}
public AccessApi getAccessApi() {
return proxy(AccessApi.class);
}
public static T getEntity(Response response, Class type) {
if (response instanceof ClientResponse) {
ClientResponse> clientResponse = (ClientResponse>) response;
return clientResponse.getEntity(type);
} else if (response instanceof BuiltResponse) {
// Handle BuiltResponsePreservingError turning objects into Strings
if (response.getEntity() instanceof String && !type.equals(String.class)) {
return new Gson().fromJson(response.getEntity().toString(), type);
}
}
// Last-gasp attempt.
return type.cast(response.getEntity());
}
public static T getEntity(Response response, GenericType type) {
if (response instanceof ClientResponse) {
ClientResponse> clientResponse = (ClientResponse>) response;
return clientResponse.getEntity(type);
} else if (response instanceof BuiltResponse) {
// Handle BuiltResponsePreservingError turning objects into Strings
if (response.getEntity() instanceof String) {
return new Gson().fromJson(response.getEntity().toString(), type.getGenericType());
}
}
// Last-gasp attempt.
return type.getType().cast(response.getEntity());
}
/**
* @deprecated since 0.8.0-incubating. Use {@link #getEntity(Response, GenericType)} instead.
*/
@Deprecated
public static T getEntityGeneric(Response response, GenericType type) {
return getEntity(response, type);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy