All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gemstone.gemfire.management.internal.web.shell.AbstractHttpOperationInvoker Maven / Gradle / Ivy

/*
 * Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
 *
 * 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. See accompanying
 * LICENSE file.
 */
package com.gemstone.gemfire.management.internal.web.shell;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import javax.management.ObjectName;
import javax.management.QueryExp;

import com.gemstone.gemfire.internal.GemFireVersion;
import com.gemstone.gemfire.internal.lang.StringUtils;
import com.gemstone.gemfire.internal.util.IOUtils;
import com.gemstone.gemfire.management.DistributedSystemMXBean;
import com.gemstone.gemfire.management.internal.MBeanJMXAdapter;
import com.gemstone.gemfire.management.internal.ManagementConstants;
import com.gemstone.gemfire.management.internal.cli.shell.Gfsh;
import com.gemstone.gemfire.management.internal.web.domain.Link;
import com.gemstone.gemfire.management.internal.web.domain.QueryParameterSource;
import com.gemstone.gemfire.management.internal.web.http.ClientHttpRequest;
import com.gemstone.gemfire.management.internal.web.http.HttpHeader;
import com.gemstone.gemfire.management.internal.web.http.HttpMethod;
import com.gemstone.gemfire.management.internal.web.http.converter.SerializableObjectHttpMessageConverter;
import com.gemstone.gemfire.management.internal.web.shell.support.HttpMBeanProxyFactory;
import com.gemstone.gemfire.management.internal.web.util.UriUtils;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

/**
 * The AbstractHttpOperationInvoker class is an abstract base class encapsulating common functionality for all
 * HTTP-based OperationInvoker implementations.
 * 

* @author John Blum * @see com.gemstone.gemfire.management.internal.cli.shell.Gfsh * @see com.gemstone.gemfire.management.internal.cli.shell.OperationInvoker * @see com.gemstone.gemfire.management.internal.web.shell.HttpOperationInvoker * @see com.gemstone.gemfire.management.internal.web.shell.RestHttpOperationInvoker * @see com.gemstone.gemfire.management.internal.web.shell.SimpleHttpOperationInvoker * @see org.springframework.http.client.SimpleClientHttpRequestFactory * @see org.springframework.web.client.RestTemplate * @since 7.5 */ @SuppressWarnings("unused") public abstract class AbstractHttpOperationInvoker implements HttpOperationInvoker { protected static final String MBEAN_ATTRIBUTE_LINK_RELATION = "mbean-attribute"; protected static final String MBEAN_OPERATION_LINK_RELATION = "mbean-operation"; protected static final String MBEAN_QUERY_LINK_RELATION = "mbean-query"; protected static final String DEFAULT_ENCODING = UriUtils.DEFAULT_ENCODING; protected static final String REST_API_BASE_URL = "http://localhost:8080"; protected static final String REST_API_VERSION = "/v1"; protected static final String REST_API_WEB_APP_CONTEXT = "/gemfire"; protected static final String REST_API_URL = REST_API_BASE_URL + REST_API_WEB_APP_CONTEXT + REST_API_VERSION; protected static final String USER_AGENT_HTTP_REQUEST_HEADER_VALUE = "GemFire-Shell/v" + GemFireVersion.getGemFireVersion(); // the ID of the GemFire distributed system (cluster) private Integer clusterId = CLUSTER_ID_WHEN_NOT_CONNECTED; // a reference to the GemFire shell (Gfsh) instance using this HTTP-based OperationInvoker for command execution // and processing private final Gfsh gfsh; // a list of acceptable content/media types supported by Gfsh private final List acceptableMediaTypes = Arrays.asList(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN); // a Java Logger used to log severe, warning, informational and debug messages during the operation of this invoker private final Logger logger = Logger.getLogger(getClass().getName()); // the Spring RestTemplate used to send HTTP requests and make REST API calls private RestTemplate restTemplate; // the base URL of the GemFire Manager's embedded HTTP service and REST API interface private final String baseUrl; /** * Default no-arg constructor to create an instance of the AbstractHttpOperationInvoker class for testing purposes. */ AbstractHttpOperationInvoker(final String baseUrl) { this.baseUrl = baseUrl; this.gfsh = null; this.restTemplate = null; } /** * Constructs an instance of the AbstractHttpOperationInvoker class with a reference to the GemFire shell (Gfsh) * instance using this HTTP-based OperationInvoker to send commands to the GemFire Manager via HTTP for processing. *

* @param gfsh a reference to the instance of the GemFire shell (Gfsh) using this HTTP-based OperationInvoker for * command processing. * @throws AssertionError if the reference to the Gfsh instance is null. * @see #AbstractHttpOperationInvoker(com.gemstone.gemfire.management.internal.cli.shell.Gfsh, String) * @see com.gemstone.gemfire.management.internal.cli.shell.Gfsh */ public AbstractHttpOperationInvoker(final Gfsh gfsh) { this(gfsh, REST_API_URL); } /** * Constructs an instance of the AbstractHttpOperationInvoker class with a reference to the GemFire shell (Gfsh) * instance using this HTTP-based OperationInvoker to send commands to the GemFire Manager via HTTP for procsessing * along with the base URL to the GemFire Manager's embedded HTTP service hosting the HTTP (REST) interface. *

* @param gfsh a reference to the instance of the GemFire shell (Gfsh) using this HTTP-based OperationInvoker for * command processing. * @param baseUrl a String specifying the base URL to the GemFire Manager's embedded HTTP service hosting the REST * interface. * @throws AssertionError if the reference to the Gfsh instance is null. * @see com.gemstone.gemfire.management.internal.cli.shell.Gfsh */ public AbstractHttpOperationInvoker(final Gfsh gfsh, final String baseUrl) { assert gfsh != null : "The reference to the GemFire shell (Gfsh) cannot be null!"; this.gfsh = gfsh; this.baseUrl = StringUtils.defaultIfBlank(baseUrl, REST_API_URL); this.restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory()); this.restTemplate.getMessageConverters().add(new SerializableObjectHttpMessageConverter()); this.restTemplate.setErrorHandler(new ResponseErrorHandler() { @Override public boolean hasError(final ClientHttpResponse response) throws IOException { final HttpStatus status = response.getStatusCode(); switch (status) { case BAD_REQUEST: // 400 * case UNAUTHORIZED: // 401 case FORBIDDEN: // 403 case NOT_FOUND: // 404 * case METHOD_NOT_ALLOWED: // 405 * case NOT_ACCEPTABLE: // 406 * case REQUEST_TIMEOUT: // 408 case REQUEST_ENTITY_TOO_LARGE: // 413 case REQUEST_URI_TOO_LONG: // 414 case UNSUPPORTED_MEDIA_TYPE: // 415 * case TOO_MANY_REQUESTS: // 429 case INTERNAL_SERVER_ERROR: // 500 * case NOT_IMPLEMENTED: // 501 case BAD_GATEWAY: // 502 ? case SERVICE_UNAVAILABLE: // 503 return true; default: return false; } } @Override public void handleError(final ClientHttpResponse response) throws IOException { final String message = String.format("The HTTP request failed with: %1$d - %2$s", response.getRawStatusCode(), response.getStatusText()); gfsh.logSevere(message, null); if (gfsh.getDebug()) { gfsh.logSevere(readBody(response), null); } } private String readBody(final ClientHttpResponse response) throws IOException { BufferedReader responseBodyReader = null; try { responseBodyReader = new BufferedReader(new InputStreamReader(response.getBody())); final StringBuilder buffer = new StringBuilder(); String line; while ((line = responseBodyReader.readLine()) != null) { buffer.append(line).append(StringUtils.LINE_SEPARATOR); } return buffer.toString().trim(); } finally { IOUtils.close(responseBodyReader); } } }); initClusterId(); } /** * Gets a list of acceptable content/media types supported by Gfsh. *

* @return a List of acceptable content/media types supported by Gfsh. * @see org.springframework.http.MediaType */ protected List getAcceptableMediaTypes() { return acceptableMediaTypes; } /** * Returns the base URL to GemFire's REST interface hosted in the GemFire Manager's embedded HTTP service * (Tomcat server). *

* @return a String value specifying the base URL to the GemFire REST interface. */ protected String getBaseUrl() { return this.baseUrl; } /** * Determines whether Gfsh is in debug mode (or whether the user enabled debugging in Gfsh). *

* @return a boolean value indicating if debugging has been turned on in Gfsh. * @see com.gemstone.gemfire.management.internal.cli.shell.Gfsh#getDebug() */ protected boolean isDebugEnabled() { return getGfsh().getDebug(); } /** * Returns the reference to the GemFire shell (Gfsh) instance using this HTTP-based OperationInvoker to send commands * to the GemFire Manager for remote execution and processing. *

* @return a reference to the instance of the GemFire shell (Gfsh) using this HTTP-based OperationInvoker to process * commands. * @see com.gemstone.gemfire.management.internal.cli.shell.Gfsh */ protected final Gfsh getGfsh() { return this.gfsh; } /** * Gets the Java Logger used to log messages. *

* @return a Java Logger used to log messages. * @see java.util.logging.Logger */ protected Logger getLogger() { return this.logger; } /** * Returns a reference to the Spring RestTemplate used by this HTTP-based OperationInvoker to send HTTP requests to * GemFire's REST interface, making REST API calls. *

* @return an instance of the Spring RestTemplate used to make REST API web service calls. * @see org.springframework.web.client.RestTemplate */ protected final RestTemplate getRestTemplate() { return this.restTemplate; } /** * Creates an instance of a client HTTP request with the specified Link targeting the resource as well as the intended * operation on the resource. *

* @param link a Link with the URI targeting and identifying the resource as well as the method of operation on the * resource. * @return a client HTTP request with the details of the request. * @see com.gemstone.gemfire.management.internal.web.http.ClientHttpRequest * @see com.gemstone.gemfire.management.internal.web.domain.Link */ protected ClientHttpRequest createHttpRequest(final Link link) { final ClientHttpRequest request = new ClientHttpRequest(link); request.addHeaderValues(HttpHeader.USER_AGENT.getName(), USER_AGENT_HTTP_REQUEST_HEADER_VALUE); request.getHeaders().setAccept(getAcceptableMediaTypes()); return request; } /** * Creates a Link with the specified relation and URI of the remote resource. *

* @param relation a String indicating the link relation, or relative state transition, operation. * @param href the URI identifying the resource and it's location. * @return a Link with the providing relation and URI. * @see com.gemstone.gemfire.management.internal.web.domain.Link * @see java.net.URI */ protected Link createLink(final String relation, final URI href) { return new Link(relation, href); } /** * Creates a Link with the specified relation and URI of the remote resource along with the method of the operation. *

* @param relation a String indicating the link relation, or relative state transition, operation. * @param href the URI identifying the resource and it's location. * @param method the HTTP method for the operation of the request. * @return a Link with the providing relation and URI. * @see com.gemstone.gemfire.management.internal.web.http.HttpMethod * @see com.gemstone.gemfire.management.internal.web.domain.Link * @see java.net.URI */ protected Link createLink(final String relation, final URI href, final HttpMethod method) { return new Link(relation, href, method); } /** * Decodes the encoded String value using the default encoding UTF-8. It is assumed the String value was encoded * with the URLEncoder using the UTF-8 encoding. This method handles UnsupportedEncodingException by just returning * the encodedValue. *

* @param encodedValue the encoded String value to decode. * @return the decoded value of the String or encodedValue if the UTF-8 encoding is unsupported. * @see com.gemstone.gemfire.management.internal.web.util.UriUtils#decode(String) */ protected String decode(final String encodedValue) { return UriUtils.decode(encodedValue); } /** * Decodes the encoded String value using the specified encoding (such as UTF-8). It is assumed the String value * was encoded with the URLEncoder using the specified encoding. This method handles UnsupportedEncodingException * by just returning the encodedValue. *

* @param encodedValue a String value encoded in the encoding. * @param encoding a String value specifying the encoding. * @return the decoded value of the String or encodedValue if the specified encoding is unsupported. * @see com.gemstone.gemfire.management.internal.web.util.UriUtils#decode(String, String) */ protected String decode(final String encodedValue, String encoding) { return UriUtils.decode(encodedValue, encoding); } /** * Encode the String value using the default encoding UTF-8. *

* @param value the String value to encode. * @return an encoded value of the String using the default encoding UTF-8 or value if the UTF-8 encoding * is unsupported. * @see com.gemstone.gemfire.management.internal.web.util.UriUtils#encode(String) */ protected String encode(final String value) { return UriUtils.encode(value); } /** * Encode the String value using the specified encoding (such as UTF-8). *

* @param value the String value to encode. * @param encoding a String value indicating the encoding. * @return an encoded value of the String using the specified encoding or value if the specified encoding * is unsupported. * @see com.gemstone.gemfire.management.internal.web.util.UriUtils#encode(String, String) */ protected String encode(final String value, final String encoding) { return UriUtils.encode(value, encoding); } /** * Finds a Link containing the HTTP request URI for the relational operation (state transition) on the resource. *

* @param relation a String describing the relational operation, or state transition on the resource. * @return an instance of Link containing the HTTP request URI used to perform the intended operation on the resource. * @see com.gemstone.gemfire.management.internal.web.domain.Link */ protected Link findLink(final String relation) { return null; } /** * Handles resource access errors such as ConnectExceptions when the server-side process/service is not listening * for client connections, or the connection to the server/service fails. *

* @param e the ResourceAccessException resulting in some sort of I/O error. * @return a user-friendly String message describing the problem and appropriate action/response by the user. * @see #stop() * @see org.springframework.web.client.ResourceAccessException */ protected String handleResourceAccessException(final ResourceAccessException e) { stop(); return String.format("The connection to the GemFire Manager's HTTP service @ %1$s failed with: %2$s. " + "Please try reconnecting or see the GemFire Manager's log file for further details.", getBaseUrl(), e.getMessage()); } /** * Displays the message inside GemFire shell at debug level. *

* @param message the String containing the message to display inside Gfsh. * @see #isDebugEnabled() * @see #printInfo(String, Object...) */ protected void printDebug(final String message, final Object... args) { if (isDebugEnabled()) { printInfo(message, args); } } /** * Displays the message inside GemFire shell at info level. *

* @param message the String containing the message to display inside Gfsh. * @see com.gemstone.gemfire.management.internal.cli.shell.Gfsh#printAsInfo(String) */ protected void printInfo(final String message, final Object... args) { getGfsh().printAsInfo(String.format(message, args)); } /** * Displays the message inside GemFire shell at warning level. *

* @param message the String containing the message to display inside Gfsh. * @see com.gemstone.gemfire.management.internal.cli.shell.Gfsh#printAsWarning(String) */ protected void printWarning(final String message, final Object... args) { getGfsh().printAsWarning(String.format(message, args)); } /** * Displays the message inside GemFire shell at severe level. *

* @param message the String containing the message to display inside Gfsh. * @see com.gemstone.gemfire.management.internal.cli.shell.Gfsh#printAsSevere(String) */ protected void printSevere(final String message, final Object... args) { getGfsh().printAsSevere(String.format(message, args)); } /** * Sends the HTTP request, using Spring's RestTemplate, to the GemFire REST API web service endpoint, expecting the * specified response type from the server in return. *

* @param the response type. * @param request the client HTTP request to send. * @param responseType the expected Class type of the return value in the server's response. * @return a ResponseEntity encapsulating the details of the server's response to the client's HTTP request. * @see #send(com.gemstone.gemfire.management.internal.web.http.ClientHttpRequest, Class, java.util.Map) * @see com.gemstone.gemfire.management.internal.web.http.ClientHttpRequest * @see org.springframework.http.ResponseEntity */ protected ResponseEntity send(final ClientHttpRequest request, final Class responseType) { return send(request, responseType, Collections.emptyMap()); } /** * Sends the HTTP request, using Spring's RestTemplate, to the GemFire REST API web service endpoint, expecting the * specified response type from the server in return. *

* @param request the client HTTP request to send. * @param responseType the expected Class type of the return value in the server's response. * @param uriVariables a Mapping of URI template path variables to values. * @return a ResponseEntity encapsulating the details of the server's response to the client's HTTP request. * @see java.net.URI * @see com.gemstone.gemfire.management.internal.web.http.ClientHttpRequest * @see org.springframework.http.ResponseEntity * @see org.springframework.web.client.RestTemplate#exchange(java.net.URI, org.springframework.http.HttpMethod, org.springframework.http.HttpEntity, Class) */ protected ResponseEntity send(final ClientHttpRequest request, final Class responseType, final Map uriVariables) { final URI url = request.getURL(uriVariables); if (isDebugEnabled()) { printInfo("Link: %1$s", request.getLink().toHttpRequestLine()); printInfo("HTTP URL: %1$s", url); printInfo("HTTP request headers: %1$s", request.getHeaders()); printInfo("HTTP request parameters: %1$s", request.getParameters()); } final ResponseEntity response = getRestTemplate().exchange(url, request.getMethod(), request.createRequestEntity(), responseType); if (isDebugEnabled()) { printInfo("------------------------------------------------------------------------"); printInfo("HTTP response headers: %1$s", response.getHeaders()); printInfo("HTTP response status: %1$d - %2$s", response.getStatusCode().value(), response.getStatusCode().getReasonPhrase()); } return response; } /** * Determines whether this HTTP-based OperationInvoker is successfully connected to the remote GemFire Manager's * HTTP service in order to send commands for execution/processing. *

* @return a boolean value indicating the connection state of the HTTP-based OperationInvoker. */ @Override public boolean isConnected() { return (getRestTemplate() != null); } /** * Determines whether this HTTP-based OperationInvoker is ready to send commands to the GemFire Manager for remote * execution/processing. *

* @return a boolean value indicating whether this HTTP-based OperationInvoker is ready for command invocations. * @see #isConnected() */ @Override public boolean isReady() { return isConnected(); } // TODO research the use of Jolokia instead /** * Read the attribute identified by name from a remote resource identified by name. The intent of this method * is to return the value of an attribute on an MBean located in the remote MBeanServer. *

* @param resourceName name/url of the remote resource from which to fetch the attribute value. * @param attributeName name of the attribute who's value will be fetched. * @return the value of the named attribute for the named resource (typically an MBean). * @throws MBeanAccessException if an MBean access error occurs. * @throws RestApiCallForCommandNotFoundException if the REST API web service endpoint for accessing an attribute on * an MBean does not exists! * @see #createHttpRequest(com.gemstone.gemfire.management.internal.web.domain.Link) * @see #findLink(String) * @see #send(com.gemstone.gemfire.management.internal.web.http.ClientHttpRequest, Class) */ @Override public Object getAttribute(final String resourceName, final String attributeName) { final Link link = findLink(MBEAN_ATTRIBUTE_LINK_RELATION); if (link != null) { final ClientHttpRequest request = createHttpRequest(link); request.addRequestParameterValues("resourceName", resourceName); request.addRequestParameterValues("attributeName", attributeName); final ResponseEntity response = send(request, byte[].class); try { return IOUtils.deserializeObject(response.getBody()); } catch (IOException e) { throw new MBeanAccessException(String.format( "De-serializing the result of accessing attribute (%1$s) on MBean (%2$s) failed!", resourceName, attributeName), e); } catch (ClassNotFoundException e) { throw new MBeanAccessException(String.format( "The Class type of the result when accessing attribute (%1$s) on MBean (%2$s) was not found!", resourceName, attributeName), e); } } else { printSevere("Getting the value of attribute (%1$s) on MBean (%2$s) is currently an unsupported operation!", attributeName, resourceName); throw new RestApiCallForCommandNotFoundException(MBEAN_ATTRIBUTE_LINK_RELATION); } } /** * Gets the identifier of the GemFire cluster. *

* @return an integer value indicating the identifier of the GemFire cluster. * @see #initClusterId() */ @Override public int getClusterId() { return clusterId; } private void initClusterId() { if (isReady()) { try { clusterId = (Integer) getAttribute(ManagementConstants.OBJECTNAME__DISTRIBUTEDSYSTEM_MXBEAN, "DistributedSystemId"); printDebug("Cluster ID (%1$s)", clusterId); } catch (Exception ignore) { printDebug("Failed to determine cluster ID: %1$s", ignore.getMessage()); } } } /** * Gets a proxy to the remote DistributedSystem MXBean to access attributes and invoke operations on the distributed * system, or the GemFire cluster. *

* @return a proxy instance of the GemFire Manager's DistributedSystem MXBean. * @see #getMBeanProxy(javax.management.ObjectName, Class) * @see com.gemstone.gemfire.management.DistributedSystemMXBean * @see com.gemstone.gemfire.management.internal.MBeanJMXAdapter#getDistributedSystemName() */ public DistributedSystemMXBean getDistributedSystemMXBean() { return getMBeanProxy(MBeanJMXAdapter.getDistributedSystemName(), DistributedSystemMXBean.class); } /** * Gets a proxy to an MXBean on a remote MBeanServer using HTTP for remoting. *

* @param the class type of the remote MXBean. * @param objectName the JMX ObjectName uniquely identifying the remote MXBean. * @param mbeanInterface the interface of the remote MXBean to proxy for attribute/operation access. * @return a proxy using HTTP remoting to access the specified, remote MXBean. * @see javax.management.ObjectName * @see com.gemstone.gemfire.management.internal.web.shell.support.HttpMBeanProxyFactory */ public T getMBeanProxy(final ObjectName objectName, final Class mbeanInterface) { return HttpMBeanProxyFactory.createMBeanProxy(this, objectName, mbeanInterface); } /** * Invoke an operation identified by name on a remote resource identified by name with the given arguments. * The intent of this method is to invoke an arbitrary operation on an MBean located in the remote MBeanServer. *

* @param resourceName name/url (object name) of the remote resource (MBea) on which operation is to be invoked. * @param operationName name of the operation to be invoked. * @param params an array of arguments for the parameters to be set when the operation is invoked. * @param signature an array containing the signature of the operation. * @return result of the operation invocation. * @throws MBeanAccessException if an MBean access error occurs. * @throws RestApiCallForCommandNotFoundException if the REST API web service endpoint for invoking an operation on * an MBean does not exists! * @see #createHttpRequest(com.gemstone.gemfire.management.internal.web.domain.Link) * @see #findLink(String) * @see #send(com.gemstone.gemfire.management.internal.web.http.ClientHttpRequest, Class) */ // TODO research the use of Jolokia instead @Override public Object invoke(final String resourceName, final String operationName, final Object[] params, final String[] signature) { final Link link = findLink(MBEAN_OPERATION_LINK_RELATION); if (link != null) { final ClientHttpRequest request = createHttpRequest(link); request.addRequestParameterValues("resourceName", resourceName); request.addRequestParameterValues("operationName", operationName); request.addRequestParameterValues("signature", (Object[]) signature); request.addRequestParameterValues("parameters", params); // TODO may need to convert method parameter arguments final ResponseEntity response = send(request, byte[].class); try { return IOUtils.deserializeObject(response.getBody()); } catch (IOException e) { throw new MBeanAccessException(String.format( "De-serializing the result from invoking operation (%1$s) on MBean (%2$s) failed!", resourceName, operationName), e); } catch (ClassNotFoundException e) { throw new MBeanAccessException(String.format( "The Class type of the result from invoking operation (%1$s) on MBean (%2$s) was not found!", resourceName, operationName), e); } } else { printSevere("Invoking operation (%1$s) on MBean (%2$s) is currently an unsupported operation!", operationName, resourceName); throw new RestApiCallForCommandNotFoundException(MBEAN_OPERATION_LINK_RELATION); } } /** * This method searches the MBean server, based on the OperationsInvoker's JMX-based or remoting capable MBean server * connection, for MBeans matching a specific ObjectName or matching an ObjectName pattern along with satisfying * criteria from the Query expression. *

* @param objectName the ObjectName or pattern for which matching MBeans in the target MBean server will be returned. * @param queryExpression the JMX-based query expression used to filter matching MBeans. * @return a set of ObjectName's matching MBeans in the MBean server matching the ObjectName and Query expression * criteria. * @see #createHttpRequest(com.gemstone.gemfire.management.internal.web.domain.Link) * @see #findLink(String) * @see #send(com.gemstone.gemfire.management.internal.web.http.ClientHttpRequest, Class) * @see javax.management.ObjectName * @see javax.management.QueryExp */ @Override @SuppressWarnings("unchecked") public Set queryNames(final ObjectName objectName, final QueryExp queryExpression) { final Link link = findLink(MBEAN_QUERY_LINK_RELATION); if (link != null) { final ClientHttpRequest request = createHttpRequest(link); request.setContent(new QueryParameterSource(objectName, queryExpression)); final ResponseEntity response = send(request, byte[].class); try { return (Set) IOUtils.deserializeObject(response.getBody()); } catch (Exception e) { throw new MBeanAccessException(String.format( "An error occurred while querying for MBean names using ObjectName pattern (%1$s) and Query expression (%2$s)!", objectName, queryExpression), e); } } else { printSevere("Running a query to get the ObjectNames of all MBeans matching the ObjectName pattern (%1$s) and Query expression (%2$s) is currently unsupported!", objectName, queryExpression); throw new RestApiCallForCommandNotFoundException(MBEAN_QUERY_LINK_RELATION); } } /** * Stops communication with and closes all connections to the remote HTTP server (service). */ @Override public void stop() { restTemplate = null; } @Override public String toString() { final StringBuilder buffer = new StringBuilder(); //buffer.append(isConnected() ? "Connected to " : "Disconnected from "); buffer.append(String.format("GemFire Manager's HTTP service @ %1$s", getBaseUrl())); return buffer.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy