private static Optional<CoprocessorDescriptor> toCoprocessorDescriptor(String spec) {
    Matcher matcher = CP_HTD_ATTR_VALUE_PATTERN.matcher(spec);
    if (matcher.matches()) {
      // jar file path can be empty if the cp class can be loaded
      // from class loader.
      String path = matcher.group(1).trim().isEmpty() ? null : matcher.group(1).trim();
      String className = matcher.group(2).trim();
      if (className.isEmpty()) {
        return Optional.empty();
      }
      String priorityStr = matcher.group(3).trim();
      int priority =
        priorityStr.isEmpty() ? Coprocessor.PRIORITY_USER : Integer.parseInt(priorityStr);
      String cfgSpec = null;
      try {
        cfgSpec = matcher.group(4);
      } catch (IndexOutOfBoundsException ex) {
        // ignore
      }
      Map<String, String> ourConf = new TreeMap<>();
      if (cfgSpec != null && !cfgSpec.trim().equals("|")) {
        cfgSpec = cfgSpec.substring(cfgSpec.indexOf('|') + 1);
        Matcher m = CP_HTD_ATTR_VALUE_PARAM_PATTERN.matcher(cfgSpec);
        while (m.find()) {
          ourConf.put(m.group(1), m.group(2));
        }
      }
      return Optional.of(CoprocessorDescriptorBuilder.newBuilder(className).setJarPath(path)
        .setPriority(priority).setProperties(ourConf).build());
    }
    return Optional.empty();
  }
This method is mostly intended for internal use. However, it it also relied on by hbase-shell
for backwards compatibility.
hbase-client/src/main/java/org/apache/hadoop/hbase/client/TableDescriptorBuilder.java