sonatype-lift[bot] commented on code in PR #1683:
URL: https://github.com/apache/solr/pull/1683#discussion_r1216021070


##########
solr/core/src/java/org/apache/solr/handler/admin/api/SyncShardAPI.java:
##########
@@ -17,52 +17,99 @@
 
 package org.apache.solr.handler.admin.api;
 
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
-import static org.apache.solr.common.params.CollectionAdminParams.COLLECTION;
-import static org.apache.solr.common.params.CollectionParams.ACTION;
-import static org.apache.solr.common.params.CoreAdminParams.SHARD;
-import static org.apache.solr.handler.ClusterAPI.wrapParams;
+import static 
org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2;
+import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
+import static org.apache.solr.common.cloud.ZkStateReader.SHARD_ID_PROP;
 import static 
org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM;
 
-import java.util.HashMap;
-import java.util.Map;
-import org.apache.solr.api.Command;
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.api.PayloadObj;
-import org.apache.solr.client.solrj.request.beans.SyncShardPayload;
-import org.apache.solr.common.params.CollectionParams;
-import org.apache.solr.handler.admin.CollectionsHandler;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import javax.inject.Inject;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.request.CoreAdminRequest;
+import org.apache.solr.common.cloud.ClusterState;
+import org.apache.solr.common.cloud.DocCollection;
+import org.apache.solr.common.cloud.ZkCoreNodeProps;
+import org.apache.solr.common.cloud.ZkNodeProps;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.handler.api.V2ApiUtils;
+import org.apache.solr.jersey.PermissionName;
+import org.apache.solr.jersey.SolrJerseyResponse;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
 
 /**
  * V2 API for triggering a shard-sync operation within a particular collection 
and shard.
  *
  * <p>This API (POST /v2/collections/collectionName/shards/shardName 
{'sync-shard': {}}) is
  * analogous to the v1 /admin/collections?action=SYNCSHARD command.
- *
- * @see SyncShardPayload
  */
-@EndPoint(
-    path = {"/c/{collection}/shards/{shard}", 
"/collections/{collection}/shards/{shard}"},
-    method = POST,
-    permission = COLL_EDIT_PERM)
-public class SyncShardAPI {
-  private static final String V2_SYNC_SHARD_CMD = "sync-shard";
+@Path("/collections/{collectionName}/shards/{shardName}/sync-shard")
+public class SyncShardAPI extends AdminAPIBase {
+
+  @Inject
+  public SyncShardAPI(
+      CoreContainer coreContainer,
+      SolrQueryRequest solrQueryRequest,
+      SolrQueryResponse solrQueryResponse) {
+    super(coreContainer, solrQueryRequest, solrQueryResponse);
+  }
+
+  @POST
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, 
BINARY_CONTENT_TYPE_V2})
+  @PermissionName(COLL_EDIT_PERM)
+  public SolrJerseyResponse syncShard(
+      @PathParam("collectionName") String collectionName, 
@PathParam("shardName") String shardName)
+      throws Exception {
+    final SolrJerseyResponse response = 
instantiateJerseyResponse(SolrJerseyResponse.class);
+    ensureRequiredParameterProvided(COLLECTION_PROP, collectionName);
+    ensureRequiredParameterProvided(SHARD_ID_PROP, shardName);
+    fetchAndValidateZooKeeperAwareCoreContainer();
+    recordCollectionForLogAndTracing(collectionName, solrQueryRequest);
+
+    doSyncShard(collectionName, shardName);
+
+    return response;
+  }
+
+  private void doSyncShard(String extCollectionName, String shardName)
+      throws IOException, SolrServerException {
+    String collection = 
coreContainer.getAliases().resolveSimpleAlias(extCollectionName);
+
+    ClusterState clusterState = 
coreContainer.getZkController().getClusterState();
 
-  private final CollectionsHandler collectionsHandler;
+    DocCollection docCollection = clusterState.getCollection(collection);
+    ZkNodeProps leaderProps = docCollection.getLeader(shardName);
+    ZkCoreNodeProps nodeProps = new ZkCoreNodeProps(leaderProps);
 
-  public SyncShardAPI(CollectionsHandler collectionsHandler) {
-    this.collectionsHandler = collectionsHandler;
+    try (SolrClient client =
+        new HttpSolrClient.Builder(nodeProps.getBaseUrl())

Review Comment:
   <picture><img alt="16% of developers fix this issue" 
src="https://lift.sonatype.com/api/commentimage/fixrate/16/display.svg";></picture>
   
   <b>*NULL_DEREFERENCE:</b>*  object `nodeProps.nodeProps` last assigned on 
line 90 could be null and is dereferenced by call to `getBaseUrl()` at line 93.
   
   ---
   
   <details><summary>ℹ️ Expand to see all <b>@sonatype-lift</b> 
commands</summary>
   
   You can reply with the following commands. For example, reply with 
***@sonatype-lift ignoreall*** to leave out all findings.
   | **Command** | **Usage** |
   | ------------- | ------------- |
   | `@sonatype-lift ignore` | Leave out the above finding from this PR |
   | `@sonatype-lift ignoreall` | Leave out all the existing findings from this 
PR |
   | `@sonatype-lift exclude <file\|issue\|path\|tool>` | Exclude specified 
`file\|issue\|path\|tool` from Lift findings by updating your config.toml file |
   
   **Note:** When talking to LiftBot, you need to **refresh** the page to see 
its response.
   <sub>[Click here](https://github.com/apps/sonatype-lift/installations/new) 
to add LiftBot to another repo.</sub></details>
   
   



##########
solr/core/src/java/org/apache/solr/handler/admin/api/ForceLeaderAPI.java:
##########
@@ -17,52 +17,166 @@
 
 package org.apache.solr.handler.admin.api;
 
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
-import static org.apache.solr.common.params.CollectionAdminParams.COLLECTION;
-import static org.apache.solr.common.params.CollectionParams.ACTION;
-import static org.apache.solr.common.params.CoreAdminParams.SHARD;
-import static org.apache.solr.handler.ClusterAPI.wrapParams;
+import static 
org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2;
+import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
+import static org.apache.solr.common.cloud.ZkStateReader.SHARD_ID_PROP;
 import static 
org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM;
 
-import java.util.HashMap;
-import java.util.Map;
-import org.apache.solr.api.Command;
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.api.PayloadObj;
-import org.apache.solr.client.solrj.request.beans.ForceLeaderPayload;
-import org.apache.solr.common.params.CollectionParams;
-import org.apache.solr.handler.admin.CollectionsHandler;
+import java.lang.invoke.MethodHandles;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.inject.Inject;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import org.apache.solr.cloud.ZkController;
+import org.apache.solr.cloud.ZkShardTerms;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.cloud.ClusterState;
+import org.apache.solr.common.cloud.DocCollection;
+import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.Slice;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.handler.api.V2ApiUtils;
+import org.apache.solr.jersey.PermissionName;
+import org.apache.solr.jersey.SolrJerseyResponse;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * V2 API for triggering a leader election on a particular collection and 
shard.
  *
- * <p>This API (POST /v2/collections/collectionName/shards/shardName 
{'force-leader': {}}) is
- * analogous to the v1 /admin/collections?action=FORCELEADER command.
- *
- * @see ForceLeaderPayload
+ * <p>This API (POST 
/v2/collections/collectionName/shards/shardName/force-leader) is analogous to
+ * the v1 /admin/collections?action=FORCELEADER command.
  */
-@EndPoint(
-    path = {"/c/{collection}/shards/{shard}", 
"/collections/{collection}/shards/{shard}"},
-    method = POST,
-    permission = COLL_EDIT_PERM)
-public class ForceLeaderAPI {
-  private static final String V2_FORCE_LEADER_CMD = "force-leader";
+@Path("/collections/{collectionName}/shards/{shardName}/force-leader")
+public class ForceLeaderAPI extends AdminAPIBase {
+  private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  @Inject
+  public ForceLeaderAPI(
+      CoreContainer coreContainer,
+      SolrQueryRequest solrQueryRequest,
+      SolrQueryResponse solrQueryResponse) {
+    super(coreContainer, solrQueryRequest, solrQueryResponse);
+  }
+
+  @POST
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, 
BINARY_CONTENT_TYPE_V2})
+  @PermissionName(COLL_EDIT_PERM)
+  public SolrJerseyResponse forceLeader(
+      @PathParam("collectionName") String collectionName,
+      @PathParam("shardName") String shardName) {
+    final SolrJerseyResponse response = 
instantiateJerseyResponse(SolrJerseyResponse.class);
+    ensureRequiredParameterProvided(COLLECTION_PROP, collectionName);
+    ensureRequiredParameterProvided(SHARD_ID_PROP, shardName);
+    fetchAndValidateZooKeeperAwareCoreContainer();
+    recordCollectionForLogAndTracing(collectionName, solrQueryRequest);
+
+    doForceLeaderElection(collectionName, shardName);
+    return response;
+  }
 
-  private final CollectionsHandler collectionsHandler;
+  public static void invokeFromV1Params(
+      CoreContainer coreContainer, SolrQueryRequest request, SolrQueryResponse 
response) {
+    final var api = new ForceLeaderAPI(coreContainer, request, response);
+    final var params = request.getParams();
+    params.required().check(COLLECTION_PROP, SHARD_ID_PROP);
 
-  public ForceLeaderAPI(CollectionsHandler collectionsHandler) {
-    this.collectionsHandler = collectionsHandler;
+    V2ApiUtils.squashIntoSolrResponseWithoutHeader(
+        response, api.forceLeader(params.get(COLLECTION_PROP), 
params.get(SHARD_ID_PROP)));
   }
 
-  @Command(name = V2_FORCE_LEADER_CMD)
-  public void forceLeader(PayloadObj<ForceLeaderPayload> obj) throws Exception 
{
-    final Map<String, Object> addedV1Params = new HashMap<>();
-    final Map<String, String> pathParams = 
obj.getRequest().getPathTemplateValues();
-    addedV1Params.put(ACTION, 
CollectionParams.CollectionAction.FORCELEADER.toLower());
-    addedV1Params.put(COLLECTION, pathParams.get(COLLECTION));
-    addedV1Params.put(SHARD, pathParams.get(SHARD));
+  private void doForceLeaderElection(String extCollectionName, String 
shardName) {
+    ZkController zkController = coreContainer.getZkController();
+    ClusterState clusterState = zkController.getClusterState();
+    String collectionName =
+        
zkController.zkStateReader.getAliases().resolveSimpleAlias(extCollectionName);
+
+    log.info("Force leader invoked, state: {}", clusterState);
+    DocCollection collection = clusterState.getCollection(collectionName);
+    Slice slice = collection.getSlice(shardName);
+    if (slice == null) {
+      throw new SolrException(
+          SolrException.ErrorCode.BAD_REQUEST,
+          "No shard with name " + shardName + " exists for collection " + 
collectionName);
+    }
+
+    try (ZkShardTerms zkShardTerms =
+        new ZkShardTerms(collectionName, slice.getName(), 
zkController.getZkClient())) {
+      // if an active replica is the leader, then all is fine already
+      Replica leader = slice.getLeader();
+      if (leader != null && leader.getState() == Replica.State.ACTIVE) {
+        throw new SolrException(
+            SolrException.ErrorCode.SERVER_ERROR,
+            "The shard already has an active leader. Force leader is not 
applicable. State: "
+                + slice);
+      }
+
+      final Set<String> liveNodes = clusterState.getLiveNodes();
+      List<Replica> liveReplicas =
+          slice.getReplicas().stream()
+              .filter(rep -> liveNodes.contains(rep.getNodeName()))
+              .collect(Collectors.toList());
+      boolean shouldIncreaseReplicaTerms =
+          liveReplicas.stream()
+              .noneMatch(
+                  rep ->
+                      zkShardTerms.registered(rep.getName())
+                          && zkShardTerms.canBecomeLeader(rep.getName()));
+      // we won't increase replica's terms if exist a live replica with term 
equals to leader
+      if (shouldIncreaseReplicaTerms) {
+        // TODO only increase terms of replicas less out-of-sync
+        liveReplicas.stream()
+            .filter(rep -> zkShardTerms.registered(rep.getName()))
+            // TODO should this all be done at once instead of increasing each 
replica individually?
+            .forEach(rep -> zkShardTerms.setTermEqualsToLeader(rep.getName()));
+      }
+
+      // Wait till we have an active leader
+      boolean success = false;
+      for (int i = 0; i < 9; i++) {
+        Thread.sleep(5000);
+        clusterState = coreContainer.getZkController().getClusterState();
+        collection = clusterState.getCollection(collectionName);
+        slice = collection.getSlice(shardName);
+        if (slice.getLeader() != null && slice.getLeader().getState() == 
Replica.State.ACTIVE) {
+          success = true;
+          break;
+        }
+        log.warn(
+            "Force leader attempt {}. Waiting 5 secs for an active leader. 
State of the slice: {}",
+            (i + 1),
+            slice); // nowarn
+      }
 
-    collectionsHandler.handleRequestBody(
-        wrapParams(obj.getRequest(), addedV1Params), obj.getResponse());
+      if (success) {
+        log.info(
+            "Successfully issued FORCELEADER command for collection: {}, 
shard: {}",
+            collectionName,
+            shardName);
+      } else {
+        log.info(

Review Comment:
   <picture><img alt="14% of developers fix this issue" 
src="https://lift.sonatype.com/api/commentimage/fixrate/14/display.svg";></picture>
   
   
<b>*[CRLF_INJECTION_LOGS](https://find-sec-bugs.github.io/bugs.htm#CRLF_INJECTION_LOGS):</b>*
  This use of org/slf4j/Logger.info(Ljava/lang/String;[Ljava/lang/Object;)V 
might be used to include CRLF characters into log messages
   
   ---
   
   <details><summary>ℹ️ Expand to see all <b>@sonatype-lift</b> 
commands</summary>
   
   You can reply with the following commands. For example, reply with 
***@sonatype-lift ignoreall*** to leave out all findings.
   | **Command** | **Usage** |
   | ------------- | ------------- |
   | `@sonatype-lift ignore` | Leave out the above finding from this PR |
   | `@sonatype-lift ignoreall` | Leave out all the existing findings from this 
PR |
   | `@sonatype-lift exclude <file\|issue\|path\|tool>` | Exclude specified 
`file\|issue\|path\|tool` from Lift findings by updating your config.toml file |
   
   **Note:** When talking to LiftBot, you need to **refresh** the page to see 
its response.
   <sub>[Click here](https://github.com/apps/sonatype-lift/installations/new) 
to add LiftBot to another repo.</sub></details>
   
   



##########
solr/core/src/java/org/apache/solr/handler/admin/api/ForceLeaderAPI.java:
##########
@@ -17,52 +17,166 @@
 
 package org.apache.solr.handler.admin.api;
 
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
-import static org.apache.solr.common.params.CollectionAdminParams.COLLECTION;
-import static org.apache.solr.common.params.CollectionParams.ACTION;
-import static org.apache.solr.common.params.CoreAdminParams.SHARD;
-import static org.apache.solr.handler.ClusterAPI.wrapParams;
+import static 
org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2;
+import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
+import static org.apache.solr.common.cloud.ZkStateReader.SHARD_ID_PROP;
 import static 
org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM;
 
-import java.util.HashMap;
-import java.util.Map;
-import org.apache.solr.api.Command;
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.api.PayloadObj;
-import org.apache.solr.client.solrj.request.beans.ForceLeaderPayload;
-import org.apache.solr.common.params.CollectionParams;
-import org.apache.solr.handler.admin.CollectionsHandler;
+import java.lang.invoke.MethodHandles;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.inject.Inject;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import org.apache.solr.cloud.ZkController;
+import org.apache.solr.cloud.ZkShardTerms;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.cloud.ClusterState;
+import org.apache.solr.common.cloud.DocCollection;
+import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.Slice;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.handler.api.V2ApiUtils;
+import org.apache.solr.jersey.PermissionName;
+import org.apache.solr.jersey.SolrJerseyResponse;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * V2 API for triggering a leader election on a particular collection and 
shard.
  *
- * <p>This API (POST /v2/collections/collectionName/shards/shardName 
{'force-leader': {}}) is
- * analogous to the v1 /admin/collections?action=FORCELEADER command.
- *
- * @see ForceLeaderPayload
+ * <p>This API (POST 
/v2/collections/collectionName/shards/shardName/force-leader) is analogous to
+ * the v1 /admin/collections?action=FORCELEADER command.
  */
-@EndPoint(
-    path = {"/c/{collection}/shards/{shard}", 
"/collections/{collection}/shards/{shard}"},
-    method = POST,
-    permission = COLL_EDIT_PERM)
-public class ForceLeaderAPI {
-  private static final String V2_FORCE_LEADER_CMD = "force-leader";
+@Path("/collections/{collectionName}/shards/{shardName}/force-leader")
+public class ForceLeaderAPI extends AdminAPIBase {
+  private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  @Inject
+  public ForceLeaderAPI(
+      CoreContainer coreContainer,
+      SolrQueryRequest solrQueryRequest,
+      SolrQueryResponse solrQueryResponse) {
+    super(coreContainer, solrQueryRequest, solrQueryResponse);
+  }
+
+  @POST
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, 
BINARY_CONTENT_TYPE_V2})
+  @PermissionName(COLL_EDIT_PERM)
+  public SolrJerseyResponse forceLeader(
+      @PathParam("collectionName") String collectionName,
+      @PathParam("shardName") String shardName) {
+    final SolrJerseyResponse response = 
instantiateJerseyResponse(SolrJerseyResponse.class);
+    ensureRequiredParameterProvided(COLLECTION_PROP, collectionName);
+    ensureRequiredParameterProvided(SHARD_ID_PROP, shardName);
+    fetchAndValidateZooKeeperAwareCoreContainer();
+    recordCollectionForLogAndTracing(collectionName, solrQueryRequest);
+
+    doForceLeaderElection(collectionName, shardName);
+    return response;
+  }
 
-  private final CollectionsHandler collectionsHandler;
+  public static void invokeFromV1Params(
+      CoreContainer coreContainer, SolrQueryRequest request, SolrQueryResponse 
response) {
+    final var api = new ForceLeaderAPI(coreContainer, request, response);
+    final var params = request.getParams();
+    params.required().check(COLLECTION_PROP, SHARD_ID_PROP);
 
-  public ForceLeaderAPI(CollectionsHandler collectionsHandler) {
-    this.collectionsHandler = collectionsHandler;
+    V2ApiUtils.squashIntoSolrResponseWithoutHeader(
+        response, api.forceLeader(params.get(COLLECTION_PROP), 
params.get(SHARD_ID_PROP)));
   }
 
-  @Command(name = V2_FORCE_LEADER_CMD)
-  public void forceLeader(PayloadObj<ForceLeaderPayload> obj) throws Exception 
{
-    final Map<String, Object> addedV1Params = new HashMap<>();
-    final Map<String, String> pathParams = 
obj.getRequest().getPathTemplateValues();
-    addedV1Params.put(ACTION, 
CollectionParams.CollectionAction.FORCELEADER.toLower());
-    addedV1Params.put(COLLECTION, pathParams.get(COLLECTION));
-    addedV1Params.put(SHARD, pathParams.get(SHARD));
+  private void doForceLeaderElection(String extCollectionName, String 
shardName) {
+    ZkController zkController = coreContainer.getZkController();
+    ClusterState clusterState = zkController.getClusterState();
+    String collectionName =
+        
zkController.zkStateReader.getAliases().resolveSimpleAlias(extCollectionName);
+
+    log.info("Force leader invoked, state: {}", clusterState);
+    DocCollection collection = clusterState.getCollection(collectionName);
+    Slice slice = collection.getSlice(shardName);
+    if (slice == null) {
+      throw new SolrException(
+          SolrException.ErrorCode.BAD_REQUEST,
+          "No shard with name " + shardName + " exists for collection " + 
collectionName);
+    }
+
+    try (ZkShardTerms zkShardTerms =
+        new ZkShardTerms(collectionName, slice.getName(), 
zkController.getZkClient())) {
+      // if an active replica is the leader, then all is fine already
+      Replica leader = slice.getLeader();
+      if (leader != null && leader.getState() == Replica.State.ACTIVE) {
+        throw new SolrException(
+            SolrException.ErrorCode.SERVER_ERROR,
+            "The shard already has an active leader. Force leader is not 
applicable. State: "
+                + slice);
+      }
+
+      final Set<String> liveNodes = clusterState.getLiveNodes();
+      List<Replica> liveReplicas =
+          slice.getReplicas().stream()
+              .filter(rep -> liveNodes.contains(rep.getNodeName()))
+              .collect(Collectors.toList());
+      boolean shouldIncreaseReplicaTerms =
+          liveReplicas.stream()
+              .noneMatch(
+                  rep ->
+                      zkShardTerms.registered(rep.getName())
+                          && zkShardTerms.canBecomeLeader(rep.getName()));
+      // we won't increase replica's terms if exist a live replica with term 
equals to leader
+      if (shouldIncreaseReplicaTerms) {
+        // TODO only increase terms of replicas less out-of-sync
+        liveReplicas.stream()
+            .filter(rep -> zkShardTerms.registered(rep.getName()))
+            // TODO should this all be done at once instead of increasing each 
replica individually?
+            .forEach(rep -> zkShardTerms.setTermEqualsToLeader(rep.getName()));
+      }
+
+      // Wait till we have an active leader
+      boolean success = false;
+      for (int i = 0; i < 9; i++) {
+        Thread.sleep(5000);
+        clusterState = coreContainer.getZkController().getClusterState();
+        collection = clusterState.getCollection(collectionName);
+        slice = collection.getSlice(shardName);
+        if (slice.getLeader() != null && slice.getLeader().getState() == 
Replica.State.ACTIVE) {
+          success = true;
+          break;
+        }
+        log.warn(
+            "Force leader attempt {}. Waiting 5 secs for an active leader. 
State of the slice: {}",
+            (i + 1),
+            slice); // nowarn
+      }
 
-    collectionsHandler.handleRequestBody(
-        wrapParams(obj.getRequest(), addedV1Params), obj.getResponse());
+      if (success) {
+        log.info(

Review Comment:
   <picture><img alt="14% of developers fix this issue" 
src="https://lift.sonatype.com/api/commentimage/fixrate/14/display.svg";></picture>
   
   
<b>*[CRLF_INJECTION_LOGS](https://find-sec-bugs.github.io/bugs.htm#CRLF_INJECTION_LOGS):</b>*
  This use of 
org/slf4j/Logger.info(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V 
might be used to include CRLF characters into log messages
   
   ---
   
   <details><summary>ℹ️ Expand to see all <b>@sonatype-lift</b> 
commands</summary>
   
   You can reply with the following commands. For example, reply with 
***@sonatype-lift ignoreall*** to leave out all findings.
   | **Command** | **Usage** |
   | ------------- | ------------- |
   | `@sonatype-lift ignore` | Leave out the above finding from this PR |
   | `@sonatype-lift ignoreall` | Leave out all the existing findings from this 
PR |
   | `@sonatype-lift exclude <file\|issue\|path\|tool>` | Exclude specified 
`file\|issue\|path\|tool` from Lift findings by updating your config.toml file |
   
   **Note:** When talking to LiftBot, you need to **refresh** the page to see 
its response.
   <sub>[Click here](https://github.com/apps/sonatype-lift/installations/new) 
to add LiftBot to another repo.</sub></details>
   
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@solr.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscr...@solr.apache.org
For additional commands, e-mail: issues-h...@solr.apache.org

Reply via email to