geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jensde...@apache.org
Subject [27/50] [abbrv] incubator-geode git commit: Merge branch 'develop' into feature/GEODE-17
Date Thu, 25 Feb 2016 20:27:15 GMT
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5c01d5f4/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/support/EnvironmentVariablesHandlerInterceptor.java
----------------------------------------------------------------------
diff --cc geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/support/EnvironmentVariablesHandlerInterceptor.java
index 0000000,2ba50ad..c722bda
mode 000000,100644..100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/support/EnvironmentVariablesHandlerInterceptor.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/support/EnvironmentVariablesHandlerInterceptor.java
@@@ -1,0 -1,93 +1,179 @@@
+ /*
+  * 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 com.gemstone.gemfire.management.internal.web.controllers.support;
+ 
++import java.lang.reflect.Method;
++import java.security.Principal;
+ import java.util.Collections;
+ import java.util.Enumeration;
+ import java.util.HashMap;
++import java.util.Iterator;
+ import java.util.Map;
++import java.util.Properties;
++import java.util.Set;
++import java.util.Map.Entry;
++
++import javax.management.remote.JMXPrincipal;
++import javax.security.auth.Subject;
+ import javax.servlet.http.HttpServletRequest;
+ import javax.servlet.http.HttpServletResponse;
+ 
+ import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+ 
++import com.gemstone.gemfire.GemFireConfigException;
++import com.gemstone.gemfire.cache.Cache;
++import com.gemstone.gemfire.cache.CacheFactory;
++import com.gemstone.gemfire.distributed.DistributedMember;
++import com.gemstone.gemfire.distributed.DistributedSystem;
++import com.gemstone.gemfire.distributed.internal.DistributionConfig;
++import com.gemstone.gemfire.internal.ClassLoadUtil;
++import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
++import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
++import com.gemstone.gemfire.internal.logging.InternalLogWriter;
++import com.gemstone.gemfire.internal.logging.LogService;
++import com.gemstone.gemfire.management.ManagementService;
++import com.gemstone.gemfire.management.internal.SystemManagementService;
++import com.gemstone.gemfire.management.internal.security.CLIOperationContext;
++import com.gemstone.gemfire.management.internal.security.MBeanServerWrapper;
++import com.gemstone.gemfire.management.internal.security.ResourceConstants;
++import com.gemstone.gemfire.security.AccessControl;
++import com.gemstone.gemfire.security.AuthenticationFailedException;
++import com.gemstone.gemfire.security.AuthenticationRequiredException;
++import com.gemstone.gemfire.security.Authenticator;
++
++import org.apache.logging.log4j.Logger;
++
+ /**
+  * The GetEnvironmentHandlerInterceptor class handles extracting Gfsh environment variables encoded in the HTTP request
+  * message as request parameters.
+  * <p/>
+  * @author John Blum
+  * @see javax.servlet.http.HttpServletRequest
+  * @see javax.servlet.http.HttpServletResponse
+  * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter
+  * @since 8.0
+  */
+ @SuppressWarnings("unused")
+ public class EnvironmentVariablesHandlerInterceptor extends HandlerInterceptorAdapter {
+ 
++  private static final Logger logger = LogService.getLogger();
++  
++  private Cache cache;
++  
++  private Authenticator auth = null;
++  
++  
++  public static final ThreadLocal<Properties> CREDENTIALS = new ThreadLocal<Properties>();
++  
++   
+   private static final ThreadLocal<Map<String, String>> ENV = new ThreadLocal<Map<String, String>>() {
+     @Override
+     protected Map<String, String> initialValue() {
+       return Collections.emptyMap();
+     }
+   };
+ 
+   protected static final String ENVIRONMENT_VARIABLE_REQUEST_PARAMETER_PREFIX = "vf.gf.env.";
++  
++  protected static final String SECURITY_VARIABLE_REQUEST_HEADER_PREFIX = "security-";
+ 
+   public static Map<String, String> getEnvironment() {
+     return ENV.get();
+   }
+ 
+   @Override
+   public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler)
+     throws Exception
+   {
++    
+     final Map<String, String> requestParameterValues = new HashMap<String, String>();
+ 
+     for (Enumeration<String> requestParameters = request.getParameterNames(); requestParameters.hasMoreElements(); ) {
+       final String requestParameter = requestParameters.nextElement();
+ 
+       if (requestParameter.startsWith(ENVIRONMENT_VARIABLE_REQUEST_PARAMETER_PREFIX)) {
+         requestParameterValues.put(requestParameter.substring(ENVIRONMENT_VARIABLE_REQUEST_PARAMETER_PREFIX.length()),
+           request.getParameter(requestParameter));
+       }
+     }
++    
++ 
++    
++    for (Enumeration<String> requestHeaders = request.getHeaderNames(); requestHeaders.hasMoreElements();) {
+ 
++      final String requestHeader = requestHeaders.nextElement();
++
++      if (requestHeader.startsWith(SECURITY_VARIABLE_REQUEST_HEADER_PREFIX)) {
++        requestParameterValues.put(requestHeader, request.getHeader(requestHeader));
++      }
++
++    }
++    
++    securityCheck(requestParameterValues);
++    
+     ENV.set(requestParameterValues);
+ 
+     return true;
+   }
++  
++
++  
++  protected void securityCheck(final Map<String, String> environment) {
++
++    Properties credentials = new Properties();
++
++    Iterator<Entry<String, String>> it = environment.entrySet().iterator();
++    while (it.hasNext()) {
++      Entry<String, String> entry = it.next();
++      if (entry.getKey().startsWith(SECURITY_VARIABLE_REQUEST_HEADER_PREFIX)) {
++        credentials.put(entry.getKey(), entry.getValue());
++      }
++
++    }
++    GemFireCacheImpl instance = GemFireCacheImpl.getInstance();
++    if(instance != null){
++      SystemManagementService service = (SystemManagementService) ManagementService
++          .getExistingManagementService(instance);
++      service.getAuthManager().verifyCredentials(credentials);
++      CREDENTIALS.set(credentials);
++    }
++
++
++  }
++
++  
+ 
+   @Override
+   public void afterCompletion(final HttpServletRequest request,
+                               final HttpServletResponse response,
+                               final Object handler,
+                               final Exception ex)
+     throws Exception
+   {
+     afterConcurrentHandlingStarted(request, response, handler);
+   }
+ 
+   @Override
+   public void afterConcurrentHandlingStarted(final HttpServletRequest request,
+                                              final HttpServletResponse response,
+                                              final Object handler)
+     throws Exception
+   {
+     ENV.remove();
+   }
+ 
+ }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5c01d5f4/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/http/support/SimpleHttpRequester.java
----------------------------------------------------------------------
diff --cc geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/http/support/SimpleHttpRequester.java
index 0000000,7d155e6..9aaa230
mode 000000,100644..100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/http/support/SimpleHttpRequester.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/http/support/SimpleHttpRequester.java
@@@ -1,0 -1,140 +1,237 @@@
+ /*
+  * 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 com.gemstone.gemfire.management.internal.web.http.support;
+ 
++import java.io.BufferedReader;
++import java.io.IOException;
++import java.io.InputStreamReader;
++import java.net.URI;
++import java.util.Map;
++import java.util.Properties;
+ import java.util.Set;
+ 
++import org.springframework.http.HttpEntity;
+ import org.springframework.http.HttpHeaders;
+ import org.springframework.http.HttpMethod;
++import org.springframework.http.HttpStatus;
++import org.springframework.http.ResponseEntity;
++import org.springframework.http.client.ClientHttpRequest;
++import org.springframework.http.client.ClientHttpResponse;
+ import org.springframework.http.client.SimpleClientHttpRequestFactory;
++import org.springframework.web.client.RequestCallback;
++import org.springframework.web.client.ResponseErrorHandler;
++import org.springframework.web.client.RestClientException;
+ import org.springframework.web.client.RestTemplate;
+ 
++import com.gemstone.gemfire.internal.lang.StringUtils;
++import com.gemstone.gemfire.internal.util.IOUtils;
++import com.gemstone.gemfire.management.internal.cli.shell.Gfsh;
++import com.gemstone.gemfire.management.internal.security.ResourceConstants;
++
++
+ /**
+  * The SimpleHttpRequester class is a Adapter/facade for the Spring RestTemplate class for abstracting HTTP requests
+  * and operations.
+  * <p/>
+  * @author John Blum
+  * @see org.springframework.http.client.SimpleClientHttpRequestFactory
+  * @see org.springframework.web.client.RestTemplate
+  * @since 8.0
+  */
+ @SuppressWarnings("unused")
+ public class SimpleHttpRequester {
+ 
+   protected static final int DEFAULT_CONNECT_TIMEOUT = (30 * 1000); // 30 seconds
+ 
+   private final RestTemplate restTemplate;
++  
++  private String user;
++  
++  private String pwd;
+ 
++  private Map<String,String> securityProperties;
+   /**
+    * Default constructor to create an instance of the SimpleHttpRequester class using the default connection timeout
+    * of 30 seconds.
+    */
 -  public SimpleHttpRequester() {
 -    this(DEFAULT_CONNECT_TIMEOUT);
++  public SimpleHttpRequester(Gfsh gfsh,Map<String,String> securityProperties) {
++    this(gfsh, DEFAULT_CONNECT_TIMEOUT, securityProperties);
+   }
+ 
+   /**
+    * Constructs an instance of the SimpleHttpRequester class with the specified connection timeout.
+    * <p/>
+    * @param connectTimeout an integer value specifying the timeout value in milliseconds for establishing the HTTP
+    * connection to the HTTP server.
+    */
 -  public SimpleHttpRequester(final int connectTimeout) {
++  public SimpleHttpRequester(final Gfsh gfsh, final int connectTimeout, Map<String,String> securityProperties) {
+     final SimpleClientHttpRequestFactory clientHttpRequestFactory = new SimpleClientHttpRequestFactory();
+ 
+     clientHttpRequestFactory.setConnectTimeout(connectTimeout);
+ 
++    this.securityProperties = securityProperties;
+     this.restTemplate = new RestTemplate(clientHttpRequestFactory);
++
++    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 CONFLICT: // 409
++        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());
++        
++        throw new RuntimeException(message);
++
++      }
++
++     
++    });
++
+   }
+ 
+   /**
+    * Gets an instance of the Spring RestTemplate to perform the HTTP operations.
+    * <p/>
+    * @return an instance of the Spring RestTemplate for performing HTTP operations.
+    * @see org.springframework.web.client.RestTemplate
+    */
+   public RestTemplate getRestTemplate() {
+     return restTemplate;
+   }
+ 
+   /**
+    * Performs an HTTP DELETE operation on the requested resource identified/located by the specified URL.
+    * <p/>
+    * @param url a String value identifying or locating the resource intended for the HTTP operation.
+    * @param urlVariables an array of variables to substitute in the URI/URL template.
+    * @see org.springframework.web.client.RestTemplate#delete(String, Object...)
+    */
+   public void delete(final String url, final Object... urlVariables) {
+     getRestTemplate().delete(url, urlVariables);
+   }
+ 
+   /**
+    * Performs an HTTP GET operation on the requested resource identified/located by the specified URL.
+    * <p/>
+    * @param url a String value identifying or locating the resource intended for the HTTP operation.
+    * @param urlVariables an array of variables to substitute in the URI/URL template.
+    * @see org.springframework.web.client.RestTemplate#getForObject(String, Class, Object...)
+    */
+   public <T> T get(final String url, final Class<T> responseType, final Object... urlVariables) {
+     return getRestTemplate().getForObject(url, responseType, urlVariables);
+   }
+ 
+   /**
+    * Retrieves the HTTP HEADERS for the requested resource identified/located by the specified URL.
+    * <p/>
+    * @param url a String value identifying or locating the resource intended for the HTTP operation.
+    * @param urlVariables an array of variables to substitute in the URI/URL template.
+    * @see org.springframework.web.client.RestTemplate#headForHeaders(String, Object...)
+    */
+   public HttpHeaders headers(final String url, final Object... urlVariables) {
+     return getRestTemplate().headForHeaders(url, urlVariables);
+   }
+ 
+   /**
+    * Request the available/allowed HTTP operations on the resource identified/located by the specified URL.
+    * <p/>
+    * @param url a String value identifying or locating the resource intended for the HTTP operation.
+    * @param urlVariables an array of variables to substitute in the URI/URL template.
+    * @see org.springframework.web.client.RestTemplate#optionsForAllow(String, Object...)
+    */
+   public Set<HttpMethod> options(final String url, final Object... urlVariables) {
+     return getRestTemplate().optionsForAllow(url, urlVariables);
+   }
+ 
+   /**
+    * Performs an HTTP POST operation on the requested resource identified/located by the specified URL.
+    * <p/>
+    * @param url a String value identifying or locating the resource intended for the HTTP operation.
+    * @param urlVariables an array of variables to substitute in the URI/URL template.
+    * @see org.springframework.web.client.RestTemplate#postForObject(String, Object, Class, Object...) z
+    */
+   public <T> T post(final String url, final Object requestBody, final Class<T> responseType, final Object... urlVariables) {
+     return getRestTemplate().postForObject(url, requestBody, responseType, urlVariables);
+   }
+ 
+   /**
 -   * Performs an HTTP PUT operation on the requested resource identified/located by the specified URL.
++   * Performs an HTTP PUT operation on the requested resource identifiedR/located by the specified URL.
+    * <p/>
+    * @param url a String value identifying or locating the resource intended for the HTTP operation.
+    * @param urlVariables an array of variables to substitute in the URI/URL template.
+    * @see org.springframework.web.client.RestTemplate#put(String, Object, Object...)
+    */
+   public void put(final String url, final Object requestBody, final Object... urlVariables) {
+     getRestTemplate().put(url, requestBody, urlVariables);
+   }
++  
++  /**
++   * Performs an HTTP GET operation on the requested resource identified/located
++   * by the specified URL.
++   * <p/>
++   * 
++   * @param url
++   *          a String value identifying or locating the resource intended for
++   *          the HTTP operation.
++   * @param urlVariables
++   *          an array of variables to substitute in the URI/URL template.
++   * @see org.springframework.web.client.RestTemplate#getForObject(String,
++   *      Class, Object...)
++   */
++  public <T> T exchange(final String url, final Class<T> responseType, final Object... urlVariables) {
++    ResponseEntity<T> response = getRestTemplate().exchange(url, HttpMethod.GET, getRequestEntity(), responseType);
++    return response.getBody();
++  }
++
++  protected HttpEntity<?> getRequestEntity() {
++    HttpHeaders requestHeaders = new HttpHeaders();  
++    if(this.securityProperties != null){
++      requestHeaders.setAll(securityProperties);
++    }
++
++    HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);
++
++    return requestEntity;
++
++  }
+ 
+ }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5c01d5f4/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/shell/AbstractHttpOperationInvoker.java
----------------------------------------------------------------------
diff --cc geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/shell/AbstractHttpOperationInvoker.java
index 0000000,425c779..052897d
mode 000000,100644..100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/shell/AbstractHttpOperationInvoker.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/shell/AbstractHttpOperationInvoker.java
@@@ -1,0 -1,801 +1,820 @@@
+ /*
+  * 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 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.Iterator;
+ import java.util.List;
+ import java.util.Map;
++import java.util.Map.Entry;
+ import java.util.Set;
+ import java.util.concurrent.Executors;
+ import java.util.concurrent.ScheduledExecutorService;
+ import java.util.concurrent.TimeUnit;
++
+ 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.logging.LogService;
+ 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.security.ResourceConstants;
+ 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.apache.logging.log4j.Logger;
+ 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 8.0
+  */
+ @SuppressWarnings("unused")
+ public abstract class AbstractHttpOperationInvoker implements HttpOperationInvoker {
+ 
+   protected static final long DEFAULT_INITIAL_DELAY = TimeUnit.SECONDS.toMillis(1);
+   protected static final long DEFAULT_PERIOD = TimeUnit.MILLISECONDS.toMillis(500);
+ 
+   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 PING_LINK_RELATION = "ping";
+   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();
+ 
+   protected static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MILLISECONDS;
+ 
+   // the ID of the GemFire distributed system (cluster)
+   private Integer clusterId = CLUSTER_ID_WHEN_NOT_CONNECTED;
+ 
+   // Executor for scheduling periodic Runnable task to assess the state of the Manager's HTTP service or Web Service
+   // hosting the M&M REST API (interface)
+   private final ScheduledExecutorService executorService;
+ 
+   // 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<MediaType> 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 = LogService.getLogger();
+ 
+   // the Spring RestTemplate used to send HTTP requests and make REST API calls
+   private volatile RestTemplate restTemplate;
+ 
+   // the base URL of the GemFire Manager's embedded HTTP service and REST API interface
+   private final String baseUrl;
++  
++  
++  protected Map<String,String> securityProperties;
+ 
+   /**
+    * Default, public, no-arg constructor to create an instance of the AbstractHttpOperationInvoker class 
+    * for testing purposes.
+    */
+   AbstractHttpOperationInvoker(final String baseUrl) {
+     this.baseUrl = baseUrl;
+     this.executorService = null;
+     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 #AbstractHttpOperationInvoker(com.gemstone.gemfire.management.internal.cli.shell.Gfsh, String, Map)
+    * @see com.gemstone.gemfire.management.internal.cli.shell.Gfsh
+    */
 -  public AbstractHttpOperationInvoker(final Gfsh gfsh) {
 -    this(gfsh, REST_API_URL);
++  public AbstractHttpOperationInvoker(final Gfsh gfsh, Map<String,String> securityProperties) {
++    this(gfsh, REST_API_URL, securityProperties);
+   }
+ 
+   /**
+    * 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) {
++  public AbstractHttpOperationInvoker(final Gfsh gfsh, final String baseUrl, Map<String,String> securityProperties) {
+     assertNotNull(gfsh, "The reference to the GemFire shell (Gfsh) cannot be null!");
+ 
+     this.gfsh = gfsh;
+     this.baseUrl = StringUtils.defaultIfBlank(baseUrl, REST_API_URL);
 -
++    this.securityProperties = securityProperties;
++  
+     // constructs an instance of a single-threaded, scheduled Executor to send periodic HTTP requests to the Manager's
+     // HTTP service or Web Service to assess the "alive" state
+     this.executorService = Executors.newSingleThreadScheduledExecutor();
+ 
+     // constructs an instance of the Spring RestTemplate for M&M REST API (interface) operations
+     this.restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory());
+ 
+     // add our custom HttpMessageConverter for serializing DTO Objects into the HTTP request message body
+     // and de-serializing HTTP response message body content back into DTO Objects
+     this.restTemplate.getMessageConverters().add(new SerializableObjectHttpMessageConverter());
+ 
+     // set the ResponseErrorHandler handling any errors originating from our HTTP request
+     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 CONFLICT: // 409
+           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);
++        //gfsh.logSevere(message, null);
+ 
+         if (gfsh.getDebug()) {
+           gfsh.logSevere(readBody(response), null);
+         }
++        throw new RuntimeException(message);
+       }
+ 
+       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);
+         }
+       }
+     });
+   }
+ 
+   /**
+    * Asserts the argument is valid, as determined by the caller passing the result of an evaluated expression to this
+    * assertion.
+    * 
+    * @param validArg a boolean value indicating the evaluation of the expression validating the argument.
+    * @param message a String value used as the message when constructing an IllegalArgumentException.
+    * @param args Object arguments used to populate placeholder's in the message.
+    * @throws IllegalArgumentException if the argument is not valid.
+    * @see java.lang.String#format(String, Object...)
+    */
+   protected static void assertArgument(final boolean validArg, final String message, final Object... args) {
+     if (!validArg) {
+       throw new IllegalArgumentException(String.format(message, args));
+     }
+   }
+ 
+   /**
+    * Asserts the Object reference is not null!
+    * 
+    * @param obj the reference to the Object.
+    * @param message the String value used as the message when constructing and throwing a NullPointerException.
+    * @param args Object arguments used to populate placeholder's in the message.
+    * @throws NullPointerException if the Object reference is null.
+    * @see java.lang.String#format(String, Object...)
+    */
+   protected static void assertNotNull(final Object obj, final String message, final Object... args) {
+     if (obj == null) {
+       throw new NullPointerException(String.format(message, args));
+     }
+   }
+ 
+   /**
+    * Asserts whether state, based on the evaluation of a conditional expression, passed to this assertion is valid.
+    * 
+    * @param validState a boolean value indicating the evaluation of the expression from which the conditional state
+    * is based.  For example, a caller might use an expression of the form (initableObj.isInitialized()).
+    * @param message a String values used as the message when constructing an IllegalStateException.
+    * @param args Object arguments used to populate placeholder's in the message.
+    * @throws IllegalStateException if the conditional state is not valid.
+    * @see java.lang.String#format(String, Object...)
+    */
+   protected static void assertState(final boolean validState, final String message, final Object... args) {
+     if (!validState) {
+       throw new IllegalStateException(String.format(message, args));
+     }
+   }
+ 
+   /**
+    * 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<MediaType> 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();
+   }
+ 
+   /**
+    * Gets the ExecutorService used by this HTTP OperationInvoker to scheduled periodic or delayed tasks.
+    * 
+    * @return an instance of the ScheduledExecutorService for scheduling periodic or delayed tasks.
+    * @see java.util.concurrent.ScheduledExecutorService
+    */
+   protected final ScheduledExecutorService getExecutorService() {
+     assertState(this.executorService != null,
+       "The ExecutorService for this HTTP OperationInvoker (%1$s) was not properly initialized!",
+         getClass().getName());
+     return this.executorService;
+   }
+ 
+   /**
+    * 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;
+   }
+ 
+   /**
+    * 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());
++    
++    if(this.securityProperties != null){
++      Iterator<Entry<String, String>> it = this.securityProperties.entrySet().iterator();
++      while(it.hasNext()){
++        Entry<String,String> entry= it.next();
++        request.addHeaderValues(entry.getKey(), entry.getValue());
++      }
++    }
+     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 <T> 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 <T> ResponseEntity<T> send(final ClientHttpRequest request, final Class<T> responseType) {
+     return send(request, responseType, Collections.<String, Object>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 <T> ResponseEntity<T> send(final ClientHttpRequest request, final Class<T> responseType, final Map<String, ?> 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<T> 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());
++      
++      printInfo("HTTP response body: ", response.getBody());
+     }
+ 
+     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.addParameterValues("resourceName", resourceName);
+       request.addParameterValues("attributeName", attributeName);
+ 
+       final ResponseEntity<byte[]> 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;
+   }
+ 
+   protected 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 <T> 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> T getMBeanProxy(final ObjectName objectName, final Class<T> 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.addParameterValues("resourceName", resourceName);
+       request.addParameterValues("operationName", operationName);
+       request.addParameterValues("signature", (Object[]) signature);
+       request.addParameterValues("parameters", params); // TODO may need to convert method parameter arguments
+ 
+       final ResponseEntity<byte[]> 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<ObjectName> 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<byte[]> response = send(request, byte[].class);
+ 
+       try {
+         return (Set<ObjectName>) 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() {
+     if (executorService != null) {
+       executorService.shutdown();
+     }
+ 
+     restTemplate = null;
+   }
+ 
+   @Override
+   public String toString() {
+     return String.format("GemFire Manager HTTP service @ %1$s", getBaseUrl());
+   }
 -
++  
+ }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5c01d5f4/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/shell/RestHttpOperationInvoker.java
----------------------------------------------------------------------
diff --cc geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/shell/RestHttpOperationInvoker.java
index 0000000,aba05ca..8235f32
mode 000000,100644..100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/shell/RestHttpOperationInvoker.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/shell/RestHttpOperationInvoker.java
@@@ -1,0 -1,424 +1,438 @@@
+ /*
+  * 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 com.gemstone.gemfire.management.internal.web.shell;
+ 
+ import java.io.IOException;
+ import java.util.ArrayList;
+ import java.util.HashMap;
++import java.util.Iterator;
+ import java.util.List;
+ import java.util.Map;
++import java.util.Map.Entry;
+ 
+ import com.gemstone.gemfire.internal.lang.Filter;
+ import com.gemstone.gemfire.internal.lang.Initable;
+ import com.gemstone.gemfire.internal.lang.StringUtils;
+ import com.gemstone.gemfire.internal.logging.LogService;
+ import com.gemstone.gemfire.internal.util.CollectionUtils;
+ import com.gemstone.gemfire.management.internal.cli.CommandRequest;
+ import com.gemstone.gemfire.management.internal.cli.i18n.CliStrings;
+ import com.gemstone.gemfire.management.internal.cli.shell.Gfsh;
++import com.gemstone.gemfire.management.internal.security.ResourceConstants;
+ import com.gemstone.gemfire.management.internal.web.domain.Link;
+ import com.gemstone.gemfire.management.internal.web.domain.LinkIndex;
+ 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.util.ConvertUtils;
+ 
+ import org.apache.logging.log4j.Logger;
+ import org.springframework.http.HttpMethod;
+ import org.springframework.http.HttpStatus;
+ import org.springframework.http.ResponseEntity;
+ import org.springframework.http.client.ClientHttpResponse;
+ import org.springframework.web.client.ResourceAccessException;
+ import org.springframework.web.util.UriTemplate;
+ 
+ /**
+  * The RestHttpOperationInvoker class is an implementation of the OperationInvoker interface that translates (adapts) 
+  * GemFire shell command invocations into HTTP requests to a corresponding REST API call hosted by the GemFire Manager's
+  * HTTP service using the Spring RestTemplate.
+  * 
+  * @author John Blum
+  * @see com.gemstone.gemfire.internal.lang.Initable
+  * @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.AbstractHttpOperationInvoker
+  * @see com.gemstone.gemfire.management.internal.web.shell.HttpOperationInvoker
+  * @see com.gemstone.gemfire.management.internal.web.shell.SimpleHttpOperationInvoker
+  * @since 8.0
+  */
+ @SuppressWarnings("unused")
+ public class RestHttpOperationInvoker extends AbstractHttpOperationInvoker implements Initable {
+ 
+   private static final Logger logger = LogService.getLogger();
+   
+   protected static final String ENVIRONMENT_VARIABLE_REQUEST_PARAMETER_PREFIX = "vf.gf.env.";
+   protected static final String RESOURCES_REQUEST_PARAMETER = "resources";
+ 
+   // the HttpOperationInvoker used when this RestHttpOperationInvoker is unable to resolve the correct REST API
+   // web service endpoint (URI) for a command
+   private final HttpOperationInvoker httpOperationInvoker;
+ 
+   // the LinkIndex containing Links to all GemFire REST API web service endpoints
+   private final LinkIndex linkIndex;
+ 
++
+   /**
+    * Constructs an instance of the RestHttpOperationInvoker class initialized with the given link index containing links
+    * referencing all REST API web service endpoints.  This constructor should only be used for testing purposes.
+    * 
+    * @param linkIndex the LinkIndex containing Links to all REST API web service endpoints in GemFire's REST interface.
+    * @see com.gemstone.gemfire.management.internal.web.domain.LinkIndex
+    */
+   RestHttpOperationInvoker(final LinkIndex linkIndex) {
+     super(REST_API_URL);
+     assertNotNull(linkIndex, "The Link Index resolving commands to REST API web service endpoints cannot be null!");
+     this.linkIndex = linkIndex;
+     this.httpOperationInvoker = new SimpleHttpOperationInvoker();
+   }
+ 
+   /**
+    * Constructs an instance of the RestHttpOperationInvoker class initialized with the given link index containing links
+    * referencing all REST API web service endpoints.  In addition, a reference to the instance of GemFire shell (Gfsh)
+    * using this RestHttpOperationInvoker to send command invocations to the GemFire Manager's HTTP service via HTTP
+    * for processing is required in order to interact with the shell and provide feedback to the user.
+    * 
+    * @param linkIndex the LinkIndex containing Links to all REST API web service endpoints in GemFire' REST interface.
+    * @param gfsh a reference to the instance of the GemFire shell using this OperationInvoker to process commands.
 -   * @see #RestHttpOperationInvoker(com.gemstone.gemfire.management.internal.web.domain.LinkIndex, com.gemstone.gemfire.management.internal.cli.shell.Gfsh, String)
++   * @see #RestHttpOperationInvoker(com.gemstone.gemfire.management.internal.web.domain.LinkIndex, com.gemstone.gemfire.management.internal.cli.shell.Gfsh,  Map)
+    * @see com.gemstone.gemfire.management.internal.cli.shell.Gfsh
+    * @see com.gemstone.gemfire.management.internal.web.domain.LinkIndex
+    */
 -  public RestHttpOperationInvoker(final LinkIndex linkIndex, final Gfsh gfsh) {
 -    this(linkIndex, gfsh, CliStrings.CONNECT__DEFAULT_BASE_URL);
++  public RestHttpOperationInvoker(final LinkIndex linkIndex, final Gfsh gfsh, Map<String,String> securityProperties) {
++    this(linkIndex, gfsh, CliStrings.CONNECT__DEFAULT_BASE_URL, securityProperties);
+   }
+ 
+   /**
+    * Constructs an instance of the RestHttpOperationInvoker class initialized with the given link index containing links
+    * referencing all REST API web service endpoints.  In addition, a reference to the instance of GemFire shell (Gfsh)
+    * using this RestHttpOperationInvoker to send command invocations to the GemFire Manager's HTTP service via HTTP
+    * for processing is required in order to interact with the shell and provide feedback to the user.  Finally, a URL
+    * to the HTTP service running in the GemFire Manager is specified as the base location for all HTTP requests.
+    * 
+    * @param linkIndex the LinkIndex containing Links to all REST API web service endpoints in GemFire's REST interface.
+    * @param gfsh a reference to the instance of the GemFire shell using this OperationInvoker to process commands.
+    * @param baseUrl the String specifying the base URL to the GemFire Manager's HTTP service, REST interface.
+    * @see com.gemstone.gemfire.management.internal.web.domain.LinkIndex
+    * @see com.gemstone.gemfire.management.internal.cli.shell.Gfsh
+    */
 -  public RestHttpOperationInvoker(final LinkIndex linkIndex, final Gfsh gfsh, final String baseUrl) {
 -    super(gfsh, baseUrl);
++  public RestHttpOperationInvoker(final LinkIndex linkIndex, final Gfsh gfsh, final String baseUrl, Map<String,String> securityProperties) {
++    super(gfsh, baseUrl, securityProperties);
+     assertNotNull(linkIndex, "The Link Index resolving commands to REST API web service endpoints cannot be null!");
+     this.linkIndex = linkIndex;
 -    this.httpOperationInvoker = new SimpleHttpOperationInvoker(gfsh, baseUrl);
++    this.httpOperationInvoker = new SimpleHttpOperationInvoker(gfsh, baseUrl, securityProperties);
++
+   }
+ 
+   /**
+    * Initializes the RestHttpOperationInvokers scheduled and periodic monitoring task to assess the availibity of the
+    * targeted GemFire Manager's HTTP service.
+    * 
+    * @see com.gemstone.gemfire.internal.lang.Initable#init()
+    * @see org.springframework.http.client.ClientHttpRequest
+    */
+   @SuppressWarnings("null")
+   public void init() {
+     final Link pingLink = getLinkIndex().find(PING_LINK_RELATION);
+ 
+     if (pingLink != null) {
+       if (logger.isDebugEnabled()) {
+         logger.debug("Scheduling periodic HTTP ping requests to monitor the availability of the GemFire Manager HTTP service @ ({})",
+             getBaseUrl());
+       }
+ 
+       getExecutorService().scheduleAtFixedRate(new Runnable() {
+         public void run() {
+           try {
+             org.springframework.http.client.ClientHttpRequest httpRequest = getRestTemplate().getRequestFactory()
+               .createRequest(pingLink.getHref(), HttpMethod.HEAD);
+ 
+             httpRequest.getHeaders().set(HttpHeader.USER_AGENT.getName(), USER_AGENT_HTTP_REQUEST_HEADER_VALUE);
+             httpRequest.getHeaders().setAccept(getAcceptableMediaTypes());
+             httpRequest.getHeaders().setContentLength(0l);
+ 
++            if(securityProperties != null){
++              Iterator<Entry<String, String>> it = securityProperties.entrySet().iterator();
++              while(it.hasNext()){
++                Entry<String,String> entry= it.next();
++                httpRequest.getHeaders().add(entry.getKey(), entry.getValue());
++              }
++            }
++
+             ClientHttpResponse httpResponse = httpRequest.execute();
+ 
+             if (HttpStatus.NOT_FOUND.equals(httpResponse.getStatusCode())) {
+               throw new IOException(String.format("The HTTP service at URL (%1$s) could not be found!",
+                 pingLink.getHref()));
+             }
+             else if (!HttpStatus.OK.equals(httpResponse.getStatusCode())) {
+               printDebug("Received unexpected HTTP status code (%1$d - %2$s) for HTTP request (%3$s).",
+                 httpResponse.getRawStatusCode(), httpResponse.getStatusText(), pingLink.getHref());
+             }
+           }
+           catch (IOException e) {
+             printDebug("An error occurred while connecting to the Manager's HTTP service: %1$s: ", e.getMessage());
+             getGfsh().notifyDisconnect(RestHttpOperationInvoker.this.toString());
+             stop();
+           }
+         }
+       }, DEFAULT_INITIAL_DELAY, DEFAULT_PERIOD, DEFAULT_TIME_UNIT);
+     }
+     else {
+       if (logger.isDebugEnabled()) {
+         logger.debug("The Link to the GemFire Manager web service endpoint @ ({}) to monitor availability was not found!",
+             getBaseUrl());
+       }
+     }
+ 
+     initClusterId();
+   }
+ 
+   /**
+    * Returns a reference to an implementation of HttpOperationInvoker used as the fallback by this
+    * RestHttpOperationInvoker for processing commands via HTTP requests.
+    * 
+    * @return an instance of HttpOperationInvoker used by this RestHttpOperationInvoker as a fallback to process commands
+    * via HTTP requests.
+    * @see com.gemstone.gemfire.management.internal.web.shell.HttpOperationInvoker
+    */
+   protected HttpOperationInvoker getHttpOperationInvoker() {
+     return httpOperationInvoker;
+   }
+ 
+   /**
+    * Returns the LinkIndex resolving Gfsh commands to GemFire REST API web service endpoints.  The corresponding
+    * web service endpoint is a URI/URL uniquely identifying the resource on which the command was invoked.
+    * 
+    * @return the LinkIndex containing Links for all GemFire REST API web service endpoints.
+    * @see com.gemstone.gemfire.management.internal.web.domain.LinkIndex
+    */
+   protected LinkIndex getLinkIndex() {
+     return linkIndex;
+   }
+ 
+   /**
+    * Creates an HTTP request from the specified command invocation encapsulated by the CommandRequest object.
+    * The CommandRequest identifies the resource targeted by the command invocation along with any parameters to be sent
+    * as part of the HTTP request.
+    * 
+    * @param command the CommandRequest object encapsulating details of the command invocation.
+    * @return a client HTTP request detailing the operation to be performed on the remote resource targeted by the
+    * command invocation.
+    * @see AbstractHttpOperationInvoker#createHttpRequest(com.gemstone.gemfire.management.internal.web.domain.Link)
+    * @see com.gemstone.gemfire.management.internal.cli.CommandRequest
+    * @see com.gemstone.gemfire.management.internal.web.http.ClientHttpRequest
+    * @see com.gemstone.gemfire.management.internal.web.util.ConvertUtils#convert(byte[][])
+    */
+   protected ClientHttpRequest createHttpRequest(final CommandRequest command) {
+     ClientHttpRequest request = createHttpRequest(findLink(command));
+ 
+     //request.getParameters().setAll(new HashMap<String, Object>(CollectionUtils.removeKeys(
+     //  new HashMap<String, String>(command.getParameters()), ExcludeNoValueFilter.INSTANCE)));
+ 
+     Map<String, String> commandParameters = command.getParameters();
+ 
+     for (Map.Entry<String, String> entry : commandParameters.entrySet()) {
+       if (NullValueFilter.INSTANCE.accept(entry)) {
+         request.addParameterValues(entry.getKey(), entry.getValue());
+       }
+     }
+ 
+     Map<String, String> environmentVariables = command.getEnvironment();
+ 
+     for (Map.Entry<String, String> entry : environmentVariables.entrySet()) {
+       if (EnvironmentVariableFilter.INSTANCE.accept(entry)) {
+         request.addParameterValues(ENVIRONMENT_VARIABLE_REQUEST_PARAMETER_PREFIX + entry.getKey(), entry.getValue());
+       }
+     }
+ 
++    
+     if (command.getFileData() != null) {
+       request.addParameterValues(RESOURCES_REQUEST_PARAMETER, (Object[]) ConvertUtils.convert(command.getFileData()));
+     }
+ 
+     return request;
+   }
+ 
+   /**
+    * Finds a Link from the Link Index containing the HTTP request URI to the web service endpoint for the relative
+    * operation on the resource.
+    * 
+    * @param relation a String describing the relative operation (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 #getLinkIndex()
+    * @see com.gemstone.gemfire.management.internal.web.domain.Link
+    * @see com.gemstone.gemfire.management.internal.web.domain.LinkIndex#find(String)
+    */
+   @Override
+   protected Link findLink(final String relation) {
+     return getLinkIndex().find(relation);
+   }
+ 
+   /**
+    * Finds a Link from the Link Index corresponding to the command invocation.  The CommandRequest indicates the
+    * intended function on the target resource so the proper Link based on it's relation (the state transition of the
+    * corresponding function), along with it's method of operation and corresponding REST API web service endpoint (URI),
+    * can be identified.
+    * 
+    * @param command the CommandRequest object encapsulating the details of the command invocation.
+    * @return a Link referencing the correct REST API web service endpoint (URI) and method for the command invocation.
+    * @see #getLinkIndex()
+    * @see #resolveLink(com.gemstone.gemfire.management.internal.cli.CommandRequest, java.util.List)
+    * @see com.gemstone.gemfire.management.internal.cli.CommandRequest
+    * @see com.gemstone.gemfire.management.internal.web.domain.Link
+    * @see com.gemstone.gemfire.management.internal.web.domain.LinkIndex
+    */
+   protected Link findLink(final CommandRequest command) {
+     List<Link> linksFound = new ArrayList<>(getLinkIndex().size());
+ 
+     for (Link link : getLinkIndex()) {
+       if (command.getInput().startsWith(link.getRelation())) {
+         linksFound.add(link);
+       }
+     }
+ 
+     if (linksFound.isEmpty()) {
+       throw new RestApiCallForCommandNotFoundException(String.format("No REST API call for command (%1$s) was found!",
+         command.getInput()));
+     }
+ 
+     return (linksFound.size() > 1 ? resolveLink(command, linksFound) : linksFound.get(0));
+   }
+ 
+   /**
+    * Resolves one Link from a Collection of Links based on the command invocation matching multiple relations from
+    * the Link Index.
+    * 
+    * @param command the CommandRequest object encapsulating details of the command invocation.
+    * @param links a Collection of Links for the command matching the relation.
+    * @return the resolved Link matching the command exactly as entered by the user.
+    * @see #findLink(com.gemstone.gemfire.management.internal.cli.CommandRequest)
+    * @see com.gemstone.gemfire.management.internal.cli.CommandRequest
+    * @see com.gemstone.gemfire.management.internal.web.domain.Link
+    * @see org.springframework.web.util.UriTemplate
+    */
+   // Find and use the Link with the greatest number of path variables that can be expanded!
+   protected Link resolveLink(final CommandRequest command, final List<Link> links) {
+     // NOTE, Gfsh's ParseResult contains a Map entry for all command options whether or not the user set the option
+     // with a value on the command-line, argh!
+     Map<String, String> commandParametersCopy = CollectionUtils.removeKeys(
+       new HashMap<>(command.getParameters()), NoValueFilter.INSTANCE);
+ 
+     Link resolvedLink = null;
+ 
+     int pathVariableCount = 0;
+ 
+     for (Link link : links) {
+       final List<String> pathVariables = new UriTemplate(decode(link.getHref().toString())).getVariableNames();
+ 
+       // first, all path variables in the URL/URI template must be resolvable/expandable for this Link
+       // to even be considered...
+       if (commandParametersCopy.keySet().containsAll(pathVariables)) {
+         // then, either we have not found a Link for the command yet, or the number of resolvable/expandable
+         // path variables in this Link has to be greater than the number of resolvable/expandable path variables
+         // for the last Link
+         if (resolvedLink == null || (pathVariables.size() > pathVariableCount)) {
+           resolvedLink = link;
+           pathVariableCount = pathVariables.size();
+         }
+       }
+     }
+ 
+     if (resolvedLink == null) {
+       throw new RestApiCallForCommandNotFoundException(String.format("No REST API call for command (%1$s) was found!",
+         command.getInput()));
+     }
+ 
+     return resolvedLink;
+   }
+ 
+   /**
+    * Processes the requested command.  Sends the command to the GemFire Manager for remote processing (execution).
+    * 
+    * @param command the command requested/entered by the user to be processed.
+    * @return the result of the command execution.
+    * @see #createHttpRequest(com.gemstone.gemfire.management.internal.cli.CommandRequest)
+    * @see #handleResourceAccessException(org.springframework.web.client.ResourceAccessException)
+    * @see #isConnected()
+    * @see #send(com.gemstone.gemfire.management.internal.web.http.ClientHttpRequest, Class, java.util.Map)
+    * @see #simpleProcessCommand(com.gemstone.gemfire.management.internal.cli.CommandRequest, RestApiCallForCommandNotFoundException)
+    * @see com.gemstone.gemfire.management.internal.cli.CommandRequest
+    * @see org.springframework.http.ResponseEntity
+    */
+   @Override
+   public String processCommand(final CommandRequest command) {
+     assertState(isConnected(), "Gfsh must be connected to the GemFire Manager in order to process commands remotely!");
+ 
+     try {
+       ResponseEntity<String> response = send(createHttpRequest(command), String.class, command.getParameters());
+ 
+       return response.getBody();
+     }
+     catch (RestApiCallForCommandNotFoundException e) {
+       return simpleProcessCommand(command, e);
+     }
+     catch (ResourceAccessException e) {
+       return handleResourceAccessException(e);
+     }
+   }
+ 
+   /**
+    * A method to process the command by sending an HTTP request to the simple URL/URI web service endpoint, where all
+    * details of the request and command invocation are encoded in the URL/URI.
+    * 
+    * @param command the CommandRequest encapsulating the details of the command invocation.
+    * @param e the RestApiCallForCommandNotFoundException indicating the standard REST API web service endpoint
+    * could not be found.
+    * @return the result of the command execution.
+    * @see #getHttpOperationInvoker()
+    * @see com.gemstone.gemfire.management.internal.web.shell.HttpOperationInvoker#processCommand(com.gemstone.gemfire.management.internal.cli.CommandRequest)
+    * @see com.gemstone.gemfire.management.internal.cli.CommandRequest
+    */
+   protected String simpleProcessCommand(final CommandRequest command, final RestApiCallForCommandNotFoundException e) {
+     if (getHttpOperationInvoker() != null) {
+       printWarning("WARNING - No REST API web service endpoint (URI) exists for command (%1$s); using the non-RESTful, simple URI.",
+         command.getName());
+ 
+       return String.valueOf(getHttpOperationInvoker().processCommand(command));
+     }
+ 
+     throw e;
+   }
+ 
+   protected static class EnvironmentVariableFilter extends NoValueFilter {
+ 
+     protected static final EnvironmentVariableFilter INSTANCE = new EnvironmentVariableFilter();
+ 
+     @Override
+     public boolean accept(final Map.Entry<String, String> entry) {
+       return (!entry.getKey().startsWith("SYS") && super.accept(entry));
+     }
+   }
+ 
+   protected static class NoValueFilter implements Filter<Map.Entry<String, String>> {
+ 
+     protected static final NoValueFilter INSTANCE = new NoValueFilter();
+ 
+     @Override
+     public boolean accept(final Map.Entry<String, String> entry) {
+       return !StringUtils.isBlank(entry.getValue());
+     }
+   }
+ 
+   protected static class NullValueFilter implements Filter<Map.Entry<String, ?>> {
+ 
+     protected static final NullValueFilter INSTANCE = new NullValueFilter();
+ 
+     @Override
+     public boolean accept(final Map.Entry<String, ?> entry) {
+       return (entry.getValue() != null);
+     }
+   }
+ 
+ }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5c01d5f4/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/shell/SimpleHttpOperationInvoker.java
----------------------------------------------------------------------
diff --cc geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/shell/SimpleHttpOperationInvoker.java
index 0000000,c01e0c6..ce83444
mode 000000,100644..100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/shell/SimpleHttpOperationInvoker.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/web/shell/SimpleHttpOperationInvoker.java
@@@ -1,0 -1,161 +1,162 @@@
+ /*
+  * 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 com.gemstone.gemfire.management.internal.web.shell;
+ 
+ import java.net.URI;
++import java.util.Map;
+ 
+ import com.gemstone.gemfire.management.internal.cli.CommandRequest;
+ 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.http.ClientHttpRequest;
+ import com.gemstone.gemfire.management.internal.web.http.HttpMethod;
+ 
+ import org.springframework.http.ResponseEntity;
+ import org.springframework.web.client.ResourceAccessException;
+ import org.springframework.web.util.UriComponentsBuilder;
+ 
+ /**
+  * The SimpleHttpOperationInvoker class is an implementation of the OperationInvoker interface that issues commands
+  * to the GemFire Manager via HTTP.  The SimpleHttpOperationInvoker uses a single URL web service endpoint to process
+  * commands and return responses.
+  * 
+  * @author John Blum
+  * @see java.net.URI
+  * @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.AbstractHttpOperationInvoker
+  * @see com.gemstone.gemfire.management.internal.web.shell.HttpOperationInvoker
+  * @see com.gemstone.gemfire.management.internal.web.shell.RestHttpOperationInvoker
+  * @since 8.0
+  */
+ @SuppressWarnings("unused")
+ public class SimpleHttpOperationInvoker extends AbstractHttpOperationInvoker {
+ 
+   protected static final String CMD_QUERY_PARAMETER = "cmd";
+   protected static final String LINK_RELATION = "simple";
+   protected static final String REST_API_MANAGEMENT_COMMANDS_URI = "/management/commands";
+ 
+   /**
+    * Default no-arg constructor to create an instance of the SimpleHttpOperationInvoker class for testing purposes.
+    */
+   SimpleHttpOperationInvoker() {
+     super(REST_API_URL);
+   }
+ 
+   /**
+    * Constructs an instance of the SimpleHttpOperationInvoker class initialized with a reference to the GemFire shell
+    * (Gfsh) using this HTTP-based OperationInvoker to send command invocations to the GemFire Manager's HTTP service
+    * using HTTP processing.
+    * 
+    * @param gfsh a reference to the instance of the GemFire shell using this OperationInvoker to process commands.
 -   * @see #SimpleHttpOperationInvoker(com.gemstone.gemfire.management.internal.cli.shell.Gfsh, String)
++   * @see #SimpleHttpOperationInvoker(com.gemstone.gemfire.management.internal.cli.shell.Gfsh, String, Map)
+    * @see com.gemstone.gemfire.management.internal.cli.shell.Gfsh
+    */
 -  public SimpleHttpOperationInvoker(final Gfsh gfsh) {
 -    this(gfsh, REST_API_URL);
++  public SimpleHttpOperationInvoker(final Gfsh gfsh, Map<String,String> securityProperties) {
++    this(gfsh, REST_API_URL, securityProperties);
+   }
+ 
+   /**
+    * Constructs an instance of the SimpleHttpOperationInvoker class initialized with a reference to the GemFire shell
+    * (Gfsh) using this HTTP-based OperationInvoker to send command invocations to the GemFire Manager's HTTP service
+    * using HTTP for processing.  In addition, the base URL to the HTTP service running in the GemFire Manager is
+    * specified as the base location for all HTTP requests.
+    * 
+    * @param gfsh a reference to the instance of the GemFire shell using this OperationInvoker to process commands.
+    * @param baseUrl the base URL to the GemFire Manager's HTTP service.
+    * @see com.gemstone.gemfire.management.internal.cli.shell.Gfsh
+    */
 -  public SimpleHttpOperationInvoker(final Gfsh gfsh, final String baseUrl) {
 -    super(gfsh, baseUrl);
++  public SimpleHttpOperationInvoker(final Gfsh gfsh, final String baseUrl, Map<String,String> securityProperties) {
++    super(gfsh, baseUrl, securityProperties);
+   }
+ 
+   /**
+    * Creates an HTTP request from a command invocation encapsulated in a CommandRequest object.  The CommandRequest
+    * identifies the resource targeted by the command invocation along with any parameters to be sent as part of the
+    * HTTP request.
+    * 
+    * @param command a CommandRequest object encapsulating the details of the command invocation.
+    * @return a client HTTP request detailing the operation to be performed on the remote resource targeted by the
+    * command invocation.
+    * @see #createLink(com.gemstone.gemfire.management.internal.cli.CommandRequest)
+    * @see AbstractHttpOperationInvoker#createHttpRequest(com.gemstone.gemfire.management.internal.web.domain.Link)
+    * @see com.gemstone.gemfire.management.internal.cli.CommandRequest
+    * @see com.gemstone.gemfire.management.internal.web.http.ClientHttpRequest
+    */
+   protected ClientHttpRequest createHttpRequest(final CommandRequest command) {
+     return createHttpRequest(createLink(command));
+   }
+ 
+   /**
+    * Creates a Link based on the resource being targeted by the command invocation.  The Link will contain the URI
+    * uniquely identifying the resource along with the HTTP GET operation specifying the method of processing.
+    * 
+    * @param command a CommandRequest object encapsulating the details of the command invocation.
+    * @return a Link identifying the resource and the operation on the resource.
+    * @see AbstractHttpOperationInvoker#createLink(String, java.net.URI, com.gemstone.gemfire.management.internal.web.http.HttpMethod)
+    * @see com.gemstone.gemfire.management.internal.cli.CommandRequest
+    * @see com.gemstone.gemfire.management.internal.web.domain.Link
+    */
+   protected Link createLink(final CommandRequest command) {
+     return createLink(LINK_RELATION, getHttpRequestUrl(command), HttpMethod.POST);
+   }
+ 
+   /**
+    * Gets HTTP request URL (URI) locating the proper resource along with details for the request.
+    * 
+    * @param command a CommandRequest object encapsulating the details of the command invocation.
+    * @return a URI identifying the resource, it's location as well as details of the HTTP request.
+    * @see com.gemstone.gemfire.management.internal.cli.CommandRequest
+    * @see java.net.URI
+    * @see com.gemstone.gemfire.management.internal.cli.CommandRequest
+    * @see org.springframework.web.util.UriComponentsBuilder
+    */
+   protected URI getHttpRequestUrl(final CommandRequest command) {
+     return UriComponentsBuilder.fromHttpUrl(getBaseUrl())
+       .path(REST_API_MANAGEMENT_COMMANDS_URI)
+       .queryParam(CMD_QUERY_PARAMETER, command.getInput())
+       .build().encode().toUri();
+   }
+ 
+   /**
+    * Processes the requested command.  Sends the command to the GemFire Manager for remote processing (execution).
+    * 
+    * @param command the command requested/entered by the user to be processed.
+    * @return the result of the command execution.
+    * @see #isConnected()
+    * @see #createHttpRequest(com.gemstone.gemfire.management.internal.cli.CommandRequest)
+    * @see AbstractHttpOperationInvoker#handleResourceAccessException(org.springframework.web.client.ResourceAccessException)
+    * @see AbstractHttpOperationInvoker#send(com.gemstone.gemfire.management.internal.web.http.ClientHttpRequest, Class)
+    * @see com.gemstone.gemfire.management.internal.cli.CommandRequest
+    * @see org.springframework.http.ResponseEntity
+    */
+   @Override
+   public String processCommand(final CommandRequest command) {
+     assertState(isConnected(), "Gfsh must be connected to the GemFire Manager in order to process commands remotely!");
+ 
+     try {
+       final ResponseEntity<String> response = send(createHttpRequest(command), String.class);
+ 
+       return response.getBody();
+     }
+     catch (ResourceAccessException e) {
+       return handleResourceAccessException(e);
+     }
+   }
+ 
+ }



Mime
View raw message