brooklyn-rest-client: add org.apache package prefix
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/c5256b18 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/c5256b18 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/c5256b18 Branch: refs/heads/master Commit: c5256b186e13e67b356e3f68825858095add30ee Parents: ffbd6ef Author: Ciprian Ciubotariu <[email protected]> Authored: Thu Jul 16 11:27:15 2015 +0300 Committer: Ciprian Ciubotariu <[email protected]> Committed: Tue Aug 4 17:19:12 2015 +0300 ---------------------------------------------------------------------- .../java/brooklyn/rest/client/BrooklynApi.java | 262 ------------------- .../util/http/BuiltResponsePreservingError.java | 78 ------ .../brooklyn/rest/client/BrooklynApi.java | 262 +++++++++++++++++++ .../util/http/BuiltResponsePreservingError.java | 78 ++++++ .../ApplicationResourceIntegrationTest.java | 190 -------------- .../rest/client/BrooklynApiRestClientTest.java | 134 ---------- .../ApplicationResourceIntegrationTest.java | 190 ++++++++++++++ .../rest/client/BrooklynApiRestClientTest.java | 134 ++++++++++ 8 files changed, 664 insertions(+), 664 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c5256b18/usage/rest-client/src/main/java/brooklyn/rest/client/BrooklynApi.java ---------------------------------------------------------------------- diff --git a/usage/rest-client/src/main/java/brooklyn/rest/client/BrooklynApi.java b/usage/rest-client/src/main/java/brooklyn/rest/client/BrooklynApi.java deleted file mode 100644 index f57b4bd..0000000 --- a/usage/rest-client/src/main/java/brooklyn/rest/client/BrooklynApi.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * 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 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 org.apache.http.auth.AuthScope; -import org.apache.http.auth.Credentials; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.impl.client.DefaultHttpClient; -import org.jboss.resteasy.client.ClientExecutor; -import org.jboss.resteasy.client.ClientRequest; -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 brooklyn.rest.api.AccessApi; -import brooklyn.rest.api.ActivityApi; -import brooklyn.rest.api.ApplicationApi; -import brooklyn.rest.api.CatalogApi; -import brooklyn.rest.api.EffectorApi; -import brooklyn.rest.api.EntityApi; -import brooklyn.rest.api.EntityConfigApi; -import brooklyn.rest.api.LocationApi; -import brooklyn.rest.api.PolicyApi; -import brooklyn.rest.api.PolicyConfigApi; -import brooklyn.rest.api.ScriptApi; -import brooklyn.rest.api.SensorApi; -import brooklyn.rest.api.ServerApi; -import brooklyn.rest.api.UsageApi; -import brooklyn.rest.api.VersionApi; -import brooklyn.util.exceptions.Exceptions; -import brooklyn.util.http.BuiltResponsePreservingError; - -import com.wordnik.swagger.core.ApiOperation; - -/** - * @author Adam Lowe - */ -@SuppressWarnings("deprecation") -public class BrooklynApi { - - private final String target; - private final ClientExecutor clientExecutor; - private static final Logger LOG = LoggerFactory.getLogger(BrooklynApi.class); - - public BrooklynApi(URL endpoint) { - this(checkNotNull(endpoint, "endpoint").toString()); - } - - public BrooklynApi(String endpoint) { - // username/password cannot be null, but credentials can - this(endpoint, null); - } - - public BrooklynApi(URL endpoint, String username, String password) { - this(endpoint.toString(), new UsernamePasswordCredentials(username, password)); - } - - public BrooklynApi(String endpoint, String username, String password) { - this(endpoint, new UsernamePasswordCredentials(username, password)); - } - - public BrooklynApi(URL endpoint, @Nullable Credentials credentials) { - this(endpoint.toString(), credentials); - } - - public BrooklynApi(String endpoint, @Nullable Credentials credentials) { - try { - new URL(checkNotNull(endpoint, "endpoint")); - } catch (MalformedURLException e) { - throw new IllegalArgumentException(e); - } - - this.target = endpoint; - if (credentials != null) { - DefaultHttpClient httpClient = new DefaultHttpClient(); - httpClient.getCredentialsProvider().setCredentials(AuthScope.ANY, credentials); - this.clientExecutor = new ApacheHttpClient4Executor(httpClient); - } else { - this.clientExecutor = ClientRequest.getDefaultExecutor(); - } - } - - public BrooklynApi(URL endpoint, ClientExecutor clientExecutor) { - this.target = checkNotNull(endpoint, "endpoint").toString(); - this.clientExecutor = checkNotNull(clientExecutor, "clientExecutor"); - } - - @SuppressWarnings("unchecked") - private <T> T proxy(Class<T> 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{ - String responseClass = method.getAnnotation(ApiOperation.class).responseClass(); - type = Class.forName(responseClass); - } 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> T getEntity(Response response, Class<T> 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> T getEntity(Response response, GenericType<T> 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 Use {@link #getEntity(Response, GenericType)} instead. - */ - @Deprecated - public static <T> T getEntityGeneric(Response response, GenericType<T> type) { - return getEntity(response, type); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c5256b18/usage/rest-client/src/main/java/brooklyn/util/http/BuiltResponsePreservingError.java ---------------------------------------------------------------------- diff --git a/usage/rest-client/src/main/java/brooklyn/util/http/BuiltResponsePreservingError.java b/usage/rest-client/src/main/java/brooklyn/util/http/BuiltResponsePreservingError.java deleted file mode 100644 index 3bd88e6..0000000 --- a/usage/rest-client/src/main/java/brooklyn/util/http/BuiltResponsePreservingError.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 brooklyn.util.http; - -import java.lang.annotation.Annotation; - -import javax.ws.rs.core.Response; - -import org.jboss.resteasy.client.core.BaseClientResponse; -import org.jboss.resteasy.core.Headers; -import org.jboss.resteasy.specimpl.BuiltResponse; - -import brooklyn.util.exceptions.Exceptions; - -/** - * Allows wrapping a {@link Response} with the stream fully read and closed so that the client can be re-used. - * <p> - * The entity may be stored as a string as type info is not available when it is deserialized, - * and that's a relatively convenient common format. - * - * TODO It would be nice to support other parsing, storing the byte array. - */ -public class BuiltResponsePreservingError extends BuiltResponse { - - private Throwable error; - - public BuiltResponsePreservingError(int status, Headers<Object> headers, Object entity, Annotation[] annotations, Throwable error) { - super(status, headers, entity, annotations); - this.error = error; - } - - @SuppressWarnings("deprecation") - public static <T> Response copyResponseAndClose(Response source, Class<T> type) { - int status = -1; - Headers<Object> headers = new Headers<Object>(); - Object entity = null; - try { - status = source.getStatus(); - if (source instanceof BaseClientResponse) - headers.putAll(((BaseClientResponse<?>)source).getMetadata()); - if (source instanceof org.jboss.resteasy.client.ClientResponse) { - entity = ((org.jboss.resteasy.client.ClientResponse<?>)source).getEntity(type); - } else { - entity = source.getEntity(); - } - return new BuiltResponsePreservingError(status, headers, entity, new Annotation[0], null); - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - return new BuiltResponsePreservingError(status, headers, entity, new Annotation[0], e); - } finally { - if (source instanceof BaseClientResponse) - ((BaseClientResponse<?>)source).close(); - } - } - - @Override - public Object getEntity() { - if (error!=null) Exceptions.propagate(error); - return super.getEntity(); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c5256b18/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/BrooklynApi.java ---------------------------------------------------------------------- diff --git a/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/BrooklynApi.java b/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/BrooklynApi.java new file mode 100644 index 0000000..f4b47e6 --- /dev/null +++ b/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/BrooklynApi.java @@ -0,0 +1,262 @@ +/* + * 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 org.apache.http.auth.AuthScope; +import org.apache.http.auth.Credentials; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.impl.client.DefaultHttpClient; +import org.jboss.resteasy.client.ClientExecutor; +import org.jboss.resteasy.client.ClientRequest; +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 brooklyn.rest.api.AccessApi; +import brooklyn.rest.api.ActivityApi; +import brooklyn.rest.api.ApplicationApi; +import brooklyn.rest.api.CatalogApi; +import brooklyn.rest.api.EffectorApi; +import brooklyn.rest.api.EntityApi; +import brooklyn.rest.api.EntityConfigApi; +import brooklyn.rest.api.LocationApi; +import brooklyn.rest.api.PolicyApi; +import brooklyn.rest.api.PolicyConfigApi; +import brooklyn.rest.api.ScriptApi; +import brooklyn.rest.api.SensorApi; +import brooklyn.rest.api.ServerApi; +import brooklyn.rest.api.UsageApi; +import brooklyn.rest.api.VersionApi; +import brooklyn.util.exceptions.Exceptions; +import org.apache.brooklyn.util.http.BuiltResponsePreservingError; + +import com.wordnik.swagger.core.ApiOperation; + +/** + * @author Adam Lowe + */ +@SuppressWarnings("deprecation") +public class BrooklynApi { + + private final String target; + private final ClientExecutor clientExecutor; + private static final Logger LOG = LoggerFactory.getLogger(BrooklynApi.class); + + public BrooklynApi(URL endpoint) { + this(checkNotNull(endpoint, "endpoint").toString()); + } + + public BrooklynApi(String endpoint) { + // username/password cannot be null, but credentials can + this(endpoint, null); + } + + public BrooklynApi(URL endpoint, String username, String password) { + this(endpoint.toString(), new UsernamePasswordCredentials(username, password)); + } + + public BrooklynApi(String endpoint, String username, String password) { + this(endpoint, new UsernamePasswordCredentials(username, password)); + } + + public BrooklynApi(URL endpoint, @Nullable Credentials credentials) { + this(endpoint.toString(), credentials); + } + + public BrooklynApi(String endpoint, @Nullable Credentials credentials) { + try { + new URL(checkNotNull(endpoint, "endpoint")); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(e); + } + + this.target = endpoint; + if (credentials != null) { + DefaultHttpClient httpClient = new DefaultHttpClient(); + httpClient.getCredentialsProvider().setCredentials(AuthScope.ANY, credentials); + this.clientExecutor = new ApacheHttpClient4Executor(httpClient); + } else { + this.clientExecutor = ClientRequest.getDefaultExecutor(); + } + } + + public BrooklynApi(URL endpoint, ClientExecutor clientExecutor) { + this.target = checkNotNull(endpoint, "endpoint").toString(); + this.clientExecutor = checkNotNull(clientExecutor, "clientExecutor"); + } + + @SuppressWarnings("unchecked") + private <T> T proxy(Class<T> 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{ + String responseClass = method.getAnnotation(ApiOperation.class).responseClass(); + type = Class.forName(responseClass); + } 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> T getEntity(Response response, Class<T> 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> T getEntity(Response response, GenericType<T> 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 Use {@link #getEntity(Response, GenericType)} instead. + */ + @Deprecated + public static <T> T getEntityGeneric(Response response, GenericType<T> type) { + return getEntity(response, type); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c5256b18/usage/rest-client/src/main/java/org/apache/brooklyn/util/http/BuiltResponsePreservingError.java ---------------------------------------------------------------------- diff --git a/usage/rest-client/src/main/java/org/apache/brooklyn/util/http/BuiltResponsePreservingError.java b/usage/rest-client/src/main/java/org/apache/brooklyn/util/http/BuiltResponsePreservingError.java new file mode 100644 index 0000000..32a5dfb --- /dev/null +++ b/usage/rest-client/src/main/java/org/apache/brooklyn/util/http/BuiltResponsePreservingError.java @@ -0,0 +1,78 @@ +/* + * 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.util.http; + +import java.lang.annotation.Annotation; + +import javax.ws.rs.core.Response; + +import org.jboss.resteasy.client.core.BaseClientResponse; +import org.jboss.resteasy.core.Headers; +import org.jboss.resteasy.specimpl.BuiltResponse; + +import brooklyn.util.exceptions.Exceptions; + +/** + * Allows wrapping a {@link Response} with the stream fully read and closed so that the client can be re-used. + * <p> + * The entity may be stored as a string as type info is not available when it is deserialized, + * and that's a relatively convenient common format. + * + * TODO It would be nice to support other parsing, storing the byte array. + */ +public class BuiltResponsePreservingError extends BuiltResponse { + + private Throwable error; + + public BuiltResponsePreservingError(int status, Headers<Object> headers, Object entity, Annotation[] annotations, Throwable error) { + super(status, headers, entity, annotations); + this.error = error; + } + + @SuppressWarnings("deprecation") + public static <T> Response copyResponseAndClose(Response source, Class<T> type) { + int status = -1; + Headers<Object> headers = new Headers<Object>(); + Object entity = null; + try { + status = source.getStatus(); + if (source instanceof BaseClientResponse) + headers.putAll(((BaseClientResponse<?>)source).getMetadata()); + if (source instanceof org.jboss.resteasy.client.ClientResponse) { + entity = ((org.jboss.resteasy.client.ClientResponse<?>)source).getEntity(type); + } else { + entity = source.getEntity(); + } + return new BuiltResponsePreservingError(status, headers, entity, new Annotation[0], null); + } catch (Exception e) { + Exceptions.propagateIfFatal(e); + return new BuiltResponsePreservingError(status, headers, entity, new Annotation[0], e); + } finally { + if (source instanceof BaseClientResponse) + ((BaseClientResponse<?>)source).close(); + } + } + + @Override + public Object getEntity() { + if (error!=null) Exceptions.propagate(error); + return super.getEntity(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c5256b18/usage/rest-client/src/test/java/brooklyn/rest/client/ApplicationResourceIntegrationTest.java ---------------------------------------------------------------------- diff --git a/usage/rest-client/src/test/java/brooklyn/rest/client/ApplicationResourceIntegrationTest.java b/usage/rest-client/src/test/java/brooklyn/rest/client/ApplicationResourceIntegrationTest.java deleted file mode 100644 index a55aa45..0000000 --- a/usage/rest-client/src/test/java/brooklyn/rest/client/ApplicationResourceIntegrationTest.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * 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 brooklyn.rest.client; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -import java.util.Collection; - -import javax.ws.rs.core.Response; - -import org.eclipse.jetty.server.Server; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import brooklyn.entity.Application; -import brooklyn.entity.basic.Lifecycle; -import brooklyn.entity.basic.StartableApplication; -import brooklyn.location.basic.BasicLocationRegistry; -import brooklyn.management.ManagementContext; -import brooklyn.management.internal.LocalManagementContext; -import brooklyn.rest.BrooklynRestApiLauncher; -import brooklyn.rest.BrooklynRestApiLauncherTest; -import brooklyn.rest.domain.ApplicationSpec; -import brooklyn.rest.domain.ApplicationSummary; -import brooklyn.rest.domain.EntitySpec; -import brooklyn.rest.domain.EntitySummary; -import brooklyn.rest.domain.SensorSummary; -import brooklyn.test.Asserts; -import brooklyn.util.time.Duration; - -import com.google.common.base.Predicate; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; - -@Test(singleThreaded = true) -public class ApplicationResourceIntegrationTest { - - private static final Logger log = LoggerFactory.getLogger(ApplicationResourceIntegrationTest.class); - - private static final Duration LONG_WAIT = Duration.minutes(10); - - private final String redisSpec = "{\"name\": \"redis-app\", \"type\": \"brooklyn.entity.nosql.redis.RedisStore\", \"locations\": [ \"localhost\"]}"; - - private final ApplicationSpec legacyRedisSpec = ApplicationSpec.builder().name("redis-legacy-app") - .entities(ImmutableSet.of(new EntitySpec("redis-ent", "brooklyn.entity.nosql.redis.RedisStore"))) - .locations(ImmutableSet.of("localhost")) - .build(); - - private ManagementContext manager; - - protected synchronized ManagementContext getManagementContext() throws Exception { - if (manager == null) { - manager = new LocalManagementContext(); - BrooklynRestApiLauncherTest.forceUseOfDefaultCatalogWithJavaClassPath(manager); - BasicLocationRegistry.setupLocationRegistryForTesting(manager); - BrooklynRestApiLauncherTest.enableAnyoneLogin(manager); - } - return manager; - } - - BrooklynApi api; - - @BeforeClass(groups = "Integration") - public void setUp() throws Exception { - Server server = BrooklynRestApiLauncher.launcher() - .managementContext(getManagementContext()) - .start(); - - api = new BrooklynApi("http://localhost:" + server.getConnectors()[0].getPort() + "/"); - } - - @AfterClass(alwaysRun = true) - public void tearDown() throws Exception { - for (Application app : getManagementContext().getApplications()) { - try { - ((StartableApplication) app).stop(); - } catch (Exception e) { - log.warn("Error stopping app " + app + " during test teardown: " + e); - } - } - } - - @Test(groups = "Integration") - public void testDeployRedisApplication() throws Exception { - Response response = api.getApplicationApi().createPoly(redisSpec.getBytes()); - assertEquals(response.getStatus(), 201); - assertEquals(getManagementContext().getApplications().size(), 1); - final String entityId = getManagementContext().getApplications().iterator().next().getChildren().iterator().next().getId(); - assertServiceStateEventually("redis-app", entityId, Lifecycle.RUNNING, LONG_WAIT); - } - - @Test(groups = "Integration", dependsOnMethods = "testDeployRedisApplication") - public void testDeployLegacyRedisApplication() throws Exception { - @SuppressWarnings("deprecation") - Response response = api.getApplicationApi().create(legacyRedisSpec); - assertEquals(response.getStatus(), 201); - assertEquals(getManagementContext().getApplications().size(), 2); - assertServiceStateEventually("redis-legacy-app", "redis-ent", Lifecycle.RUNNING, LONG_WAIT); - - // Tear the app down so it doesn't interfere with other tests - Response deleteResponse = api.getApplicationApi().delete("redis-legacy-app"); - assertEquals(deleteResponse.getStatus(), 202); - assertEquals(getManagementContext().getApplications().size(), 1); - } - - @Test(groups = "Integration", dependsOnMethods = "testDeployRedisApplication") - public void testListEntities() { - Collection<EntitySummary> entities = api.getEntityApi().list("redis-app"); - Assert.assertFalse(entities.isEmpty()); - } - - @Test(groups = "Integration", dependsOnMethods = "testDeployRedisApplication") - public void testListSensorsRedis() throws Exception { - String entityId = getManagementContext().getApplications().iterator().next().getChildren().iterator().next().getId(); - Collection<SensorSummary> sensors = api.getSensorApi().list("redis-app", entityId); - assertTrue(sensors.size() > 0); - SensorSummary uptime = Iterables.find(sensors, new Predicate<SensorSummary>() { - @Override - public boolean apply(SensorSummary sensorSummary) { - return sensorSummary.getName().equals("redis.uptime"); - } - }); - assertEquals(uptime.getType(), "java.lang.Integer"); - } - - @Test(groups = "Integration", dependsOnMethods = {"testListSensorsRedis", "testListEntities"}) - public void testTriggerRedisStopEffector() throws Exception { - final String entityId = getManagementContext().getApplications().iterator().next().getChildren().iterator().next().getId(); - Response response = api.getEffectorApi().invoke("redis-app", entityId, "stop", "5000", ImmutableMap.<String, Object>of()); - - assertEquals(response.getStatus(), Response.Status.ACCEPTED.getStatusCode()); - assertServiceStateEventually("redis-app", entityId, Lifecycle.STOPPED, LONG_WAIT); - } - - @Test(groups = "Integration", dependsOnMethods = "testTriggerRedisStopEffector") - public void testDeleteRedisApplication() throws Exception { - int size = getManagementContext().getApplications().size(); - Response response = api.getApplicationApi().delete("redis-app"); - Assert.assertNotNull(response); - try { - Asserts.succeedsEventually(ImmutableMap.of("timeout", Duration.minutes(1)), new Runnable() { - public void run() { - try { - ApplicationSummary summary = api.getApplicationApi().get("redis-app"); - fail("Redis app failed to disappear: summary="+summary); - } catch (Exception failure) { - // expected -- it will be a ClientResponseFailure but that class is deprecated so catching all - // and asserting contains the word 404 - Assert.assertTrue(failure.toString().indexOf("404") >= 0, "wrong failure, got: "+failure); - } - }}); - } catch (Exception failure) { - // expected -- as above - Assert.assertTrue(failure.toString().indexOf("404") >= 0, "wrong failure, got: "+failure); - } - - assertEquals(getManagementContext().getApplications().size(), size - 1); - } - - private void assertServiceStateEventually(final String app, final String entity, final Lifecycle state, Duration timeout) { - Asserts.succeedsEventually(ImmutableMap.of("timeout", timeout), new Runnable() { - public void run() { - Object status = api.getSensorApi().get(app, entity, "service.state", false); - assertTrue(state.toString().equalsIgnoreCase(status.toString()), "status="+status); - }}); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c5256b18/usage/rest-client/src/test/java/brooklyn/rest/client/BrooklynApiRestClientTest.java ---------------------------------------------------------------------- diff --git a/usage/rest-client/src/test/java/brooklyn/rest/client/BrooklynApiRestClientTest.java b/usage/rest-client/src/test/java/brooklyn/rest/client/BrooklynApiRestClientTest.java deleted file mode 100644 index 7a320e7..0000000 --- a/usage/rest-client/src/test/java/brooklyn/rest/client/BrooklynApiRestClientTest.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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 brooklyn.rest.client; - -import java.util.List; -import java.util.Map; - -import javax.ws.rs.core.Response; - -import org.eclipse.jetty.server.Server; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import brooklyn.entity.Application; -import brooklyn.entity.basic.Entities; -import brooklyn.entity.basic.StartableApplication; -import brooklyn.location.basic.BasicLocationRegistry; -import brooklyn.management.ManagementContext; -import brooklyn.management.internal.LocalManagementContext; -import brooklyn.rest.BrooklynRestApiLauncher; -import brooklyn.rest.BrooklynRestApiLauncherTest; -import brooklyn.rest.domain.ApplicationSummary; -import brooklyn.rest.domain.CatalogLocationSummary; -import brooklyn.rest.security.provider.TestSecurityProvider; -import brooklyn.test.HttpTestUtils; -import brooklyn.test.entity.TestEntity; - -@Test -public class BrooklynApiRestClientTest { - - private static final Logger log = LoggerFactory.getLogger(BrooklynApiRestClientTest.class); - - private ManagementContext manager; - - private BrooklynApi api; - - protected synchronized ManagementContext getManagementContext() throws Exception { - if (manager == null) { - manager = new LocalManagementContext(); - BrooklynRestApiLauncherTest.forceUseOfDefaultCatalogWithJavaClassPath(manager); - BasicLocationRegistry.setupLocationRegistryForTesting(manager); - BrooklynRestApiLauncherTest.enableAnyoneLogin(manager); - } - return manager; - } - - @BeforeClass - public void setUp() throws Exception { - Server server = BrooklynRestApiLauncher.launcher() - .managementContext(manager) - .securityProvider(TestSecurityProvider.class) - .start(); - - api = new BrooklynApi("http://localhost:" + server.getConnectors()[0].getPort() + "/", - TestSecurityProvider.USER, TestSecurityProvider.PASSWORD); - } - - @AfterClass(alwaysRun = true) - public void tearDown() throws Exception { - for (Application app : getManagementContext().getApplications()) { - try { - ((StartableApplication) app).stop(); - } catch (Exception e) { - log.warn("Error stopping app " + app + " during test teardown: " + e); - } - } - Entities.destroyAll(getManagementContext()); - } - - public void testLocationApi() throws Exception { - log.info("Testing location API"); - Map<String, Map<String, Object>> locations = api.getLocationApi().getLocatedLocations(); - log.info("locations located are: "+locations); - } - - public void testCatalogApiLocations() throws Exception { - List<CatalogLocationSummary> locations = api.getCatalogApi().listLocations(".*", null, false); - log.info("locations from catalog are: "+locations); - } - - public void testApplicationApiList() throws Exception { - List<ApplicationSummary> apps = api.getApplicationApi().list(null); - log.info("apps are: "+apps); - } - - public void testApplicationApiCreate() throws Exception { - Response r1 = api.getApplicationApi().createFromYaml("name: test-1234\n" - + "services: [ { type: "+TestEntity.class.getName()+" } ]"); - HttpTestUtils.assertHealthyStatusCode(r1.getStatus()); - log.info("creation result: "+r1.getEntity()); - List<ApplicationSummary> apps = api.getApplicationApi().list(null); - log.info("apps with test: "+apps); - Assert.assertTrue(apps.toString().contains("test-1234"), "should have had test-1234 as an app; instead: "+apps); - } - - public void testApplicationApiHandledError() throws Exception { - Response r1 = api.getApplicationApi().createFromYaml("name: test"); - Assert.assertTrue(r1.getStatus()/100 != 2, "needed an unhealthy status, not "+r1.getStatus()); - Object entity = r1.getEntity(); - Assert.assertTrue(entity.toString().indexOf("Unrecognized application blueprint format: no services defined")>=0, - "Missing expected text in response: "+entity.toString()); - } - - public void testApplicationApiThrownError() throws Exception { - try { - ApplicationSummary summary = api.getApplicationApi().get("test-5678"); - Assert.fail("Should have thrown, not given: "+summary); - } catch (Exception e) { - e.printStackTrace(); - Assert.assertTrue(e.toString().toLowerCase().contains("not found"), - "Missing expected text in response: "+e.toString()); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c5256b18/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/ApplicationResourceIntegrationTest.java ---------------------------------------------------------------------- diff --git a/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/ApplicationResourceIntegrationTest.java b/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/ApplicationResourceIntegrationTest.java new file mode 100644 index 0000000..02c19bb --- /dev/null +++ b/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/ApplicationResourceIntegrationTest.java @@ -0,0 +1,190 @@ +/* + * 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 org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +import java.util.Collection; + +import javax.ws.rs.core.Response; + +import org.eclipse.jetty.server.Server; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import brooklyn.entity.Application; +import brooklyn.entity.basic.Lifecycle; +import brooklyn.entity.basic.StartableApplication; +import brooklyn.location.basic.BasicLocationRegistry; +import brooklyn.management.ManagementContext; +import brooklyn.management.internal.LocalManagementContext; +import brooklyn.rest.BrooklynRestApiLauncher; +import brooklyn.rest.BrooklynRestApiLauncherTest; +import brooklyn.rest.domain.ApplicationSpec; +import brooklyn.rest.domain.ApplicationSummary; +import brooklyn.rest.domain.EntitySpec; +import brooklyn.rest.domain.EntitySummary; +import brooklyn.rest.domain.SensorSummary; +import brooklyn.test.Asserts; +import brooklyn.util.time.Duration; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; + +@Test(singleThreaded = true) +public class ApplicationResourceIntegrationTest { + + private static final Logger log = LoggerFactory.getLogger(ApplicationResourceIntegrationTest.class); + + private static final Duration LONG_WAIT = Duration.minutes(10); + + private final String redisSpec = "{\"name\": \"redis-app\", \"type\": \"brooklyn.entity.nosql.redis.RedisStore\", \"locations\": [ \"localhost\"]}"; + + private final ApplicationSpec legacyRedisSpec = ApplicationSpec.builder().name("redis-legacy-app") + .entities(ImmutableSet.of(new EntitySpec("redis-ent", "brooklyn.entity.nosql.redis.RedisStore"))) + .locations(ImmutableSet.of("localhost")) + .build(); + + private ManagementContext manager; + + protected synchronized ManagementContext getManagementContext() throws Exception { + if (manager == null) { + manager = new LocalManagementContext(); + BrooklynRestApiLauncherTest.forceUseOfDefaultCatalogWithJavaClassPath(manager); + BasicLocationRegistry.setupLocationRegistryForTesting(manager); + BrooklynRestApiLauncherTest.enableAnyoneLogin(manager); + } + return manager; + } + + BrooklynApi api; + + @BeforeClass(groups = "Integration") + public void setUp() throws Exception { + Server server = BrooklynRestApiLauncher.launcher() + .managementContext(getManagementContext()) + .start(); + + api = new BrooklynApi("http://localhost:" + server.getConnectors()[0].getPort() + "/"); + } + + @AfterClass(alwaysRun = true) + public void tearDown() throws Exception { + for (Application app : getManagementContext().getApplications()) { + try { + ((StartableApplication) app).stop(); + } catch (Exception e) { + log.warn("Error stopping app " + app + " during test teardown: " + e); + } + } + } + + @Test(groups = "Integration") + public void testDeployRedisApplication() throws Exception { + Response response = api.getApplicationApi().createPoly(redisSpec.getBytes()); + assertEquals(response.getStatus(), 201); + assertEquals(getManagementContext().getApplications().size(), 1); + final String entityId = getManagementContext().getApplications().iterator().next().getChildren().iterator().next().getId(); + assertServiceStateEventually("redis-app", entityId, Lifecycle.RUNNING, LONG_WAIT); + } + + @Test(groups = "Integration", dependsOnMethods = "testDeployRedisApplication") + public void testDeployLegacyRedisApplication() throws Exception { + @SuppressWarnings("deprecation") + Response response = api.getApplicationApi().create(legacyRedisSpec); + assertEquals(response.getStatus(), 201); + assertEquals(getManagementContext().getApplications().size(), 2); + assertServiceStateEventually("redis-legacy-app", "redis-ent", Lifecycle.RUNNING, LONG_WAIT); + + // Tear the app down so it doesn't interfere with other tests + Response deleteResponse = api.getApplicationApi().delete("redis-legacy-app"); + assertEquals(deleteResponse.getStatus(), 202); + assertEquals(getManagementContext().getApplications().size(), 1); + } + + @Test(groups = "Integration", dependsOnMethods = "testDeployRedisApplication") + public void testListEntities() { + Collection<EntitySummary> entities = api.getEntityApi().list("redis-app"); + Assert.assertFalse(entities.isEmpty()); + } + + @Test(groups = "Integration", dependsOnMethods = "testDeployRedisApplication") + public void testListSensorsRedis() throws Exception { + String entityId = getManagementContext().getApplications().iterator().next().getChildren().iterator().next().getId(); + Collection<SensorSummary> sensors = api.getSensorApi().list("redis-app", entityId); + assertTrue(sensors.size() > 0); + SensorSummary uptime = Iterables.find(sensors, new Predicate<SensorSummary>() { + @Override + public boolean apply(SensorSummary sensorSummary) { + return sensorSummary.getName().equals("redis.uptime"); + } + }); + assertEquals(uptime.getType(), "java.lang.Integer"); + } + + @Test(groups = "Integration", dependsOnMethods = {"testListSensorsRedis", "testListEntities"}) + public void testTriggerRedisStopEffector() throws Exception { + final String entityId = getManagementContext().getApplications().iterator().next().getChildren().iterator().next().getId(); + Response response = api.getEffectorApi().invoke("redis-app", entityId, "stop", "5000", ImmutableMap.<String, Object>of()); + + assertEquals(response.getStatus(), Response.Status.ACCEPTED.getStatusCode()); + assertServiceStateEventually("redis-app", entityId, Lifecycle.STOPPED, LONG_WAIT); + } + + @Test(groups = "Integration", dependsOnMethods = "testTriggerRedisStopEffector") + public void testDeleteRedisApplication() throws Exception { + int size = getManagementContext().getApplications().size(); + Response response = api.getApplicationApi().delete("redis-app"); + Assert.assertNotNull(response); + try { + Asserts.succeedsEventually(ImmutableMap.of("timeout", Duration.minutes(1)), new Runnable() { + public void run() { + try { + ApplicationSummary summary = api.getApplicationApi().get("redis-app"); + fail("Redis app failed to disappear: summary="+summary); + } catch (Exception failure) { + // expected -- it will be a ClientResponseFailure but that class is deprecated so catching all + // and asserting contains the word 404 + Assert.assertTrue(failure.toString().indexOf("404") >= 0, "wrong failure, got: "+failure); + } + }}); + } catch (Exception failure) { + // expected -- as above + Assert.assertTrue(failure.toString().indexOf("404") >= 0, "wrong failure, got: "+failure); + } + + assertEquals(getManagementContext().getApplications().size(), size - 1); + } + + private void assertServiceStateEventually(final String app, final String entity, final Lifecycle state, Duration timeout) { + Asserts.succeedsEventually(ImmutableMap.of("timeout", timeout), new Runnable() { + public void run() { + Object status = api.getSensorApi().get(app, entity, "service.state", false); + assertTrue(state.toString().equalsIgnoreCase(status.toString()), "status="+status); + }}); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c5256b18/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/BrooklynApiRestClientTest.java ---------------------------------------------------------------------- diff --git a/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/BrooklynApiRestClientTest.java b/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/BrooklynApiRestClientTest.java new file mode 100644 index 0000000..c36a456 --- /dev/null +++ b/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/BrooklynApiRestClientTest.java @@ -0,0 +1,134 @@ +/* + * 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 java.util.List; +import java.util.Map; + +import javax.ws.rs.core.Response; + +import org.eclipse.jetty.server.Server; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import brooklyn.entity.Application; +import brooklyn.entity.basic.Entities; +import brooklyn.entity.basic.StartableApplication; +import brooklyn.location.basic.BasicLocationRegistry; +import brooklyn.management.ManagementContext; +import brooklyn.management.internal.LocalManagementContext; +import brooklyn.rest.BrooklynRestApiLauncher; +import brooklyn.rest.BrooklynRestApiLauncherTest; +import brooklyn.rest.domain.ApplicationSummary; +import brooklyn.rest.domain.CatalogLocationSummary; +import brooklyn.rest.security.provider.TestSecurityProvider; +import brooklyn.test.HttpTestUtils; +import brooklyn.test.entity.TestEntity; + +@Test +public class BrooklynApiRestClientTest { + + private static final Logger log = LoggerFactory.getLogger(BrooklynApiRestClientTest.class); + + private ManagementContext manager; + + private BrooklynApi api; + + protected synchronized ManagementContext getManagementContext() throws Exception { + if (manager == null) { + manager = new LocalManagementContext(); + BrooklynRestApiLauncherTest.forceUseOfDefaultCatalogWithJavaClassPath(manager); + BasicLocationRegistry.setupLocationRegistryForTesting(manager); + BrooklynRestApiLauncherTest.enableAnyoneLogin(manager); + } + return manager; + } + + @BeforeClass + public void setUp() throws Exception { + Server server = BrooklynRestApiLauncher.launcher() + .managementContext(manager) + .securityProvider(TestSecurityProvider.class) + .start(); + + api = new BrooklynApi("http://localhost:" + server.getConnectors()[0].getPort() + "/", + TestSecurityProvider.USER, TestSecurityProvider.PASSWORD); + } + + @AfterClass(alwaysRun = true) + public void tearDown() throws Exception { + for (Application app : getManagementContext().getApplications()) { + try { + ((StartableApplication) app).stop(); + } catch (Exception e) { + log.warn("Error stopping app " + app + " during test teardown: " + e); + } + } + Entities.destroyAll(getManagementContext()); + } + + public void testLocationApi() throws Exception { + log.info("Testing location API"); + Map<String, Map<String, Object>> locations = api.getLocationApi().getLocatedLocations(); + log.info("locations located are: "+locations); + } + + public void testCatalogApiLocations() throws Exception { + List<CatalogLocationSummary> locations = api.getCatalogApi().listLocations(".*", null, false); + log.info("locations from catalog are: "+locations); + } + + public void testApplicationApiList() throws Exception { + List<ApplicationSummary> apps = api.getApplicationApi().list(null); + log.info("apps are: "+apps); + } + + public void testApplicationApiCreate() throws Exception { + Response r1 = api.getApplicationApi().createFromYaml("name: test-1234\n" + + "services: [ { type: "+TestEntity.class.getName()+" } ]"); + HttpTestUtils.assertHealthyStatusCode(r1.getStatus()); + log.info("creation result: "+r1.getEntity()); + List<ApplicationSummary> apps = api.getApplicationApi().list(null); + log.info("apps with test: "+apps); + Assert.assertTrue(apps.toString().contains("test-1234"), "should have had test-1234 as an app; instead: "+apps); + } + + public void testApplicationApiHandledError() throws Exception { + Response r1 = api.getApplicationApi().createFromYaml("name: test"); + Assert.assertTrue(r1.getStatus()/100 != 2, "needed an unhealthy status, not "+r1.getStatus()); + Object entity = r1.getEntity(); + Assert.assertTrue(entity.toString().indexOf("Unrecognized application blueprint format: no services defined")>=0, + "Missing expected text in response: "+entity.toString()); + } + + public void testApplicationApiThrownError() throws Exception { + try { + ApplicationSummary summary = api.getApplicationApi().get("test-5678"); + Assert.fail("Should have thrown, not given: "+summary); + } catch (Exception e) { + e.printStackTrace(); + Assert.assertTrue(e.toString().toLowerCase().contains("not found"), + "Missing expected text in response: "+e.toString()); + } + } +}
