/*
 * 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.solr.common.util;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.apache.solr.client.solrj.cloud.DistribStateManager;
import org.apache.solr.client.solrj.cloud.autoscaling.VersionedData;
import org.apache.solr.client.solrj.impl.BinaryRequestWriter;
import org.apache.solr.common.IteratorWriter;
import org.apache.solr.common.LinkedHashMapWriter;
import org.apache.solr.common.MapWriter;
import org.apache.solr.common.MapWriterMap;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SpecProvider;
import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.common.cloud.ZkOperation;
import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.params.CommonParams;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.server.ByteBufferInputStream;
import org.noggit.CharArr;
import org.noggit.JSONParser;
import org.noggit.JSONWriter;
import org.noggit.ObjectBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.lang.invoke.MethodHandles;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Collections.singletonList;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableSet;
import static java.util.concurrent.TimeUnit.NANOSECONDS;

public class Utils {
  public static final Function NEW_HASHMAP_FUN = o -> new HashMap<>();
  public static final Function NEW_LINKED_HASHMAP_FUN = o -> new LinkedHashMap<>();
  public static final Function NEW_ATOMICLONG_FUN = o -> new AtomicLong();
  public static final Function NEW_ARRAYLIST_FUN = o -> new ArrayList<>();
  public static final Function NEW_SYNCHRONIZED_ARRAYLIST_FUN = o -> Collections.synchronizedList(new ArrayList<>());
  public static final Function NEW_HASHSET_FUN = o -> new HashSet<>();
  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

  public static Map getDeepCopy(Map map, int maxDepth) {
    return getDeepCopy(map, maxDepth, true, false);
  }

  public static Map getDeepCopy(Map map, int maxDepth, boolean mutable) {
    return getDeepCopy(map, maxDepth, mutable, false);
  }

  public static Map getDeepCopy(Map map, int maxDepth, boolean mutable, boolean sorted) {
    if (map == null) return null;
    if (maxDepth < 1) return map;
    Map copy;
    if (sorted) {
      copy = new TreeMap();
    } else {
      copy = map instanceof LinkedHashMap ? new LinkedHashMap(map.size()) : new HashMap(map.size());
    }
    for (Object o : map.entrySet()) {
      Map.Entry e = (Map.Entry) o;
      copy.put(e.getKey(), makeDeepCopy(e.getValue(), maxDepth, mutable, sorted));
    }
    return mutable ? copy : Collections.unmodifiableMap(copy);
  }

  public static void forEachMapEntry(Object o, String path, BiConsumer fun) {
    Object val = Utils.getObjectByPath(o, false, path);
    forEachMapEntry(val, fun);
  }

  public static void forEachMapEntry(Object o, List<String> path, BiConsumer fun) {
    Object val = Utils.getObjectByPath(o, false, path);
    forEachMapEntry(val, fun);
  }

  public static void forEachMapEntry(Object o, BiConsumer fun) {
    if (o instanceof MapWriter) {
      MapWriter m = (MapWriter) o;
      try {
        m.writeMap(new MapWriter.EntryWriter() {
          @Override
          public MapWriter.EntryWriter put(CharSequence k, Object v) {
            fun.accept(k, v);
            return this;
          }
        });
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    } else if (o instanceof Map) {
      ((Map) o).forEach((k, v) -> fun.accept(k, v));
    }
  }

  private static Object makeDeepCopy(Object v, int maxDepth, boolean mutable, boolean sorted) {
    if (v instanceof MapWriter && maxDepth > 1) {
      v = ((MapWriter) v).toMap(new LinkedHashMap<>());
    } else if (v instanceof IteratorWriter && maxDepth > 1) {
      v = ((IteratorWriter) v).toList(new ArrayList<>());
      if (sorted) {
        Collections.sort((List) v);
      }
    }

    if (v instanceof Map) {
      v = getDeepCopy((Map) v, maxDepth - 1, mutable, sorted);
    } else if (v instanceof Collection) {
      v = getDeepCopy((Collection) v, maxDepth - 1, mutable, sorted);
    }
    return v;
  }

  public static InputStream toJavabin(Object o) throws IOException {
    try (final JavaBinCodec jbc = new JavaBinCodec()) {
      BinaryRequestWriter.BAOS baos = new BinaryRequestWriter.BAOS();
      jbc.marshal(o, baos);
      return new ByteBufferInputStream(ByteBuffer.wrap(baos.getbuf(), 0, baos.size()));
    }
  }
  
  public static Object fromJavabin(byte[] bytes) throws IOException {
    try (JavaBinCodec jbc = new JavaBinCodec()) {
      return jbc.unmarshal(bytes);
    }
  }

  public static Collection getDeepCopy(Collection c, int maxDepth, boolean mutable) {
    return getDeepCopy(c, maxDepth, mutable, false);
  }

  public static Collection getDeepCopy(Collection c, int maxDepth, boolean mutable, boolean sorted) {
    if (c == null || maxDepth < 1) return c;
    Collection result = c instanceof Set ?
        (sorted ? new TreeSet() : new HashSet()) : new ArrayList();
    for (Object o : c) result.add(makeDeepCopy(o, maxDepth, mutable, sorted));
    if (sorted && (result instanceof List)) {
      Collections.sort((List) result);
    }
    return mutable ? result : result instanceof Set ? unmodifiableSet((Set) result) : unmodifiableList((List) result);
  }

  public static void writeJson(Object o, OutputStream os, boolean indent) throws IOException {
    writeJson(o, new OutputStreamWriter(os, UTF_8), indent)
        .flush();
  }

  public static Writer writeJson(Object o, Writer writer, boolean indent) throws IOException {
    try (SolrJSONWriter jsonWriter = new SolrJSONWriter(writer)) {
      jsonWriter.setIndent(indent)
      .writeObj(o);
    }
    return writer;
  }

  /**
   * Given long integer, return an integer or a long integer
   * depending upon whether it overflows the integer range.
   */
  static public Number intIfNotOverflown(long n) {
    if (((int) n) == n){
      return Integer.valueOf((int)n);
    } else {
      return Long.valueOf(n);
    }
  }

  private static class MapWriterJSONWriter extends JSONWriter {

    public MapWriterJSONWriter(CharArr out, int indentSize) {
      super(out, indentSize);
    }

    @Override
    public void handleUnknownClass(Object o) {
      if (o instanceof MapWriter) {
        Map m = ((MapWriter) o).toMap(new LinkedHashMap<>());
        write(m);
      } else {
        super.handleUnknownClass(o);
      }
    }
  }

  public static byte[] toJSON(Object o) {
    if (o == null) return new byte[0];
    CharArr out = new CharArr();
    if (!(o instanceof List) && !(o instanceof Map)) {
      if (o instanceof MapWriter) {
        o = ((MapWriter) o).toMap(new LinkedHashMap<>());
      } else if (o instanceof IteratorWriter) {
        o = ((IteratorWriter) o).toList(new ArrayList<>());
      }
    }
    new MapWriterJSONWriter(out, 2).write(o); // indentation by default
    return toUTF8(out);
  }

  public static String toJSONString(Object o) {
    return new String(toJSON(o), StandardCharsets.UTF_8);
  }

  public static byte[] toUTF8(CharArr out) {
    byte[] arr = new byte[out.size() * 3];
    int nBytes = ByteUtils.UTF16toUTF8(out, 0, out.size(), arr, 0);
    return Arrays.copyOf(arr, nBytes);
  }

  public static Object fromJSON(byte[] utf8) {
    return fromJSON(utf8, 0, utf8.length);
  }
  
  public static Object fromJSON(byte[] utf8, int offset, int length) {
    // convert directly from bytes to chars
    // and parse directly from that instead of going through
    // intermediate strings or readers
    CharArr chars = new CharArr();
    ByteUtils.UTF8toUTF16(utf8, offset, length, chars);
    JSONParser parser = new JSONParser(chars.getArray(), chars.getStart(), chars.length());
    parser.setFlags(parser.getFlags() |
        JSONParser.ALLOW_MISSING_COLON_COMMA_BEFORE_OBJECT |
        JSONParser.OPTIONAL_OUTER_BRACES);
    try {
      return STANDARDOBJBUILDER.apply(parser).getValStrict();
    } catch (IOException e) {
      throw new RuntimeException(e); // should never happen w/o using real IO
    }
  }

  public static Map<String, Object> makeMap(Object... keyVals) {
    return makeMap(false, keyVals);
  }

  public static Map<String, Object> makeMap(boolean skipNulls, Object... keyVals) {
    if ((keyVals.length & 0x01) != 0) {
      throw new IllegalArgumentException("arguments should be key,value");
    }
    Map<String, Object> propMap = new LinkedHashMap<>(keyVals.length >> 1);
    for (int i = 0; i < keyVals.length; i += 2) {
      Object keyVal = keyVals[i + 1];
      if (skipNulls && keyVal == null) continue;
      propMap.put(keyVals[i].toString(), keyVal);
    }
    return propMap;
  }

  public static Object fromJSON(InputStream is) {
    return fromJSON(new InputStreamReader(is, UTF_8));
  }

  public static Object fromJSON(Reader is) {
    try {
      return STANDARDOBJBUILDER.apply(getJSONParser(is)).getValStrict();
    } catch (IOException e) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Parse error", e);
    }
  }

  public static final Function<JSONParser, ObjectBuilder> STANDARDOBJBUILDER = jsonParser -> {
    try {
      return new ObjectBuilder(jsonParser);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  };
  public static final Function<JSONParser, ObjectBuilder> MAPWRITEROBJBUILDER = jsonParser -> {
    try {
      return new ObjectBuilder(jsonParser) {
        @Override
        public Object newObject() {
          return new LinkedHashMapWriter();
        }
      };
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  };

  public static final Function<JSONParser, ObjectBuilder> MAPOBJBUILDER = jsonParser -> {
    try {
      return new ObjectBuilder(jsonParser) {
        @Override
        public Object newObject() {
          return new HashMap();
        }
      };
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  };

  /**
   * Util function to convert {@link Object} to {@link String}
   * Specially handles {@link Date} to string conversion
   */
  public static final Function<Object, String> OBJECT_TO_STRING =
      obj -> ((obj instanceof Date) ? Objects.toString(((Date) obj).toInstant()) : Objects.toString(obj));

  public static Object fromJSON(InputStream is, Function<JSONParser, ObjectBuilder> objBuilderProvider) {
    try {
      return objBuilderProvider.apply(getJSONParser((new InputStreamReader(is, StandardCharsets.UTF_8)))).getValStrict();
    } catch (IOException e) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Parse error", e);
    }
  }

  public static Object fromJSONResource(String resourceName) {
    final URL resource = Utils.class.getClassLoader().getResource(resourceName);
    if (null == resource) {
      throw new IllegalArgumentException("invalid resource name: " + resourceName);
    }
    try (InputStream stream = resource.openStream()) {
      return fromJSON(stream);
    } catch (IOException e) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
          "Resource error: " + e.getMessage(), e);
    }
  }

  public static JSONParser getJSONParser(Reader reader) {
    JSONParser parser = new JSONParser(reader);
    parser.setFlags(parser.getFlags() |
        JSONParser.ALLOW_MISSING_COLON_COMMA_BEFORE_OBJECT |
        JSONParser.OPTIONAL_OUTER_BRACES);
    return parser;
  }

  public static Object fromJSONString(String json) {
    try {
      return STANDARDOBJBUILDER.apply(getJSONParser(new StringReader(json))).getValStrict();
    } catch (Exception e) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Parse error : " + json, e);
    }
  }

  public static Object getObjectByPath(Object root, boolean onlyPrimitive, String hierarchy) {
    if (hierarchy == null) return getObjectByPath(root, onlyPrimitive, singletonList(null));
    List<String> parts = StrUtils.splitSmart(hierarchy, '/', true);
    return getObjectByPath(root, onlyPrimitive, parts);
  }

  public static boolean setObjectByPath(Object root, String hierarchy, Object value) {
    List<String> parts = StrUtils.splitSmart(hierarchy, '/', true);
    return setObjectByPath(root, parts, value);
  }

  public static boolean setObjectByPath(Object root, List<String> hierarchy, Object value) {
    if (root == null) return false;
    if (!isMapLike(root)) throw new RuntimeException("must be a Map or NamedList");
    Object obj = root;
    for (int i = 0; i < hierarchy.size(); i++) {
      int idx = -2; //-1 means append to list, -2 means not found
      String s = hierarchy.get(i);
      if (s.endsWith("]")) {
        Matcher matcher = ARRAY_ELEMENT_INDEX.matcher(s);
        if (matcher.find()) {
          s = matcher.group(1);
          idx = Integer.parseInt(matcher.group(2));
        }
      }
      if (i < hierarchy.size() - 1) {
        Object o = getVal(obj, s, -1);
        if (o == null) return false;
        if (idx > -1) {
          List l = (List) o;
          o = idx < l.size() ? l.get(idx) : null;
        }
        if (!isMapLike(o)) return false;
        obj = o;
      } else {
        if (idx == -2) {
          if (obj instanceof NamedList) {
            NamedList namedList = (NamedList) obj;
            int location = namedList.indexOf(s, 0);
            if (location == -1) namedList.add(s, value);
            else namedList.setVal(location, value);
          } else if (obj instanceof Map) {
            ((Map) obj).put(s, value);
          }
          return true;
        } else {
          Object v = getVal(obj, s, -1);
          if (v instanceof List) {
            List list = (List) v;
            if (idx == -1) {
              list.add(value);
            } else {
              if (idx < list.size()) list.set(idx, value);
              else return false;
            }
            return true;
          } else {
            return false;
          }
        }
      }
    }

    return false;

  }


  public static Object getObjectByPath(Object root, boolean onlyPrimitive, List<String> hierarchy) {
    if (root == null) return null;
    if (!isMapLike(root)) return null;
    Object obj = root;
    for (int i = 0; i < hierarchy.size(); i++) {
      int idx = -1;
      String s = hierarchy.get(i);
      if (s != null && s.endsWith("]")) {
        Matcher matcher = ARRAY_ELEMENT_INDEX.matcher(s);
        if (matcher.find()) {
          s = matcher.group(1);
          idx = Integer.parseInt(matcher.group(2));
        }
      }
      if (i < hierarchy.size() - 1) {
        Object o = getVal(obj, s, -1);
        if (o == null) return null;
        if (idx > -1) {
          if (o instanceof MapWriter) {
            o = getVal(o, null, idx);
          } else if (o instanceof Map) {
            o = getVal(new MapWriterMap((Map) o), null, idx);
          } else {
            List l = (List) o;
            o = idx < l.size() ? l.get(idx) : null;
          }
        }
        if (!isMapLike(o)) return null;
        obj = o;
      } else {
        Object val = getVal(obj, s, -1);
        if (val == null) return null;
        if (idx > -1) {
          if (val instanceof IteratorWriter) {
            val = getValueAt((IteratorWriter) val, idx);
          } else {
            List l = (List) val;
            val = idx < l.size() ? l.get(idx) : null;
          }
        }
        if (onlyPrimitive && isMapLike(val)) {
          return null;
        }
        return val;
      }
    }

    return false;
  }


  private static Object getValueAt(IteratorWriter iteratorWriter, int idx) {
    Object[] result = new Object[1];
    try {
      iteratorWriter.writeIter(new IteratorWriter.ItemWriter() {
        int i = -1;

        @Override
        public IteratorWriter.ItemWriter add(Object o) {
          ++i;
          if (i > idx) return this;
          if (i == idx) result[0] = o;
          return this;
        }
      });
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    return result[0];

  }

  static class MapWriterEntry<V> extends AbstractMap.SimpleEntry<CharSequence, V> implements MapWriter, Map.Entry<CharSequence, V> {
    MapWriterEntry(CharSequence key, V value) {
      super(key, value);
    }

    @Override
    public void writeMap(EntryWriter ew) throws IOException {
      ew.put("key", getKey());
      ew.put("value", getValue());
    }

  }

  private static boolean isMapLike(Object o) {
    return o instanceof Map || o instanceof NamedList || o instanceof MapWriter;
  }

  private static Object getVal(Object obj, String key, int idx) {
    if (obj instanceof MapWriter) {
      Object[] result = new Object[1];
      try {
        ((MapWriter) obj).writeMap(new MapWriter.EntryWriter() {
          int count = -1;

          @Override
          public MapWriter.EntryWriter put(CharSequence k, Object v) {
            if (result[0] != null) return this;
            if (idx < 0) {
              if (k.equals(key)) result[0] = v;
            } else {
              if (++count == idx) result[0] = new MapWriterEntry(k, v);
            }
            return this;
          }
        });
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
      return result[0];
    } else if (obj instanceof Map) return ((Map) obj).get(key);
    else throw new RuntimeException("must be a NamedList or Map");
  }

  /**
   * If the passed entity has content, make sure it is fully
   * read and closed.
   *
   * @param entity to consume or null
   */
  public static void consumeFully(HttpEntity entity) {
    if (entity != null) {
      try {
        // make sure the stream is full read
        readFully(entity.getContent());
      } catch (UnsupportedOperationException e) {
        // nothing to do then
      } catch (IOException e) {
        // quiet
      } finally {
        // close the stream
        EntityUtils.consumeQuietly(entity);
      }
    }
  }

  /**
   * Make sure the InputStream is fully read.
   *
   * @param is to read
   * @throws IOException on problem with IO
   */
  private static void readFully(InputStream is) throws IOException {
    is.skip(is.available());
    while (is.read() != -1) {
    }
  }

  public static Map<String, Object> getJson(DistribStateManager distribStateManager, String path) throws InterruptedException, IOException, KeeperException {
    VersionedData data = null;
    try {
      data = distribStateManager.getData(path);
    } catch (KeeperException.NoNodeException | NoSuchElementException e) {
      return Collections.emptyMap();
    }
    if (data == null || data.getData() == null || data.getData().length == 0) return Collections.emptyMap();
    return (Map<String, Object>) Utils.fromJSON(data.getData());
  }

  /**
   * Assumes data in ZooKeeper is a JSON string, deserializes it and returns as a Map
   *
   * @param zkClient        the zookeeper client
   * @param path            the path to the znode being read
   * @param retryOnConnLoss whether to retry the operation automatically on connection loss, see {@link org.apache.solr.common.cloud.ZkCmdExecutor#retryOperation(ZkOperation)}
   * @return a Map if the node exists and contains valid JSON or an empty map if znode does not exist or has a null data
   */
  public static Map<String, Object> getJson(SolrZkClient zkClient, String path, boolean retryOnConnLoss) throws KeeperException, InterruptedException {
    try {
      byte[] bytes = zkClient.getData(path, null, null, retryOnConnLoss);
      if (bytes != null && bytes.length > 0) {
        return (Map<String, Object>) Utils.fromJSON(bytes);
      }
    } catch (KeeperException.NoNodeException e) {
      return Collections.emptyMap();
    }
    return Collections.emptyMap();
  }

  public static final Pattern ARRAY_ELEMENT_INDEX = Pattern
      .compile("(\\S*?)\\[([-]?\\d+)\\]");

  public static SpecProvider getSpec(final String name) {
    return () -> {
      return ValidatingJsonMap.parse(CommonParams.APISPEC_LOCATION + name + ".json", CommonParams.APISPEC_LOCATION);
    };
  }

  public static String parseMetricsReplicaName(String collectionName, String coreName) {
    if (collectionName == null || !coreName.startsWith(collectionName)) {
      return null;
    } else {
      // split "collection1_shard1_1_replica1" into parts
      if (coreName.length() > collectionName.length()) {
        String str = coreName.substring(collectionName.length() + 1);
        int pos = str.lastIndexOf("_replica");
        if (pos == -1) { // ?? no _replicaN part ??
          return str;
        } else {
          return str.substring(pos + 1);
        }
      } else {
        return null;
      }
    }
  }

  /**
   * Applies one json over other. The 'input' is applied over the sink
   * The values in input isapplied over the values in 'sink' . If a value is 'null'
   * that value is removed from sink
   *
   * @param sink  the original json object to start with. Ensure that this Map is mutable
   * @param input the json with new values
   * @return whether there was any change made to sink or not.
   */
  public static boolean mergeJson(Map<String, Object> sink, Map<String, Object> input) {
    boolean isModified = false;
    for (Map.Entry<String, Object> e : input.entrySet()) {
      if (sink.get(e.getKey()) != null) {
        Object sinkVal = sink.get(e.getKey());
        if (e.getValue() == null) {
          sink.remove(e.getKey());
          isModified = true;
        } else {
          if (e.getValue() instanceof Map) {
            Map<String, Object> mapInputVal = (Map<String, Object>) e.getValue();
            if (sinkVal instanceof Map) {
              if (mergeJson((Map<String, Object>) sinkVal, mapInputVal)) isModified = true;
            } else {
              sink.put(e.getKey(), mapInputVal);
              isModified = true;
            }
          } else {
            sink.put(e.getKey(), e.getValue());
            isModified = true;
          }

        }
      } else if (e.getValue() != null) {
        sink.put(e.getKey(), e.getValue());
        isModified = true;
      }

    }

    return isModified;
  }

  public static String getBaseUrlForNodeName(final String nodeName, String urlScheme) {
    final int _offset = nodeName.indexOf("_");
    if (_offset < 0) {
      throw new IllegalArgumentException("nodeName does not contain expected '_' separator: " + nodeName);
    }
    final String hostAndPort = nodeName.substring(0, _offset);
    try {
      final String path = URLDecoder.decode(nodeName.substring(1 + _offset), "UTF-8");
      return urlScheme + "://" + hostAndPort + (path.isEmpty() ? "" : ("/" + path));
    } catch (UnsupportedEncodingException e) {
      throw new IllegalStateException("JVM Does not seem to support UTF-8", e);
    }
  }

  public static long time(TimeSource timeSource, TimeUnit unit) {
    return unit.convert(timeSource.getTimeNs(), TimeUnit.NANOSECONDS);
  }

  public static long timeElapsed(TimeSource timeSource, long start, TimeUnit unit) {
    return unit.convert(timeSource.getTimeNs() - NANOSECONDS.convert(start, unit), NANOSECONDS);
  }

  public static String getMDCNode() {
    String s = MDC.get(ZkStateReader.NODE_NAME_PROP);
    if (s == null) return null;
    if (s.startsWith("n:")) {
      return s.substring(2);
    } else {
      return null;
    }
  }

  public static <T> T handleExp(Logger logger, T def, Callable<T> c) {
    try {
      return c.call();
    } catch (Exception e) {
      logger.error(e.getMessage(), e);
    }
    return def;
  }

  public interface InputStreamConsumer<T> {

    T accept(InputStream is) throws IOException;

  }

  public static final InputStreamConsumer<?> JAVABINCONSUMER = is -> new JavaBinCodec().unmarshal(is);
  public static final InputStreamConsumer<?> JSONCONSUMER = Utils::fromJSON;

  public static InputStreamConsumer<ByteBuffer> newBytesConsumer(int maxSize) {
    return is -> {
      try (BinaryRequestWriter.BAOS bos = new BinaryRequestWriter.BAOS()) {
        long sz = 0;
        int next = is.read();
        while (next > -1) {
          if (++sz > maxSize) throw new BufferOverflowException();
          bos.write(next);
          next = is.read();
        }
        bos.flush();
        return ByteBuffer.wrap(bos.getbuf(), 0, bos.size());
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    };

  }


  public static <T> T executeGET(HttpClient client, String url, InputStreamConsumer<T> consumer) throws SolrException {
    T result = null;
    HttpGet httpGet = new HttpGet(url);
    HttpResponse rsp = null;
    try {
      rsp = client.execute(httpGet);
    } catch (IOException e) {
      log.error("Error in request to url : " + url, e);
      throw new SolrException(SolrException.ErrorCode.UNKNOWN, "error sending request");
    }
    int statusCode = rsp.getStatusLine().getStatusCode();
    if (statusCode != 200) {
      try {
        log.error("Failed a request to: {}, status: {}, body: {}", url, rsp.getStatusLine(), EntityUtils.toString(rsp.getEntity(), StandardCharsets.UTF_8));
      } catch (IOException e) {
        log.error("could not print error", e);
      }
      throw new SolrException(SolrException.ErrorCode.getErrorCode(statusCode), "Unknown error");
    }
    HttpEntity entity = rsp.getEntity();
    try {
      InputStream is = entity.getContent();
      if (consumer != null) {

        result = consumer.accept(is);
      }
    } catch (IOException e) {
      throw new SolrException(SolrException.ErrorCode.UNKNOWN, e);
    } finally {
      Utils.consumeFully(entity);
    }
    return result;
  }


}
