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

org.apache.geode.management.internal.cli.functions.DataCommandFunction Maven / Gradle / Ivy

Go to download

Apache Geode provides a database-like consistency model, reliable transaction processing and a shared-nothing architecture to maintain very low latency performance with high concurrency processing

There is a newer version: 1.15.1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.geode.management.internal.cli.functions;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.subject.Subject;
import org.json.JSONArray;

import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheClosedException;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.execute.FunctionAdapter;
import org.apache.geode.cache.execute.FunctionContext;
import org.apache.geode.cache.partition.PartitionRegionHelper;
import org.apache.geode.cache.query.FunctionDomainException;
import org.apache.geode.cache.query.NameResolutionException;
import org.apache.geode.cache.query.Query;
import org.apache.geode.cache.query.QueryInvalidException;
import org.apache.geode.cache.query.QueryInvocationTargetException;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.cache.query.SelectResults;
import org.apache.geode.cache.query.Struct;
import org.apache.geode.cache.query.TypeMismatchException;
import org.apache.geode.cache.query.internal.CompiledValue;
import org.apache.geode.cache.query.internal.DefaultQuery;
import org.apache.geode.cache.query.internal.IndexTrackingQueryObserver;
import org.apache.geode.cache.query.internal.QCompiler;
import org.apache.geode.cache.query.internal.QueryObserver;
import org.apache.geode.cache.query.internal.QueryObserverHolder;
import org.apache.geode.cache.query.internal.StructImpl;
import org.apache.geode.cache.query.internal.Undefined;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.internal.ClassPathLoader;
import org.apache.geode.internal.InternalEntity;
import org.apache.geode.internal.NanoTimer;
import org.apache.geode.internal.cache.PartitionedRegion;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.security.SecurityService;
import org.apache.geode.management.cli.Result;
import org.apache.geode.management.internal.cli.CliUtil;
import org.apache.geode.management.internal.cli.commands.DataCommands;
import org.apache.geode.management.internal.cli.domain.DataCommandRequest;
import org.apache.geode.management.internal.cli.domain.DataCommandResult;
import org.apache.geode.management.internal.cli.domain.DataCommandResult.SelectResultRow;
import org.apache.geode.management.internal.cli.i18n.CliStrings;
import org.apache.geode.management.internal.cli.json.GfJsonException;
import org.apache.geode.management.internal.cli.json.GfJsonObject;
import org.apache.geode.management.internal.cli.multistep.CLIMultiStepHelper;
import org.apache.geode.management.internal.cli.remote.CommandExecutionContext;
import org.apache.geode.management.internal.cli.result.CommandResult;
import org.apache.geode.management.internal.cli.result.CompositeResultData;
import org.apache.geode.management.internal.cli.result.CompositeResultData.SectionResultData;
import org.apache.geode.management.internal.cli.result.ResultBuilder;
import org.apache.geode.management.internal.cli.shell.Gfsh;
import org.apache.geode.management.internal.cli.util.JsonUtil;
import org.apache.geode.pdx.PdxInstance;

/**
 * @since GemFire 7.0
 */
public class DataCommandFunction extends FunctionAdapter implements InternalEntity {
  private static final Logger logger = LogService.getLogger();

  private static final long serialVersionUID = 1L;
  private boolean optimizeForWrite = false;

  protected static final String SELECT_STEP_DISPLAY = "SELECT_DISPLAY";
  protected static final String SELECT_STEP_MOVE = "SELECT_PAGE_MOVE";
  protected static final String SELECT_STEP_END = "SELECT_END";
  protected static final String SELECT_STEP_EXEC = "SELECT_EXEC";
  private static final int NESTED_JSON_LENGTH = 20;

  // this needs to be static so that it won't get serialized
  private static SecurityService securityService = SecurityService.getSecurityService();

  @Override
  public String getId() {
    return DataCommandFunction.class.getName();
  }

  @Override

  public boolean hasResult() {
    return true;
  }

  @Override

  public boolean isHA() {
    return false;
  }

  @Override
  /**
   * Read only function
   */
  public boolean optimizeForWrite() {
    return optimizeForWrite;
  }


  public void setOptimizeForWrite(boolean optimizeForWrite) {
    this.optimizeForWrite = optimizeForWrite;
  }

  @Override
  public void execute(FunctionContext functionContext) {
    try {
      Cache cache = CacheFactory.getAnyInstance();
      DataCommandRequest request = (DataCommandRequest) functionContext.getArguments();
      if (logger.isDebugEnabled()) {
        logger.debug("Executing function : \n{}\n on member {}", request,
            System.getProperty("memberName"));
      }
      DataCommandResult result = null;
      if (request.isGet())
        result = get(request);
      else if (request.isLocateEntry())
        result = locateEntry(request);
      else if (request.isPut())
        result = put(request);
      else if (request.isRemove())
        result = remove(request);
      else if (request.isSelect())
        result = select(request);
      if (logger.isDebugEnabled()) {
        logger.debug("Result is {}", result);
      }
      functionContext.getResultSender().lastResult(result);
    } catch (CacheClosedException e) {
      e.printStackTrace();
      functionContext.getResultSender().sendException(e);
    } catch (Exception e) {
      e.printStackTrace();
      functionContext.getResultSender().sendException(e);
    }
  }



  public DataCommandResult remove(DataCommandRequest request) {
    String key = request.getKey();
    String keyClass = request.getKeyClass();
    String regionName = request.getRegionName();
    String removeAllKeys = request.getRemoveAllKeys();
    return remove(key, keyClass, regionName, removeAllKeys);
  }

  public DataCommandResult get(DataCommandRequest request) {
    String key = request.getKey();
    String keyClass = request.getKeyClass();
    String valueClass = request.getValueClass();
    String regionName = request.getRegionName();
    Boolean loadOnCacheMiss = request.isLoadOnCacheMiss();
    return get(request.getPrincipal(), key, keyClass, valueClass, regionName, loadOnCacheMiss);
  }

  public DataCommandResult locateEntry(DataCommandRequest request) {
    String key = request.getKey();
    String keyClass = request.getKeyClass();
    String valueClass = request.getValueClass();
    String regionName = request.getRegionName();
    boolean recursive = request.isRecursive();
    return locateEntry(key, keyClass, valueClass, regionName, recursive);
  }


  public DataCommandResult put(DataCommandRequest request) {
    String key = request.getKey();
    String value = request.getValue();
    boolean putIfAbsent = request.isPutIfAbsent();
    String keyClass = request.getKeyClass();
    String valueClass = request.getValueClass();
    String regionName = request.getRegionName();
    return put(key, value, putIfAbsent, keyClass, valueClass, regionName);
  }

  public DataCommandResult select(DataCommandRequest request) {
    String query = request.getQuery();
    return select(request.getPrincipal(), query);
  }

  /**
   * To catch trace output
   */
  public static class WrappedIndexTrackingQueryObserver extends IndexTrackingQueryObserver {

    @Override
    public void reset() {
      // NOOP
    }

    public void reset2() {
      super.reset();
    }
  }

  @SuppressWarnings("rawtypes")
  private DataCommandResult select(Object principal, String queryString) {

    Cache cache = CacheFactory.getAnyInstance();
    AtomicInteger nestedObjectCount = new AtomicInteger(0);
    if (queryString != null && !queryString.isEmpty()) {
      QueryService qs = cache.getQueryService();

      // TODO : Find out if is this optimised use. Can you have something equivalent of parsed
      // queries with names
      // where name can be retrieved to avoid parsing every-time
      Query query = qs.newQuery(queryString);
      DefaultQuery tracedQuery = (DefaultQuery) query;
      WrappedIndexTrackingQueryObserver queryObserver = null;
      String queryVerboseMsg = null;
      long startTime = -1;
      if (tracedQuery.isTraced()) {
        startTime = NanoTimer.getTime();
        queryObserver = new WrappedIndexTrackingQueryObserver();
        QueryObserverHolder.setInstance(queryObserver);
      }
      List list = new ArrayList();

      try {
        Object results = query.execute();
        if (tracedQuery.isTraced()) {
          queryVerboseMsg = getLogMessage(queryObserver, startTime, queryString);
          queryObserver.reset2();
        }
        if (results instanceof SelectResults) {
          SelectResults selectResults = (SelectResults) results;
          for (Iterator iter = selectResults.iterator(); iter.hasNext();) {
            Object object = iter.next();
            // Post processing
            object = this.securityService.postProcess(principal, null, null, object, false);

            if (object instanceof Struct) {
              StructImpl impl = (StructImpl) object;
              GfJsonObject jsonStruct = getJSONForStruct(impl, nestedObjectCount);
              if (logger.isDebugEnabled())
                logger.debug("SelectResults : Adding select json string : {}", jsonStruct);
              list.add(new SelectResultRow(DataCommandResult.ROW_TYPE_STRUCT_RESULT,
                  jsonStruct.toString()));
            } else {
              if (JsonUtil.isPrimitiveOrWrapper(object.getClass())) {
                if (logger.isDebugEnabled())
                  logger.debug("SelectResults : Adding select primitive : {}", object);
                list.add(new SelectResultRow(DataCommandResult.ROW_TYPE_PRIMITIVE, object));
              } else {
                if (logger.isDebugEnabled())
                  logger.debug("SelectResults : Bean Results class is {}", object.getClass());
                String str = toJson(object);
                GfJsonObject jsonBean;
                try {
                  jsonBean = new GfJsonObject(str);
                } catch (GfJsonException e) {
                  logger.fatal(e.getMessage(), e);
                  jsonBean = new GfJsonObject();
                  try {
                    jsonBean.put("msg", e.getMessage());
                  } catch (GfJsonException e1) {
                  }
                }
                if (logger.isDebugEnabled())
                  logger.debug("SelectResults : Adding bean json string : {}", jsonBean);
                list.add(new SelectResultRow(DataCommandResult.ROW_TYPE_BEAN, jsonBean.toString()));
              }
            }
          }
        } else {
          if (logger.isDebugEnabled())
            logger.debug("BeanResults : Bean Results class is {}", results.getClass());
          String str = toJson(results);
          GfJsonObject jsonBean;
          try {
            jsonBean = new GfJsonObject(str);
          } catch (GfJsonException e) {
            e.printStackTrace();
            jsonBean = new GfJsonObject();
            try {
              jsonBean.put("msg", e.getMessage());
            } catch (GfJsonException e1) {
            }
          }
          if (logger.isDebugEnabled())
            logger.debug("BeanResults : Adding bean json string : {}", jsonBean);
          list.add(new SelectResultRow(DataCommandResult.ROW_TYPE_BEAN, jsonBean.toString()));
        }
        return DataCommandResult.createSelectResult(queryString, list, queryVerboseMsg, null, null,
            true);

      } catch (FunctionDomainException e) {
        logger.warn(e.getMessage(), e);
        return DataCommandResult.createSelectResult(queryString, null, queryVerboseMsg, e,
            e.getMessage(), false);
      } catch (TypeMismatchException e) {
        logger.warn(e.getMessage(), e);
        return DataCommandResult.createSelectResult(queryString, null, queryVerboseMsg, e,
            e.getMessage(), false);
      } catch (NameResolutionException e) {
        logger.warn(e.getMessage(), e);
        return DataCommandResult.createSelectResult(queryString, null, queryVerboseMsg, e,
            e.getMessage(), false);
      } catch (QueryInvocationTargetException e) {
        logger.warn(e.getMessage(), e);
        return DataCommandResult.createSelectResult(queryString, null, queryVerboseMsg, e,
            e.getMessage(), false);
      } catch (GfJsonException e) {
        logger.warn(e.getMessage(), e);
        return DataCommandResult.createSelectResult(queryString, null, queryVerboseMsg, e,
            e.getMessage(), false);
      } finally {
        if (queryObserver != null) {
          QueryObserverHolder.reset();
        }
      }
    } else {
      return DataCommandResult.createSelectInfoResult(null, null, -1, null,
          CliStrings.QUERY__MSG__QUERY_EMPTY, false);
    }
  }

  private String toJson(Object object) {
    if (object instanceof Undefined) {
      return "{\"Value\":\"UNDEFINED\"}";
    } else if (object instanceof PdxInstance)
      return pdxToJson((PdxInstance) object);
    else
      return JsonUtil.objectToJsonNestedChkCDep(object, NESTED_JSON_LENGTH);
  }

  private GfJsonObject getJSONForStruct(StructImpl impl, AtomicInteger ai) throws GfJsonException {
    String fields[] = impl.getFieldNames();
    Object[] values = impl.getFieldValues();
    GfJsonObject jsonObject = new GfJsonObject();
    for (int i = 0; i < fields.length; i++) {
      Object value = values[i];
      if (value != null) {
        if (JsonUtil.isPrimitiveOrWrapper(value.getClass())) {
          jsonObject.put(fields[i], value);
        } else {
          // jsonObject.put(fields[i], value.getClass().getCanonicalName());
          jsonObject.put(fields[i], toJson(value));
        }
      } else {
        jsonObject.put(fields[i], "null");
      }
    }
    return jsonObject;
  }

  @SuppressWarnings({"rawtypes"})
  public DataCommandResult remove(String key, String keyClass, String regionName,
      String removeAllKeys) {

    Cache cache = CacheFactory.getAnyInstance();

    if (regionName == null || regionName.isEmpty()) {
      return DataCommandResult.createRemoveResult(key, null, null,
          CliStrings.REMOVE__MSG__REGIONNAME_EMPTY, false);
    }

    boolean allKeysFlag = (removeAllKeys == null || removeAllKeys.isEmpty());
    if (allKeysFlag && (key == null || key.isEmpty())) {
      return DataCommandResult.createRemoveResult(key, null, null,
          CliStrings.REMOVE__MSG__KEY_EMPTY, false);
    }

    Region region = cache.getRegion(regionName);
    if (region == null) {
      return DataCommandResult.createRemoveInfoResult(key, null, null,
          CliStrings.format(CliStrings.REMOVE__MSG__REGION_NOT_FOUND, regionName), false);
    } else {
      if (removeAllKeys == null) {
        Object keyObject = null;
        try {
          keyObject = getClassObject(key, keyClass);
        } catch (ClassNotFoundException e) {
          return DataCommandResult.createRemoveResult(key, null, null,
              "ClassNotFoundException " + keyClass, false);
        } catch (IllegalArgumentException e) {
          return DataCommandResult.createRemoveResult(key, null, null,
              "Error in converting JSON " + e.getMessage(), false);
        }

        if (region.containsKey(keyObject)) {
          Object value = region.remove(keyObject);
          if (logger.isDebugEnabled())
            logger.debug("Removed key {} successfully", key);
          // return DataCommandResult.createRemoveResult(key, value, null, null);
          Object array[] = getJSONForNonPrimitiveObject(value);
          DataCommandResult result =
              DataCommandResult.createRemoveResult(key, array[1], null, null, true);
          if (array[0] != null)
            result.setValueClass((String) array[0]);
          return result;
        } else {
          return DataCommandResult.createRemoveInfoResult(key, null, null,
              CliStrings.REMOVE__MSG__KEY_NOT_FOUND_REGION, false);
        }
      } else {
        DataPolicy policy = region.getAttributes().getDataPolicy();
        if (!policy.withPartitioning()) {
          region.clear();
          if (logger.isDebugEnabled())
            logger.debug("Cleared all keys in the region - {}", regionName);
          return DataCommandResult.createRemoveInfoResult(key, null, null,
              CliStrings.format(CliStrings.REMOVE__MSG__CLEARED_ALL_CLEARS, regionName), true);
        } else {
          return DataCommandResult.createRemoveInfoResult(key, null, null,
              CliStrings.REMOVE__MSG__CLEAREALL_NOT_SUPPORTED_FOR_PARTITIONREGION, false);
        }
      }
    }
  }

  @SuppressWarnings({"rawtypes"})
  public DataCommandResult get(Object principal, String key, String keyClass, String valueClass,
      String regionName, Boolean loadOnCacheMiss) {

    Cache cache = CacheFactory.getAnyInstance();

    if (regionName == null || regionName.isEmpty()) {
      return DataCommandResult.createGetResult(key, null, null,
          CliStrings.GET__MSG__REGIONNAME_EMPTY, false);
    }

    if (key == null || key.isEmpty()) {
      return DataCommandResult.createGetResult(key, null, null, CliStrings.GET__MSG__KEY_EMPTY,
          false);
    }

    Region region = cache.getRegion(regionName);

    if (region == null) {
      if (logger.isDebugEnabled())
        logger.debug("Region Not Found - {}", regionName);
      return DataCommandResult.createGetResult(key, null, null,
          CliStrings.format(CliStrings.GET__MSG__REGION_NOT_FOUND, regionName), false);
    } else {
      Object keyObject = null;
      try {
        keyObject = getClassObject(key, keyClass);
      } catch (ClassNotFoundException e) {
        return DataCommandResult.createGetResult(key, null, null,
            "ClassNotFoundException " + keyClass, false);
      } catch (IllegalArgumentException e) {
        return DataCommandResult.createGetResult(key, null, null,
            "Error in converting JSON " + e.getMessage(), false);
      }

      // TODO determine whether the following conditional logic (assigned to 'doGet') is safer or
      // necessary
      // boolean doGet = (Boolean.TRUE.equals(loadOnCacheMiss) &&
      // region.getAttributes().getCacheLoader() != null);
      boolean doGet = Boolean.TRUE.equals(loadOnCacheMiss);

      if (doGet || region.containsKey(keyObject)) {
        Object value = region.get(keyObject);

        // run it through post processor. region.get will return the deserialized object already, so
        // we don't need to
        // deserialize it anymore to pass it to the postProcessor
        value = this.securityService.postProcess(principal, regionName, keyObject, value, false);

        if (logger.isDebugEnabled())
          logger.debug("Get for key {} value {}", key, value);
        // return DataCommandResult.createGetResult(key, value, null, null);
        Object array[] = getJSONForNonPrimitiveObject(value);
        if (value != null) {
          DataCommandResult result =
              DataCommandResult.createGetResult(key, array[1], null, null, true);
          if (array[0] != null)
            result.setValueClass((String) array[0]);
          return result;
        } else {
          return DataCommandResult.createGetResult(key, array[1], null, null, false);
        }
      } else {
        if (logger.isDebugEnabled())
          logger.debug("Key is not present in the region {}", regionName);
        return DataCommandResult.createGetInfoResult(key, null, null,
            CliStrings.GET__MSG__KEY_NOT_FOUND_REGION, false);
      }
    }
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  public DataCommandResult locateEntry(String key, String keyClass, String valueClass,
      String regionPath, boolean recursive) {

    Cache cache = CacheFactory.getAnyInstance();

    if (regionPath == null || regionPath.isEmpty()) {
      return DataCommandResult.createLocateEntryResult(key, null, null,
          CliStrings.LOCATE_ENTRY__MSG__REGIONNAME_EMPTY, false);
    }

    if (key == null || key.isEmpty()) {
      return DataCommandResult.createLocateEntryResult(key, null, null,
          CliStrings.LOCATE_ENTRY__MSG__KEY_EMPTY, false);
    }

    List listofRegionStartingwithRegionPath = new ArrayList();

    if (recursive) {
      // Recursively find the keys starting from the specified region path.
      List regionPaths = getAllRegionPaths(cache, true);
      for (int i = 0; i < regionPaths.size(); i++) {
        String path = regionPaths.get(i);
        if (path.startsWith(regionPath) || path.startsWith(Region.SEPARATOR + regionPath)) {
          Region targetRegion = cache.getRegion(path);
          listofRegionStartingwithRegionPath.add(targetRegion);
        }
      }
      if (listofRegionStartingwithRegionPath.size() == 0) {
        if (logger.isDebugEnabled())
          logger.debug("Region Not Found - {}", regionPath);
        return DataCommandResult.createLocateEntryResult(key, null, null,
            CliStrings.format(CliStrings.REMOVE__MSG__REGION_NOT_FOUND, regionPath), false);
      }
    } else {
      Region region = cache.getRegion(regionPath);
      if (region == null) {
        if (logger.isDebugEnabled())
          logger.debug("Region Not Found - {}", regionPath);
        return DataCommandResult.createLocateEntryResult(key, null, null,
            CliStrings.format(CliStrings.REMOVE__MSG__REGION_NOT_FOUND, regionPath), false);
      } else
        listofRegionStartingwithRegionPath.add(region);
    }

    Object keyObject = null;
    try {
      keyObject = getClassObject(key, keyClass);
    } catch (ClassNotFoundException e) {
      logger.fatal(e.getMessage(), e);
      return DataCommandResult.createLocateEntryResult(key, null, null,
          "ClassNotFoundException " + keyClass, false);
    } catch (IllegalArgumentException e) {
      logger.fatal(e.getMessage(), e);
      return DataCommandResult.createLocateEntryResult(key, null, null,
          "Error in converting JSON " + e.getMessage(), false);
    }

    Object value = null;
    DataCommandResult.KeyInfo keyInfo = null;
    keyInfo = new DataCommandResult.KeyInfo();
    DistributedMember member = cache.getDistributedSystem().getDistributedMember();
    keyInfo.setHost(member.getHost());
    keyInfo.setMemberId(member.getId());
    keyInfo.setMemberName(member.getName());

    for (Region region : listofRegionStartingwithRegionPath) {
      if (region instanceof PartitionedRegion) {
        // Following code is adaptation of which.java of old Gfsh
        PartitionedRegion pr = (PartitionedRegion) region;
        Region localRegion = PartitionRegionHelper.getLocalData((PartitionedRegion) region);
        value = localRegion.get(keyObject);
        if (value != null) {
          DistributedMember primaryMember =
              PartitionRegionHelper.getPrimaryMemberForKey(region, keyObject);
          int bucketId = pr.getKeyInfo(keyObject).getBucketId();
          boolean isPrimary = member == primaryMember;
          keyInfo.addLocation(new Object[] {region.getFullPath(), true,
              getJSONForNonPrimitiveObject(value)[1], isPrimary, "" + bucketId});
        } else {
          if (logger.isDebugEnabled())
            logger.debug("Key is not present in the region {}", regionPath);
          return DataCommandResult.createLocateEntryInfoResult(key, null, null,
              CliStrings.LOCATE_ENTRY__MSG__KEY_NOT_FOUND_REGION, false);
        }
      } else {
        if (region.containsKey(keyObject)) {
          value = region.get(keyObject);
          if (logger.isDebugEnabled())
            logger.debug("Get for key {} value {} in region {}", key, value, region.getFullPath());
          if (value != null)
            keyInfo.addLocation(new Object[] {region.getFullPath(), true,
                getJSONForNonPrimitiveObject(value)[1], false, null});
          else
            keyInfo.addLocation(new Object[] {region.getFullPath(), false, null, false, null});
        } else {
          if (logger.isDebugEnabled())
            logger.debug("Key is not present in the region {}", regionPath);
          keyInfo.addLocation(new Object[] {region.getFullPath(), false, null, false, null});
        }
      }
    }

    if (keyInfo.hasLocation()) {
      return DataCommandResult.createLocateEntryResult(key, keyInfo, null, null, true);
    } else {
      return DataCommandResult.createLocateEntryInfoResult(key, null, null,
          CliStrings.LOCATE_ENTRY__MSG__KEY_NOT_FOUND_REGION, false);
    }

  }

  @SuppressWarnings({"rawtypes"})
  public DataCommandResult put(String key, String value, boolean putIfAbsent, String keyClass,
      String valueClass, String regionName) {

    if (regionName == null || regionName.isEmpty()) {
      return DataCommandResult.createPutResult(key, null, null,
          CliStrings.PUT__MSG__REGIONNAME_EMPTY, false);
    }

    if (key == null || key.isEmpty()) {
      return DataCommandResult.createPutResult(key, null, null, CliStrings.PUT__MSG__KEY_EMPTY,
          false);
    }

    if (value == null || value.isEmpty()) {
      return DataCommandResult.createPutResult(key, null, null, CliStrings.PUT__MSG__VALUE_EMPTY,
          false);
    }

    Cache cache = CacheFactory.getAnyInstance();
    Region region = cache.getRegion(regionName);
    if (region == null) {
      return DataCommandResult.createPutResult(key, null, null,
          CliStrings.format(CliStrings.PUT__MSG__REGION_NOT_FOUND, regionName), false);
    } else {
      Object keyObject = null;
      Object valueObject = null;
      try {
        keyObject = getClassObject(key, keyClass);
      } catch (ClassNotFoundException e) {
        return DataCommandResult.createPutResult(key, null, null,
            "ClassNotFoundException " + keyClass, false);
      } catch (IllegalArgumentException e) {
        return DataCommandResult.createPutResult(key, null, null,
            "Error in converting JSON " + e.getMessage(), false);
      }

      try {
        valueObject = getClassObject(value, valueClass);
      } catch (ClassNotFoundException e) {
        return DataCommandResult.createPutResult(key, null, null,
            "ClassNotFoundException " + valueClass, false);
      }
      Object returnValue;
      if (putIfAbsent && region.containsKey(keyObject))
        returnValue = region.get(keyObject);
      else
        returnValue = region.put(keyObject, valueObject);
      Object array[] = getJSONForNonPrimitiveObject(returnValue);
      DataCommandResult result = DataCommandResult.createPutResult(key, array[1], null, null, true);
      if (array[0] != null)
        result.setValueClass((String) array[0]);
      return result;
    }
  }

  @SuppressWarnings({"rawtypes", "unchecked"})
  private Object getClassObject(String string, String klassString)
      throws ClassNotFoundException, IllegalArgumentException {
    if (klassString == null || klassString.isEmpty())
      return string;
    else {
      Object o = null;
      Class klass = ClassPathLoader.getLatest().forName(klassString);

      if (klass.equals(String.class))
        return string;

      if (JsonUtil.isPrimitiveOrWrapper(klass)) {
        try {
          if (klass.equals(Byte.class)) {
            o = Byte.parseByte(string);
            return o;
          } else if (klass.equals(Short.class)) {
            o = Short.parseShort(string);
            return o;
          } else if (klass.equals(Integer.class)) {
            o = Integer.parseInt(string);
            return o;
          } else if (klass.equals(Long.class)) {
            o = Long.parseLong(string);
            return o;
          } else if (klass.equals(Double.class)) {
            o = Double.parseDouble(string);
            return o;
          } else if (klass.equals(Boolean.class)) {
            o = Boolean.parseBoolean(string);
            return o;
          } else if (klass.equals(Float.class)) {
            o = Float.parseFloat(string);
            return o;
          }
          return o;
        } catch (NumberFormatException e) {
          throw new IllegalArgumentException(
              "Failed to convert input key to " + klassString + " Msg : " + e.getMessage());
        }
      }

      try {
        o = getObjectFromJson(string, klass);
        return o;
      } catch (IllegalArgumentException e) {
        throw e;
      }
    }
  }

  @SuppressWarnings({"rawtypes"})
  public static Object[] getJSONForNonPrimitiveObject(Object obj) {
    Object[] array = new Object[2];
    if (obj == null) {
      array[0] = null;
      array[1] = "";
      return array;
    } else {
      array[0] = obj.getClass().getCanonicalName();
      Class klass = obj.getClass();
      if (JsonUtil.isPrimitiveOrWrapper(klass)) {
        array[1] = obj;
      } else if (obj instanceof PdxInstance) {
        String str = pdxToJson((PdxInstance) obj);
        array[1] = str;
      } else {
        GfJsonObject object = new GfJsonObject(obj, true);
        Iterator keysIterator = object.keys();
        while (keysIterator.hasNext()) {
          String key = (String) keysIterator.next();
          Object value = object.get(key);
          if (GfJsonObject.isJSONKind(value)) {
            GfJsonObject jsonVal = new GfJsonObject(value);
            // System.out.println("Re-wrote inner object");
            try {
              if (jsonVal.has("type-class")) {
                object.put(key, jsonVal.get("type-class"));
              } else {
                // Its Map Value
                object.put(key, "a Map");
              }
            } catch (GfJsonException e) {
              throw new RuntimeException(e);
            }
          } else if (value instanceof JSONArray) {
            // Its a collection either a set or list
            try {
              object.put(key, "a Collection");
            } catch (GfJsonException e) {
              throw new RuntimeException(e);
            }
          }
        }
        String str = object.toString();
        array[1] = str;
      }
      return array;
    }
  }

  private static String pdxToJson(PdxInstance obj) {
    if (obj != null) {
      try {
        GfJsonObject json = new GfJsonObject();
        for (String field : obj.getFieldNames()) {
          Object fieldValue = obj.getField(field);
          if (fieldValue != null) {
            if (JsonUtil.isPrimitiveOrWrapper(fieldValue.getClass())) {
              json.put(field, fieldValue);
            } else {
              json.put(field, fieldValue.getClass());
            }
          }
        }
        return json.toString();
      } catch (GfJsonException e) {
        return null;
      }
    }
    return null;
  }

  public static  V getObjectFromJson(String json, Class klass) {
    String newString = json.replaceAll("'", "\"");
    if (newString.charAt(0) == '(') {
      int len = newString.length();
      StringBuilder sb = new StringBuilder();
      sb.append("{").append(newString.substring(1, len - 1)).append("}");
      newString = sb.toString();
    }
    V v = JsonUtil.jsonToObject(newString, klass);
    return v;
  }


  // Copied from RegionUtil of old Gfsh
  /**
   * Returns a sorted list of all region full paths found in the specified cache.
   * 
   * @param cache The cache to search.
   * @param recursive recursive search for sub-regions
   * @return Returns a sorted list of all region paths defined in the distributed system.
   */
  @SuppressWarnings({"rawtypes", "unchecked"})
  public static List getAllRegionPaths(Cache cache, boolean recursive) {
    ArrayList list = new ArrayList();
    if (cache == null) {
      return list;
    }

    // get a list of all root regions
    Set regions = cache.rootRegions();
    Iterator itor = regions.iterator();

    while (itor.hasNext()) {
      String regionPath = ((Region) itor.next()).getFullPath();

      Region region = cache.getRegion(regionPath);
      list.add(regionPath);
      Set subregionSet = region.subregions(true);
      if (recursive) {
        for (Iterator subIter = subregionSet.iterator(); subIter.hasNext();) {
          list.add(((Region) subIter.next()).getFullPath());
        }
      }
    }
    Collections.sort(list);
    return list;
  }

  private static DataCommandResult cachedResult = null;

  public static class SelectDisplayStep extends CLIMultiStepHelper.LocalStep {

    public SelectDisplayStep(Object[] arguments) {
      super(SELECT_STEP_DISPLAY, arguments);
    }

    @Override
    public Result exec() {
      boolean interactive = (Boolean) commandArguments[2];
      GfJsonObject args = CLIMultiStepHelper.getStepArgs();
      int startCount = args.getInt(DataCommandResult.QUERY_PAGE_START);
      int endCount = args.getInt(DataCommandResult.QUERY_PAGE_END);
      int rows = args.getInt(DataCommandResult.NUM_ROWS); // returns Zero if no rows added so it
                                                          // works.
      boolean flag = args.getBoolean(DataCommandResult.RESULT_FLAG);
      CommandResult commandResult = CLIMultiStepHelper.getDisplayResultFromArgs(args);
      Gfsh.println();
      while (commandResult.hasNextLine()) {
        Gfsh.println(commandResult.nextLine());
      }

      if (flag) {
        boolean paginationNeeded = (startCount < rows) && (endCount < rows) && interactive && flag;
        if (paginationNeeded) {
          while (true) {
            String message = ("Press n to move to next page, q to quit and p to previous page : ");
            try {
              String step = Gfsh.getCurrentInstance().interact(message);
              if ("n".equals(step)) {
                int nextStart = startCount + getPageSize();
                return CLIMultiStepHelper.createBannerResult(
                    new String[] {DataCommandResult.QUERY_PAGE_START,
                        DataCommandResult.QUERY_PAGE_END,},
                    new Object[] {nextStart, (nextStart + getPageSize())}, SELECT_STEP_MOVE);
              } else if ("p".equals(step)) {
                int nextStart = startCount - getPageSize();
                if (nextStart < 0)
                  nextStart = 0;
                return CLIMultiStepHelper.createBannerResult(
                    new String[] {DataCommandResult.QUERY_PAGE_START,
                        DataCommandResult.QUERY_PAGE_END},
                    new Object[] {nextStart, (nextStart + getPageSize())}, SELECT_STEP_MOVE);
              } else if ("q".equals(step))
                return CLIMultiStepHelper.createBannerResult(new String[] {}, new Object[] {},
                    SELECT_STEP_END);
              else
                Gfsh.println("Unknown option ");
            } catch (IOException e) {
              throw new RuntimeException(e);
            }
          }
        }
      }
      return CLIMultiStepHelper.createBannerResult(new String[] {}, new Object[] {},
          SELECT_STEP_END);
    }
  }


  public static class SelectMoveStep extends CLIMultiStepHelper.RemoteStep {

    private static final long serialVersionUID = 1L;

    public SelectMoveStep(Object[] arguments) {
      super(SELECT_STEP_MOVE, arguments);
    }

    @Override
    public Result exec() {
      GfJsonObject args = CLIMultiStepHelper.getStepArgs();
      int startCount = args.getInt(DataCommandResult.QUERY_PAGE_START);
      int endCount = args.getInt(DataCommandResult.QUERY_PAGE_END);
      return cachedResult.pageResult(startCount, endCount, SELECT_STEP_DISPLAY);
    }
  };

  public static class SelectExecStep extends CLIMultiStepHelper.RemoteStep {

    private static final long serialVersionUID = 1L;

    private static SecurityService securityService = SecurityService.getSecurityService();

    public SelectExecStep(Object[] arguments) {
      super(SELECT_STEP_EXEC, arguments);
    }

    @Override
    public Result exec() {
      String remainingQuery = (String) commandArguments[0];
      boolean interactive = (Boolean) commandArguments[2];
      DataCommandResult result = _select(remainingQuery);
      int endCount = 0;
      cachedResult = result;
      if (interactive) {
        endCount = getPageSize();
      } else {
        if (result.getSelectResult() != null)
          endCount = result.getSelectResult().size();
      }
      if (interactive)
        return result.pageResult(0, endCount, SELECT_STEP_DISPLAY);
      else
        return CLIMultiStepHelper.createBannerResult(new String[] {}, new Object[] {},
            SELECT_STEP_END);
    }

    /*
     * private int getLimit(CompiledValue compiledQuery) { return compiledQuery instanceof
     * CompiledSelect ? ((CompiledSelect)compiledQuery).getLimitValue(): -1; }
     */

    public DataCommandResult _select(String query) {
      Cache cache = CacheFactory.getAnyInstance();
      DataCommandResult dataResult = null;

      if (query == null || query.isEmpty()) {
        dataResult = DataCommandResult.createSelectInfoResult(null, null, -1, null,
            CliStrings.QUERY__MSG__QUERY_EMPTY, false);
        return dataResult;
      }

      // String query = querySB.toString().trim();
      Object array[] = DataCommands.replaceGfshEnvVar(query, CommandExecutionContext.getShellEnv());
      query = (String) array[1];
      query = addLimit(query);

      @SuppressWarnings("deprecation")
      QCompiler compiler = new QCompiler();
      Set regionsInQuery = null;
      try {
        CompiledValue compiledQuery = compiler.compileQuery(query);
        Set regions = new HashSet();
        compiledQuery.getRegionsInQuery(regions, null);

        // authorize data read on these regions
        for (String region : regions) {
          this.securityService.authorizeRegionRead(region);
        }

        regionsInQuery = Collections.unmodifiableSet(regions);
        if (regionsInQuery.size() > 0) {
          Set members =
              DataCommands.getQueryRegionsAssociatedMembers(regionsInQuery, cache, false);
          if (members != null && members.size() > 0) {
            DataCommandFunction function = new DataCommandFunction();
            DataCommandRequest request = new DataCommandRequest();
            request.setCommand(CliStrings.QUERY);
            request.setQuery(query);
            Subject subject = this.securityService.getSubject();
            if (subject != null) {
              request.setPrincipal((Serializable) subject.getPrincipal());
            }
            dataResult = DataCommands.callFunctionForRegion(request, function, members);
            dataResult.setInputQuery(query);
            return (dataResult);
          } else {
            return (dataResult =
                DataCommandResult.createSelectInfoResult(null, null, -1, null, CliStrings.format(
                    CliStrings.QUERY__MSG__REGIONS_NOT_FOUND, regionsInQuery.toString()), false));
          }
        } else {
          return (dataResult = DataCommandResult.createSelectInfoResult(null, null, -1, null,
              CliStrings.format(CliStrings.QUERY__MSG__INVALID_QUERY,
                  "Region mentioned in query probably missing /"),
              false));
        }
      } catch (QueryInvalidException qe) {
        logger.error("{} Failed Error {}", query, qe.getMessage(), qe);
        return (dataResult = DataCommandResult.createSelectInfoResult(null, null, -1, null,
            CliStrings.format(CliStrings.QUERY__MSG__INVALID_QUERY, qe.getMessage()), false));
      }
    }

    private String addLimit(String query) {
      if (StringUtils.containsIgnoreCase(query, " limit")
          || StringUtils.containsIgnoreCase(query, " count("))
        return query;
      return query + " limit " + getFetchSize();
    }
  };

  public static class SelectQuitStep extends CLIMultiStepHelper.RemoteStep {

    public SelectQuitStep(Object[] arguments) {
      super(SELECT_STEP_END, arguments);
    }

    private static final long serialVersionUID = 1L;

    @Override
    public Result exec() {
      boolean interactive = (Boolean) commandArguments[2];
      GfJsonObject args = CLIMultiStepHelper.getStepArgs();
      DataCommandResult dataResult = cachedResult;
      cachedResult = null;
      if (interactive)
        return CLIMultiStepHelper.createEmptyResult("END");
      else {
        CompositeResultData rd = dataResult.toSelectCommandResult();
        SectionResultData section = rd.addSection(CLIMultiStepHelper.STEP_SECTION);
        section.addData(CLIMultiStepHelper.NEXT_STEP_NAME, "END");
        return ResultBuilder.buildResult(rd);
      }
    }
  };

  public static int getPageSize() {
    int pageSize = -1;
    Map session = null;
    if (CliUtil.isGfshVM()) {
      session = Gfsh.getCurrentInstance().getEnv();
    } else {
      session = CommandExecutionContext.getShellEnv();
    }
    if (session != null) {
      String size = session.get(Gfsh.ENV_APP_COLLECTION_LIMIT);
      if (size == null || size.isEmpty())
        pageSize = Gfsh.DEFAULT_APP_COLLECTION_LIMIT;
      else
        pageSize = Integer.parseInt(size);
    }
    if (pageSize == -1)
      pageSize = Gfsh.DEFAULT_APP_COLLECTION_LIMIT;
    return pageSize;
  }

  private static int getFetchSize() {
    return CommandExecutionContext.getShellFetchSize();
  }


  public static String getLogMessage(QueryObserver observer, long startTime, String query) {
    String usedIndexesString = null;
    String rowCountString = null;
    float time = 0.0f;

    if (startTime > 0L) {
      time = (NanoTimer.getTime() - startTime) / 1.0e6f;
    }

    if (observer != null && observer instanceof IndexTrackingQueryObserver) {
      IndexTrackingQueryObserver indexObserver = (IndexTrackingQueryObserver) observer;
      Map usedIndexes = indexObserver.getUsedIndexes();
      indexObserver.reset();
      StringBuffer buf = new StringBuffer();
      buf.append(" indexesUsed(");
      buf.append(usedIndexes.size());
      buf.append(")");
      if (usedIndexes.size() > 0) {
        buf.append(":");
        for (Iterator itr = usedIndexes.entrySet().iterator(); itr.hasNext();) {
          Map.Entry entry = (Map.Entry) itr.next();
          buf.append(entry.getKey().toString() + entry.getValue());
          if (itr.hasNext()) {
            buf.append(",");
          }
        }
      }
      usedIndexesString = buf.toString();
    } else if (DefaultQuery.QUERY_VERBOSE) {
      usedIndexesString = " indexesUsed(NA due to other observer in the way: "
          + observer.getClass().getName() + ")";
    }

    /*
     * if (resultSize != -1){ rowCountString = " rowCount = " + resultSize + ";"; }
     */
    return "Query Executed" + (startTime > 0L ? " in " + time + " ms;" : ";")
        + (rowCountString != null ? rowCountString : "")
        + (usedIndexesString != null ? usedIndexesString : "")
    /* + " \"" + query + "\"" */;
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy